protected abstract bool CutLineHull(double centerOffset, double r2, double tolerance, out double tMin, out double tMax, out NearSegment hullStartNear, out NearSegment hullEndNear, out bool coincident);
protected static bool Near([NotNull] Pnt p0, [NotNull] Pnt l0, [NotNull] Pnt p1, [NotNull] Pnt l1, double r2, double l12, ref double tMin, ref double tMax, ref NearSegment hullStartNear, ref NearSegment hullEndNear) { double cMin, cMax; double u0 = (p0 + tMin * l0 - p1) * l1 / l12; double u1 = (p0 + tMax * l0 - p1) * l1 / l12; if (u0 < 0) { if (SegmentUtils.CutLineCircle(p0, l0, p1, r2, out cMin, out cMax) == false) { return(false); } hullStartNear = Near(cMin, cMax); // Debug.Assert(cMin > tMin); numerical exceptions possible tMin = cMin; if (u1 < 0) { //Debug.Assert(cMax < tMax); numerical exceptions possible tMax = cMax; } } else if (u0 > 1) { if (SegmentUtils.CutLineCircle(p0, l0, p1 + l1, r2, out cMin, out cMax) == false) { return(false); } hullEndNear = Near(cMin, cMax); //Debug.Assert(cMin > tMin); numerical exceptions possible tMin = cMin; if (u1 > 1) { //Debug.Assert(cMax < tMax); numerical exceptions possible tMax = cMax; } } if (u1 < 0 && u0 >= 0) { if (SegmentUtils.CutLineCircle(p0, l0, p1, r2, out cMin, out cMax) == false) { //throw new InvalidProgramException( // "error in software design assumption"); numerical exceptions possible tMax = tMin + u0 / (u0 - u1) * (tMax - tMin); hullStartNear = Near(tMin, tMax); } else { hullStartNear = Near(cMin, cMax); //Debug.Assert(cMax < tMax); numerical exceptions possible tMax = cMax; } } else if (u1 > 1 && u0 <= 1) { if (SegmentUtils.CutLineCircle(p0, l0, p1 + l1, r2, out cMin, out cMax) == false) { //throw new InvalidProgramException( // "error in software design assumption"); numerical exceptions possible tMax = tMin + (1 - u0) / (u1 - u0) * (tMax - tMin); hullEndNear = Near(tMin, tMax); } else { hullEndNear = Near(cMin, cMax); //Debug.Assert(cMax < tMax); numerical exceptions possible tMax = cMax; } } return(true); }
protected abstract bool CutCurveHullDetailed(double tolerance, [NotNull] out IList <double[]> limits, out NearSegment hullStartNear, out NearSegment hullEndNear, out bool coincident);
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); }