internal static IList <double[]> GetLimits([NotNull] SegmentProxy segmentProxy, [NotNull] IPolygon buffer) { // TODO this method would be extremely expensive when called on WksSegmentProxy instances var result = new List <double[]>(); // Remark: segmentLine is altered by ITopologicalOperator.Intersect in such a way // that equal segments may not be considered as equal anymore IPolyline segmentLine = segmentProxy.GetPolyline(true); //IPolyline segmentLine = segmentProxy.GetPolyline(); var intersects = (IGeometryCollection) ((ITopologicalOperator)buffer).Intersect( segmentLine, esriGeometryDimension.esriGeometry1Dimension); int intersectCount = intersects.GeometryCount; for (var i = 0; i < intersectCount; i++) { var part = (IPath)intersects.Geometry[i]; double t0 = 0; double t1 = 0; double offset = 0; var rightSide = false; // TODO if called frequently, create abstract GetSegmentDistance(IPoint) on SegmentProxy, // with custom implementation on WksSegmentProxy. // Currently this seems to be called for AoSegmentProxys only, but this is not obvious. // TODO use a template point and part.QueryFromPoint() / part.QueryToPoint()? segmentLine.QueryPointAndDistance(esriSegmentExtension.esriExtendTangents, part.FromPoint, true, HelpPoint, ref t0, ref offset, ref rightSide); segmentLine.QueryPointAndDistance(esriSegmentExtension.esriExtendTangents, part.ToPoint, true, HelpPoint, ref t1, ref offset, ref rightSide); double tMin = Math.Min(t0, t1); double tMax = Math.Max(t0, t1); result.Add(new[] { tMin, tMax }); } // Handle spatial tolerance problems for segments near tolerance size! if (intersectCount == 0 && !((IRelationalOperator)buffer).Disjoint(segmentLine)) { ((ITopologicalOperator)segmentLine).Simplify(); if (segmentLine.IsEmpty) { result.Add(new[] { 0.0, 1.0 }); } } return(result); }
public static double GetClosestPointFraction([NotNull] SegmentProxy segmentProxy, [NotNull] Pnt nearPoint, out double?offset, out bool?onRightSide, bool as3D) { if (segmentProxy.IsLinear) { Pnt p0s = segmentProxy.GetStart(as3D); Pnt p0e = segmentProxy.GetEnd(as3D); Pnt l0 = p0e - p0s; offset = null; onRightSide = null; return(GetAlongFraction(nearPoint - p0s, l0)); } const bool forceCreation = true; IPolyline segmentLine = segmentProxy.GetPolyline(forceCreation); IPoint near = new PointClass(); near.PutCoords(nearPoint.X, nearPoint.Y); IPoint onPoint = new PointClass(); double fraction = 0; double offsetValue = 0; var rightSide = false; const bool asRatio = true; segmentLine.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, near, asRatio, onPoint, ref fraction, ref offsetValue, ref rightSide); offset = offsetValue; onRightSide = rightSide; return(fraction); }
private static bool GetCoincident([NotNull] SegmentProxy segment, [NotNull] SegmentProxy hull, bool is3D, out NearSegment hullStartNear, out NearSegment hullEndNear) { hullStartNear = NearSegment.NotNear; // TODO hullEndNear = NearSegment.NotNear; // TODO IPolyline segLine = segment.GetPolyline(false); IPolyline hullLine = hull.GetPolyline(false); if (!((IRelationalOperator)segLine).Equals(hullLine)) { return(false); } var coincident = true; Pnt segmentStart = segment.GetStart(is3D); Pnt segmentEnd = segment.GetEnd(is3D); Pnt hullStart = hull.GetStart(is3D); Pnt hullEnd = hull.GetEnd(is3D); double distFromSegFromHull; { double dx = segmentStart.X - hullStart.X; double dy = segmentStart.Y - hullStart.Y; distFromSegFromHull = dx * dx + dy * dy; } double distFromSegToHull; { double dx = segmentStart.X - hullEnd.X; double dy = segmentStart.Y - hullEnd.Y; distFromSegToHull = dx * dx + dy * dy; } bool isInverse = (distFromSegFromHull > distFromSegToHull); Pnt hullMatchSegFrom; Pnt hullMatchSegTo; if (!isInverse) { hullMatchSegFrom = hullStart; hullMatchSegTo = hullEnd; } else { hullMatchSegFrom = hullEnd; hullMatchSegTo = hullStart; } if (is3D) { double zPrecision = 0; ISpatialReference spatialReference = segment.SpatialReference; if (spatialReference != null && spatialReference.HasZPrecision()) { double falseZ; double zUnits; spatialReference.GetZFalseOriginAndUnits(out falseZ, out zUnits); zPrecision = 1 / zUnits; } if (Math.Abs(hullMatchSegFrom[2] - segmentStart[2]) > zPrecision || Math.Abs(hullMatchSegTo[2] - segmentStart[2]) > zPrecision) { coincident = false; } } if (coincident) { if (!isInverse) { hullStartNear = NearSegment.NearStart; hullEndNear = NearSegment.NearEnd; } else { hullStartNear = NearSegment.NearEnd; hullEndNear = NearSegment.NearStart; } } return(coincident); }