Exemple #1
0
        private static IPolyline CreatePolyline([NotNull] SubClosedCurve connected,
                                                bool zAware)
        {
            IPolyline result = connected.GetGeometry();

            ((IZAware)result).ZAware = zAware;

            return(result);
        }
Exemple #2
0
        private int PartCoincidenceErrors([NotNull] IRow row0,
                                          [NotNull] IRow row1,
                                          [NotNull] SubClosedCurve connected,
                                          double near,
                                          double minLength,
                                          bool isDisjoint = false)
        {
            double length = connected.GetLength();

            if (length <= minLength)
            {
                return(NoError);
            }

            IGeometry shape0 = ((IFeature)row0).Shape;
            IGeometry shape1 = ((IFeature)row1).Shape;

            bool isWithinFeature = row0 == row1;
            bool zAware          = ((IZAware)shape0).ZAware &&
                                   ((IZAware)shape1).ZAware;

            IPolyline errorGeometry = CreatePolyline(connected, zAware);

            // NOTE there can be multiple paths in the error geometry, when the curve touches itself
            // see https://issuetracker02.eggits.net/browse/COM-47

            var errorCount = 0;

            string shapeFieldName = ((IFeatureClass)((IFeature)row0).Class).ShapeFieldName;

            foreach (IPath errorPath in GeometryUtils.GetPaths(errorGeometry))
            {
                if (errorPath.Length < minLength)
                {
                    continue;
                }

                IPolyline errorPartGeometry = CreateErrorGeometry(errorPath, zAware);

                ISpatialReference    spatialReference = shape0.SpatialReference;
                ICollection <object> values;
                string description = UsesConstantNearTolerance
                                                             ? GetShortDescription(minLength, errorPartGeometry,
                                                                                   spatialReference, out values)
                                                             : GetExtendedDescription(minLength, near,
                                                                                      errorPartGeometry,
                                                                                      spatialReference,
                                                                                      shape0, shape1,
                                                                                      isDisjoint, isWithinFeature,
                                                                                      out values);

                errorCount += isWithinFeature
                                                      ? ReportError(description, errorGeometry,
                                                                    Codes[Code.NearlyCoincidentSection_WithinFeature],
                                                                    shapeFieldName, values,
                                                                    row0)
                                                      : ReportError(description, errorGeometry,
                                                                    Codes[Code.NearlyCoincidentSection_BetweenFeatures],
                                                                    shapeFieldName, values,
                                                                    row0, row1);
            }

            return(errorCount);
        }
Exemple #3
0
        private int CheckPartCoincidence([NotNull] IRow row0, [NotNull] IRow row1,
                                         [NotNull] IList <SubClosedCurve> nearCurves,
                                         [NotNull] IList <SubClosedCurve> coincidentCurves,
                                         bool nearSelf,
                                         double near,
                                         double connectedMinLength, double disjointMinLength)
        {
            if (nearCurves.Count == 0)
            {
                return(NoError);
            }

            IList <SubClosedCurve> disjointCurves  = new List <SubClosedCurve>(nearCurves.Count);
            IList <SubClosedCurve> connectedCurves = new List <SubClosedCurve>(nearCurves.Count);

            // Find and handle disjoint subcurves
            foreach (SubClosedCurve nearCurve in nearCurves)
            {
                if (nearSelf)
                {
                    connectedCurves.Add(nearCurve);
                    continue;
                }

                SubClosedCurve within = null;
                foreach (SubClosedCurve candidate in coincidentCurves)
                {
                    if (nearCurve.IsWithin(candidate))
                    {
                        within = candidate;
                        break;
                    }
                }

                if (within == null)
                {
                    disjointCurves.Add(nearCurve);
                }
                else
                {
                    connectedCurves.Add(nearCurve);
                }
            }

            var errorCount = 0;

            foreach (SubClosedCurve disjointCurve in disjointCurves)
            {
                errorCount += PartCoincidenceErrors(row0, row1, disjointCurve,
                                                    near, disjointMinLength,
                                                    true);
            }

            // Handle connected curves

            double coincidenceMinLength = _coincidenceTolerance * connectedMinLength / near;

            coincidentCurves = GetLongSubcurves(coincidentCurves, coincidenceMinLength);
            foreach (SubClosedCurve coincidentCurve in coincidentCurves)
            {
                SubClosedCurve surround = null;
                foreach (SubClosedCurve candidate in connectedCurves)
                {
                    if (candidate.IsWithin(coincidentCurve))
                    {
                        surround = candidate;
                        break;
                    }
                }

                if (surround == null)
                {
                    // surrounding curve is < _connectedMinLength and was filtered away.
                    continue;
                }

                connectedCurves.Remove(surround);

                if (surround.IsCompleteClosedPart())
                {
                    if (coincidentCurve.IsCompleteClosedPart())
                    {
                        continue;
                    }

                    var rest = new SubClosedCurve(surround.BaseGeometry,
                                                  surround.PartIndex, coincidentCurve.EndFullIndex,
                                                  coincidentCurve.StartFullIndex);
                    if (rest.GetLength() >= connectedMinLength)
                    {
                        connectedCurves.Add(rest);
                    }

                    continue;
                }

                var pre = new SubClosedCurve(surround.BaseGeometry,
                                             surround.PartIndex, surround.StartFullIndex,
                                             coincidentCurve.StartFullIndex);
                if (pre.GetLength() >= connectedMinLength)
                {
                    connectedCurves.Add(pre);
                }

                var post = new SubClosedCurve(surround.BaseGeometry,
                                              surround.PartIndex, coincidentCurve.EndFullIndex,
                                              surround.EndFullIndex);
                if (post.GetLength() >= connectedMinLength)
                {
                    connectedCurves.Add(post);
                }
            }

            foreach (SubClosedCurve connectedCurve in connectedCurves)
            {
                errorCount += PartCoincidenceErrors(row0, row1, connectedCurve,
                                                    near, connectedMinLength);
            }

            return(errorCount);
        }
Exemple #4
0
        private void AddSegment([NotNull] IFeature feature,
                                [NotNull] IIndexedSegments geom,
                                [NotNull] IList <Subcurve> standardConnectedList,
                                [NotNull] IList <Subcurve> nearSelfConnectedList,
                                [NotNull] SegmentPart segPart,
                                double connectedMinLength,
                                double nearSquared)
        {
            Subcurve         current       = null;
            IList <Subcurve> connectedList = standardConnectedList;

            SegmentProxy neighbor = segPart.NearSelf;

            if (neighbor != null)
            {
                // Get the distance between the parts that are near
                double d0        = double.MaxValue;
                int    partIndex = segPart.PartIndex;

                if (geom.IsPartClosed(partIndex) || segPart.SegmentIndex > neighbor.SegmentIndex)
                {
                    if (segPart.PartIndex == neighbor.PartIndex)
                    // TODO revise; workaround to avoid exception (invalid index)
                    {
                        // raw estimate for distance betwenn segPart and neighborPart
                        // this estimate is too small, because not the entire part of neighbor is near segPart
                        var curve = new SubClosedCurve(geom, partIndex,
                                                       neighbor.SegmentIndex + 1,
                                                       segPart.FullMin);
                        d0 = curve.GetLength();
                        if (d0 < connectedMinLength)
                        {
                            double d0Max = d0 + neighbor.Length;
                            if (d0Max > connectedMinLength)
                            {
                                // closer investigation necessary
                                double min;
                                double max;
                                GetClosePart(neighbor, geom, segPart, nearSquared, Is3D,
                                             out min, out max);

                                d0 = d0 + (1 - max) * neighbor.Length;
                            }                     // else segPart is definitly near neighbor
                        }                         //else segPart is definitly not near neighbor
                    }
                }

                if (geom.IsPartClosed(partIndex) || segPart.SegmentIndex < neighbor.SegmentIndex)
                {
                    if (segPart.PartIndex == neighbor.PartIndex)
                    // TODO revise; workaround to avoid exception (invalid index)
                    {
                        var curve = new SubClosedCurve(geom, partIndex,
                                                       segPart.FullMax,
                                                       neighbor.SegmentIndex);

                        double d0Min = curve.GetLength();
                        if (d0Min < connectedMinLength)
                        {
                            double d0Max = d0Min + neighbor.Length;
                            if (d0Max > connectedMinLength)
                            {
                                // closer investigation necessary
                                double min;
                                double max;
                                GetClosePart(neighbor, geom, segPart, nearSquared, Is3D,
                                             out min, out max);

                                d0Min = d0Min + min * neighbor.Length;
                            }                     //else segPart is definitly near neighbor
                        }                         // else segPart is definitly not near neighbor

                        d0 = Math.Min(d0, d0Min);
                    }
                }

                if (d0 < connectedMinLength)
                {
                    connectedList = nearSelfConnectedList;
                }
            }

            if (connectedList.Count > 0)
            {
                current = connectedList[connectedList.Count - 1];
            }

            if (current != null)
            {
                if (current.PartIndex != segPart.PartIndex)
                {
                    current = null;
                }
                else if (current.EndFullIndex < segPart.FullMin)
                {
                    current = null;
                }
            }

            if (current == null)
            {
                current = new Subcurve(geom, segPart.PartIndex, segPart.SegmentIndex,
                                       segPart.MinFraction, segPart.SegmentIndex,
                                       segPart.MaxFraction);
                connectedList.Add(current);
            }
            else
            {
                if (current.EndFullIndex < segPart.FullMax)
                {
                    current.EndSegmentIndex = segPart.SegmentIndex;
                    current.EndFraction     = segPart.MaxFraction;
                }
            }
        }
            public IEnumerable <ConnectedLinesEx> CleanupNotReportedPairs(
                ConnectedLinesEx errorCandidate)
            {
                if (_notReportedCondition == null)
                {
                    yield return(errorCandidate);

                    yield break;
                }

                AllNotReportedPairConditions notReportedCondition = _notReportedCondition;

                ConnectedLines      subConnected       = null;
                SegmentNeighbors    subNeighbors       = null;
                SegmentPairRelation subRelevantSegment = null;
                int minRelationIndex = SegmentRelationsToCheck.Count;

                foreach (
                    ConnectedSegmentsSubpart allParts in errorCandidate.Line.BaseSegments)
                {
                    IEnumerable <SegmentPartWithNeighbor> neighbors;
                    double limit;
                    Func <SegmentPartWithNeighbor, double, bool>   checkLimit;
                    Func <SegmentPartWithNeighbor, double, double> getLimit;
                    Func <double, bool> checkEndLimit;
                    if (allParts.FullStartFraction > allParts.FullEndFraction)
                    {
                        var sorted =
                            new List <SegmentPartWithNeighbor>(GetNeighbors(allParts));
                        sorted.Sort((x, y) => - x.FullMax.CompareTo(y.FullMax));
                        neighbors = sorted;

                        limit         = allParts.FullMaxFraction;
                        checkLimit    = (x, l) => x.FullMax < l;
                        getLimit      = (x, l) => Math.Min(l, x.FullMin);
                        checkEndLimit = l => l > allParts.FullMinFraction;
                    }
                    else
                    {
                        neighbors     = GetNeighbors(allParts);
                        limit         = allParts.FullMinFraction;
                        checkLimit    = (x, l) => x.FullMin > l;
                        getLimit      = (x, l) => Math.Max(l, x.FullMax);
                        checkEndLimit = l => l < allParts.FullMaxFraction;
                    }

                    ConnectedSegmentsSubpart subSubparts = null;
                    foreach (SegmentPartWithNeighbor segmentPart in neighbors)
                    {
                        if (notReportedCondition.IsFulfilled(
                                allParts.BaseFeature, allParts.TableIndex,
                                segmentPart.NeighborFeature,
                                segmentPart.NeighborTableIndex))
                        {
                            continue;
                        }

                        if (checkLimit(segmentPart, limit) && subConnected != null)
                        {
                            subConnected.RelevantSegment =
                                errorCandidate.Line.RelevantSegment;
                            yield return(GetClean(subConnected, errorCandidate));

                            subConnected = null;
                        }

                        if (subConnected == null)
                        {
                            subConnected =
                                new ConnectedLines(new List <ConnectedSegmentsSubpart>());
                            subRelevantSegment = null;
                            subSubparts        = null;
                        }

                        if (subRelevantSegment == null ||
                            segmentPart.MinRelationIndex <
                            subRelevantSegment.Segment.MinRelationIndex)
                        {
                            subRelevantSegment = new SegmentPairRelation(
                                segmentPart,
                                SegmentRelationsToCheck[segmentPart.MinRelationIndex]);
                        }

                        if (subSubparts == null)
                        {
                            subNeighbors = new SegmentNeighbors(new SegmentPartComparer());

                            var subCurve = new SubClosedCurve(allParts.ConnectedCurve.BaseGeometry,
                                                              allParts.ConnectedCurve.PartIndex,
                                                              segmentPart.FullMin,
                                                              segmentPart.FullMax);

                            subSubparts = new ConnectedSegmentsSubpart(
                                allParts, subNeighbors, subCurve);

                            subConnected.BaseSegments.Add(subSubparts);
                        }

                        SegmentParts parts;
                        var          key = new SegmentPart(
                            Assert.NotNull(segmentPart.SegmentProxy), 0, 1, true);
                        if (!subNeighbors.TryGetValue(key, out parts))
                        {
                            parts = new SegmentParts();
                            subNeighbors.Add(key, parts);
                        }

                        parts.Add(segmentPart);

                        int relationIndex = segmentPart.MinRelationIndex;
                        if (relationIndex < minRelationIndex)
                        {
                            minRelationIndex = relationIndex;
                        }

                        limit = getLimit(segmentPart, limit);
                    }

                    if (checkEndLimit(limit) && subConnected != null)
                    {
                        subConnected.RelevantSegment = errorCandidate.Line.RelevantSegment;
                        yield return(GetClean(subConnected, errorCandidate));

                        subConnected = null;
                    }
                }

                if (subConnected != null)
                {
                    subConnected.RelevantSegment = errorCandidate.Line.RelevantSegment;
                    yield return(GetClean(subConnected, errorCandidate));
                }
            }