/// <summary> /// Computes the (approximate) intersection point between two line segments /// using homogeneous coordinates. /// Note that this algorithm is /// not numerically stable; i.e. it can produce intersection points which /// lie outside the envelope of the line segments themselves. In order /// to increase the precision of the calculation input points should be normalized /// before passing them to this routine. /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="q1"></param> /// <param name="q2"></param> /// <returns></returns> public static ICoordinate Intersection(ICoordinate p1, ICoordinate p2, ICoordinate q1, ICoordinate q2) { HCoordinate l1 = new HCoordinate(new HCoordinate(p1), new HCoordinate(p2)); HCoordinate l2 = new HCoordinate(new HCoordinate(q1), new HCoordinate(q2)); HCoordinate intHCoord = new HCoordinate(l1, l2); ICoordinate intPt = intHCoord.Coordinate; return(intPt); }
/// <summary> /// /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> public HCoordinate(HCoordinate p1, HCoordinate p2) { x = p1.y * p2.w - p2.y * p1.w; y = p2.x * p1.w - p1.x * p2.w; w = p1.x * p2.y - p2.x * p1.y; }
/// <summary> /// This method computes the actual value of the intersection point. /// To obtain the maximum precision from the intersection calculation, /// the coordinates are normalized by subtracting the minimum /// ordinate values (in absolute value). This has the effect of /// removing common significant digits from the calculation to /// maintain more bits of precision. /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="q1"></param> /// <param name="q2"></param> /// <returns></returns> private ICoordinate Intersection(ICoordinate p1, ICoordinate p2, ICoordinate q1, ICoordinate q2) { ICoordinate n1 = new Coordinate(p1); ICoordinate n2 = new Coordinate(p2); ICoordinate n3 = new Coordinate(q1); ICoordinate n4 = new Coordinate(q2); ICoordinate normPt = new Coordinate(); NormalizeToEnvCentre(n1, n2, n3, n4, normPt); ICoordinate intPt = null; try { intPt = HCoordinate.Intersection(n1, n2, n3, n4); } catch (NotRepresentableException) { Assert.ShouldNeverReachHere("Coordinate for intersection is not calculable"); } intPt.X += normPt.X; intPt.Y += normPt.Y; /* * * MD - May 4 2005 - This is still a problem. Here is a failure case: * * LINESTRING (2089426.5233462777 1180182.3877339689, 2085646.6891757075 1195618.7333999649) * LINESTRING (1889281.8148903656 1997547.0560044837, 2259977.3672235999 483675.17050843034) * int point = (2097408.2633752143,1144595.8008114607) */ if (!IsInSegmentEnvelopes(intPt)) { Trace.WriteLine("Intersection outside segment envelopes: " + intPt); } /* * // disabled until a better solution is found * if(!IsInSegmentEnvelopes(intPt)) * { * Trace.WriteLine("first value outside segment envelopes: " + intPt); * * IteratedBisectionIntersector ibi = new IteratedBisectionIntersector(p1, p2, q1, q2); * intPt = ibi.Intersection; * } * if(!IsInSegmentEnvelopes(intPt)) * { * Trace.WriteLine("ERROR - outside segment envelopes: " + intPt); * * IteratedBisectionIntersector ibi = new IteratedBisectionIntersector(p1, p2, q1, q2); * Coordinate testPt = ibi.Intersection; * } */ if (precisionModel != null) { precisionModel.MakePrecise(intPt); } return(intPt); }