private void QueryCompareGeometryCoordinates(VertexIndex atVertexIndex, [NotNull] IPoint result) { if (_compareGeometry.GeometryType == esriGeometryType.esriGeometryMultipoint) { ((IPointCollection)_compareGeometry).QueryPoint(atVertexIndex.PartIndex, result); return; } var geometryCollection = _compareGeometry as IGeometryCollection; if (geometryCollection == null || atVertexIndex.PartIndex == 0) { ((IPointCollection)_compareGeometry).QueryPoint( atVertexIndex.VertexIndexInPart, result); return; } if (!(_compareGeometry is ISegmentCollection)) { throw new NotImplementedException( string.Format("Not implemented for geometry type {0}", _compareGeometry.GeometryType)); } // This makes a big difference for geometries with hundreds of parts (proved by CanCalculateDifferenceInHugeLockergestein()) int globalIndex = GetGlobalVertexIndex( atVertexIndex, GetCompareGeometryPartStartIndex(geometryCollection)); ((IPointCollection)_compareGeometry).QueryPoint(globalIndex, result); }
private ISegment GetBaseSegment(VertexIndex atFromVertexIndex) { var fromSegments = _baseGeometry as ISegmentCollection; if (fromSegments == null) { throw new NotImplementedException( "Cannot get base segments, no segment collection"); } var geometryCollection = _baseGeometry as IGeometryCollection; if (geometryCollection == null || atFromVertexIndex.PartIndex == 0) { return(fromSegments.Segment[atFromVertexIndex.VertexIndexInPart]); } if (!(_baseGeometry is ISegmentCollection)) { throw new NotImplementedException( string.Format("Not implemented for geometry type {0}", _compareGeometry.GeometryType)); } // This makes a big difference for geometries with hundreds of parts (such as the one // used in CanCalculateDifferenceInHugeLockergestein()) int globalSegmentIndex = GetGlobalSegmentIndex( atFromVertexIndex, GetBaseGeometryPartStartIndex(geometryCollection)); ISegment segment = fromSegments.Segment[globalSegmentIndex]; return(segment); }
private static int GetGlobalVertexIndex(VertexIndex atVertexIndex, IList <int> partStartVertxIndexes) { int globalIndex = partStartVertxIndexes[atVertexIndex.PartIndex] + atVertexIndex.VertexIndexInPart; return(globalIndex); }
private static int GetGlobalSegmentIndex( VertexIndex fromVertexIndex, IList <int> partStartVertxIndexes) { // each part has one segment less than vertices: int globalIndex = partStartVertxIndexes[fromVertexIndex.PartIndex] - fromVertexIndex.PartIndex + fromVertexIndex.VertexIndexInPart; return(globalIndex); }
private Dictionary <WKSPointZ, VertexIndex> CreateCoordinateDictionary( [NotNull] IGeometry geometry, bool compare3D, out Dictionary <WKSPointZ, List <VertexIndex> > duplicateCoordinates) { double zTolerance = compare3D ? _zTolerance : double.NaN; var comparer = new WKSPointZComparer(_xyTolerance, zTolerance, geometry.SpatialReference); var coordinateDictionary = new Dictionary <WKSPointZ, VertexIndex>(((IPointCollection)geometry).PointCount, comparer); WKSPointZ[] pointArray = GeometryUtils.GetWKSPointZs(geometry, true); // NOTE: there can be ambiguity if two different segments have the same point (rings, boundary loops) // or in the 2D case if two points differ only in Z. Hence duplicates must be explicitly managed. var currentPartIdx = 0; var currentIndexInPart = 0; var geometryCollection = geometry as IGeometryCollection; int partCount = geometryCollection?.GeometryCount ?? 1; duplicateCoordinates = new Dictionary <WKSPointZ, List <VertexIndex> >(partCount); // one duplicate for each ring IPointCollection currentPartPoints = geometryCollection == null ? (IPointCollection)geometry : null; foreach (WKSPointZ wksPointZ in pointArray) { if (currentPartPoints == null && geometryCollection != null) { currentPartPoints = geometryCollection.get_Geometry(currentPartIdx) as IPointCollection; } bool isLastInPart = currentPartPoints != null && currentIndexInPart == currentPartPoints.PointCount - 1; var currentVertexIndex = new VertexIndex(currentPartIdx, currentIndexInPart, isLastInPart); if (!coordinateDictionary.ContainsKey(wksPointZ)) { coordinateDictionary.Add(wksPointZ, currentVertexIndex); } else if (!compare3D && !double.IsNaN(_zTolerance)) { VertexIndex alreadyAdded = coordinateDictionary[wksPointZ]; List <VertexIndex> duplicateIndices; if (!duplicateCoordinates.TryGetValue(wksPointZ, out duplicateIndices)) { duplicateIndices = new List <VertexIndex>(2) { alreadyAdded }; duplicateCoordinates.Add(wksPointZ, duplicateIndices); } duplicateIndices.Add(currentVertexIndex); } if (isLastInPart) { currentPartIdx++; currentPartPoints = null; currentIndexInPart = 0; } else { currentIndexInPart++; } } return(coordinateDictionary); }
public IPolyline GetBaseSegmentZDifferences( out IDictionary <WKSPointZ, VertexIndex> zDifferentPoints) { Assert.True(_baseGeometry is IPolyline || _baseGeometry is IPath, "Not implemented for geometries other than lines."); Stopwatch watch = _msg.DebugStartTiming("Calculating Z difference on source..."); // Get the points that are in the base but not in the target: zDifferentPoints = GetDifference(true); IDictionary <VertexIndex, ISegment> sourceSegmentsToAdd = new Dictionary <VertexIndex, ISegment>(); foreach ( KeyValuePair <WKSPointZ, VertexIndex> differentPointOnPath in zDifferentPoints) { bool targetContainsPoint = CompareGeometryContainsPoint3D(differentPointOnPath.Key); if (!targetContainsPoint) { // Take the respective segment before and after this point as difference VertexIndex vertexIndex = differentPointOnPath.Value; int previousSegmentIdx = vertexIndex.VertexIndexInPart - 1; var previousVertexIdx = new VertexIndex(vertexIndex.PartIndex, previousSegmentIdx, false); if (previousSegmentIdx >= 0 && !sourceSegmentsToAdd.ContainsKey(previousVertexIdx)) { ISegment segment = GetBaseSegment(previousVertexIdx); sourceSegmentsToAdd.Add(previousVertexIdx, segment); } if (!vertexIndex.IsLastInPart && !sourceSegmentsToAdd.ContainsKey(vertexIndex)) { ISegment segment = GetBaseSegment(vertexIndex); sourceSegmentsToAdd.Add(vertexIndex, segment); } } } IPolyline sourceDifferences = GeometryFactory.CreatePolyline(_baseGeometry.SpatialReference, true, GeometryUtils.IsMAware(_baseGeometry)); var segmentArray = new ISegment[sourceSegmentsToAdd.Count]; sourceSegmentsToAdd.Values.CopyTo(segmentArray, 0); GeometryUtils.GeometryBridge.SetSegments((ISegmentCollection)sourceDifferences, ref segmentArray); _msg.DebugStopTiming(watch, "Calculated Z differences on source and built difference line"); return(sourceDifferences); }