static internal Point RawIntersection(IntersectionInfo xx, Point origin) { // If this fires, then you didn't pass the LineSegment as the first argument to GetAllIntersections. Debug.Assert(xx.Segment0 is LineSegment, "LineSegment was not first arg to GetAllIntersections"); // The intersection snaps the end of the intersection to the PolylinePoint at the start/end // of the interesecting segment on the obstacle if the intersection is Curve.CloseIntersections // to that segment endpoint, which can return a point that is just more than Curve.DistanceEpsilon // off the line. Therefore, re-create the intersection using the LineSegment and intersection // parameters (this assumes the LineSegment.End is not Curve.CloseIntersections to the intersection). Point point = xx.Segment0[xx.Par0]; #if DEBUG // This may legitimately be rounding-error'd in the same way as xx.IntersectionPoint (and the // caller addresses this later). The purpose of the assert is to verify that the LineSegment // interception is not outside the bbox in the perpendicular direction. var lineSeg = (LineSegment)xx.Segment0; if (StaticGraphUtility.IsVertical(PointComparer.GetDirections(lineSeg.Start, lineSeg.End))) { Debug.Assert(PointComparer.Equal(point.X, origin.X), "segment0 obstacle intersection is off the vertical line"); } else { Debug.Assert(PointComparer.Equal(point.Y, origin.Y), "segment0 obstacle intersection is off the horizontal line"); } #endif // DEBUG return ApproximateComparer.Round(point); }
// Most of the original contents of this file have been subsumed into ObstacleTree and TransientGraphUtility. internal static Point MungeClosestIntersectionInfo(Point rayOrigin, IntersectionInfo closestIntersection, bool isHorizontal) { Rectangle bbox = closestIntersection.Segment1.BoundingBox; #if SHARPKIT //https://code.google.com/p/sharpkit/issues/detail?id=369 Point closest = RawIntersection(closestIntersection, rayOrigin).Clone(); #else Point closest = RawIntersection(closestIntersection, rayOrigin); #endif if (isHorizontal) { closest.X = MungeIntersect(rayOrigin.X, closest.X, bbox.Left, bbox.Right); } else { // vertical closest.Y = MungeIntersect(rayOrigin.Y, closest.Y, bbox.Bottom, bbox.Top); } return closest; }
internal static IntersectionInfo LiftIntersectionToCurves(ICurve c0, ICurve c1, IntersectionInfo xx) { return LiftIntersectionToCurves(c0, c1, xx.Par0, xx.Par1, xx.IntersectionPoint, xx.Segment0, xx.Segment1); }
static void AddIntersection(ParallelogramLeaf n0, ParallelogramLeaf n1, List<IntersectionInfo> intersections, double aSol, double bSol, Point x) { //adjust the intersection if it is close to the ends of the segs if (ApproximateComparer.CloseIntersections(x, n0.Seg[n0.Low])) { x = n0.Seg[n0.Low]; aSol = n0.Low; } else if (ApproximateComparer.CloseIntersections(x, n0.Seg[n0.High])) { x = n0.Seg[n0.High]; aSol = n0.High; } if (ApproximateComparer.CloseIntersections(x, n1.Seg[n1.Low])) { x = n1.Seg[n1.Low]; bSol = n1.Low; } else if (ApproximateComparer.CloseIntersections(x, n1.Seg[n1.High])) { x = n1.Seg[n1.High]; bSol = n1.High; } bool oldIntersection = OldIntersection(intersections, ref x); if (!oldIntersection) { var xx = new IntersectionInfo(aSol, bSol, x, n0.Seg, n1.Seg); intersections.Add(xx); } return; }
static IntersectionInfo DropIntersectionToSegs(IntersectionInfo xx) { ICurve seg0; double par0; if (xx.Segment0 is Curve) (xx.Segment0 as Curve).GetSegmentAndParameter(xx.Par0, out par0, out seg0); else { par0 = xx.Par0; seg0 = xx.Segment0; } ICurve seg1; double par1; if (xx.Segment1 is Curve) (xx.Segment1 as Curve).GetSegmentAndParameter(xx.Par1, out par1, out seg1); else { par1 = xx.Par1; seg1 = xx.Segment1; } return new IntersectionInfo(par0, par1, xx.IntersectionPoint, seg0, seg1); }
static bool AlreadyInside(List<IntersectionInfo> ret, IntersectionInfo intersectionInfo) { for(int i=0;i<ret.Count;i++) { var ii = ret[i]; if (ApproximateComparer.CloseIntersections(ii.IntersectionPoint, intersectionInfo.IntersectionPoint)) return true; } return false; }
public static bool RealCut(IntersectionInfo xx, Curve polyline, bool onlyFromInsideCuts) { ValidateArg.IsNotNull(xx, "xx"); ValidateArg.IsNotNull(polyline, "polyline"); ICurve sseg = xx.Segment0; ICurve pseg = xx.Segment1; double spar = xx.Par0; double ppar = xx.Par1; Point x = xx.IntersectionPoint; //normalised tangent to spline Point ts = sseg.Derivative(spar).Normalize(); Point pn = pseg.Derivative(ppar).Normalize().Rotate(Math.PI/2); if (ApproximateComparer.Close(x, pseg.End)) { //so pseg enters the spline ICurve exitSeg = null; for (int i = 0; i < polyline.Segments.Count - 1; i++) if (polyline.Segments[i] == pseg) { exitSeg = polyline.Segments[i + 1]; break; } if (exitSeg == null) return false; //hit the end of the polyline Point tsn = ts.Rotate((Math.PI/2)); bool touch = (tsn*pseg.Derivative(pseg.ParEnd))*(tsn*exitSeg.Derivative(exitSeg.ParStart)) < ApproximateComparer.Tolerance; return !touch; } if (ApproximateComparer.Close(x, pseg.Start)) { //so pseg exits the spline ICurve enterSeg = null; for (int i = polyline.segs.Count - 1; i > 0; i--) if (polyline.Segments[i] == pseg) { enterSeg = polyline.Segments[i - 1]; break; } if (enterSeg == null) return false; Point tsn = ts.Rotate((Math.PI/2)); bool touch = (tsn*pseg.Derivative(pseg.ParStart))* (tsn*enterSeg.Derivative(enterSeg.ParEnd)) < ApproximateComparer.Tolerance; return !touch; } double d = ts*pn; if (onlyFromInsideCuts) return d > ApproximateComparer.DistanceEpsilon; return Math.Abs(d) > ApproximateComparer.DistanceEpsilon; }
/// <summary> /// Returns true if curves do not touch in the intersection point /// </summary> /// <param name="xx"></param> /// <param name="polygon"></param> /// <param name="onlyFromInsideCuts">if set to true and first curve is closed will return true /// only when the second curve cuts the first one from the inside</param> /// <returns></returns> public static bool RealCutWithClosedCurve(IntersectionInfo xx, Curve polygon, bool onlyFromInsideCuts) { ValidateArg.IsNotNull(xx, "xx"); ValidateArg.IsNotNull(polygon, "polygon"); ICurve sseg = xx.Segment0; ICurve pseg = xx.Segment1; double spar = xx.Par0; double ppar = xx.Par1; Point x = xx.IntersectionPoint; //normalised tangent to spline Point ts = sseg.Derivative(spar).Normalize(); Point pn = pseg.Derivative(ppar).Normalize().Rotate(Math.PI/2); if (ApproximateComparer.Close(x, pseg.End)) { //so pseg enters the spline ICurve exitSeg = null; for (int i = 0; i < polygon.Segments.Count; i++) if (polygon.Segments[i] == pseg) { exitSeg = polygon.Segments[(i + 1)%polygon.Segments.Count]; break; } if (exitSeg == null) throw new InvalidOperationException(); //"exitSeg==null"); Point tsn = ts.Rotate((Math.PI/2)); bool touch = (tsn*pseg.Derivative(pseg.ParEnd))*(tsn*exitSeg.Derivative(exitSeg.ParStart)) < ApproximateComparer.Tolerance; return !touch; } if (ApproximateComparer.Close(x, pseg.Start)) { //so pseg exits the spline ICurve enterSeg = null; for (int i = 0; i < polygon.Segments.Count; i++) if (polygon.Segments[i] == pseg) { enterSeg = polygon.Segments[i > 0 ? (i - 1) : polygon.Segments.Count - 1]; break; } Point tsn = ts.Rotate((Math.PI/2)); bool touch = (tsn*pseg.Derivative(pseg.ParStart))* (tsn*enterSeg.Derivative(enterSeg.ParEnd)) < ApproximateComparer.Tolerance; return !touch; } double d = ts*pn; if (onlyFromInsideCuts) return d > ApproximateComparer.DistanceEpsilon; return Math.Abs(d) > ApproximateComparer.DistanceEpsilon; }
static ICurve GetTrimmedCurveForHookingUpAnywhere(ICurve curve, PolylinePoint lastPointInside, IntersectionInfo x0, IntersectionInfo x1) { var clockwise = Point.GetTriangleOrientation(x1.IntersectionPoint, x0.IntersectionPoint, lastPointInside.Point) == TriangleOrientation.Clockwise; double rightX = x0.Par0; double leftX = x1.Par0; ICurve tr0, tr1; Curve ret; if (clockwise) { if (rightX < leftX) return curve.Trim(rightX, leftX); tr0 = curve.Trim(rightX, curve.ParEnd); tr1 = curve.Trim(curve.ParStart, leftX); ret = new Curve(); return ret.AddSegs(tr0, tr1); } if (leftX < rightX) return curve.Trim(leftX, rightX); tr0 = curve.Trim(leftX, curve.ParEnd); tr1 = curve.Trim(curve.ParStart, rightX); ret = new Curve(); return ret.AddSegs(tr0, tr1); }
void ExtendPolyline(Point tangentAtIntersection, IntersectionInfo x, Point polylineTangent, HookUpAnywhereFromInsidePort port) { var normal=tangentAtIntersection.Rotate(Math.PI/2); if(normal*polylineTangent<0) normal=-normal; var pointBeforeLast = x.IntersectionPoint + normal * port.HookSize; Point pointAfterX; if (!Point.LineLineIntersection(pointBeforeLast, pointBeforeLast+tangentAtIntersection, _polyline.End, _polyline.End+polylineTangent, out pointAfterX)) return; _polyline.AddPoint(pointAfterX); _polyline.AddPoint(pointBeforeLast); _polyline.AddPoint(x.IntersectionPoint); }