private static IPolyline CreatePolyline([NotNull] SubClosedCurve connected, bool zAware) { IPolyline result = connected.GetGeometry(); ((IZAware)result).ZAware = zAware; return(result); }
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); }
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); }
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)); } }