/// <summary> /// /// </summary> /// <param name="p"></param> /// <param name="l"></param> /// <returns></returns> private static Location Locate(Coordinate p, ILineString l) { // bounding-box check if (!l.EnvelopeInternal.Intersects(p)) { return(Location.Exterior); } Coordinate[] pt = l.Coordinates; if (!l.IsClosed) { if (p.Equals(pt[0]) || p.Equals(pt[pt.Length - 1])) { return(Location.Boundary); } } if (CGAlgorithms.IsOnLine(p, pt)) { return(Location.Interior); } return(Location.Exterior); }
/// <summary> /// /// </summary> /// <param name="o"></param> /// <param name="p"></param> /// <param name="q"></param> /// <returns></returns> private static int PolarCompare(Coordinate o, Coordinate p, Coordinate q) { double dxp = p.X - o.X; double dyp = p.Y - o.Y; double dxq = q.X - o.X; double dyq = q.Y - o.Y; int orient = CGAlgorithms.ComputeOrientation(o, p, q); if(orient == CGAlgorithms.CounterClockwise) return 1; if(orient == CGAlgorithms.Clockwise) return -1; // points are collinear - check distance double op = dxp * dxp + dyp * dyp; double oq = dxq * dxq + dyq * dyq; if (op < oq) return -1; if (op > oq) return 1; return 0; }
/// <summary> /// Computes the distance from a line segment AB to a line segment CD. /// Note: NON-ROBUST! /// </summary> /// <param name="A">A point of one line.</param> /// <param name="B">The second point of the line (must be different to A).</param> /// <param name="C">One point of the line.</param> /// <param name="D">Another point of the line (must be different to A).</param> /// <returns>The distance from line segment AB to line segment CD.</returns> public static double DistanceLineLine(Coordinate A, Coordinate B, Coordinate C, Coordinate D) { // check for zero-length segments if (A.Equals(B)) { return(CGAlgorithms.DistancePointLine(A, C, D)); } if (C.Equals(D)) { return(CGAlgorithms.DistancePointLine(D, A, B)); } // AB and CD are line segments /* * from comp.graphics.algo * * Solving the above for r and s yields * (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy) * r = ----------------------------- (eqn 1) * (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) * * (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay) * s = ----------------------------- (eqn 2) * (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) * * Let P be the position vector of the * intersection point, then * P=A+r(B-A) or * Px=Ax+r(Bx-Ax) * Py=Ay+r(By-Ay) * By examining the values of r & s, you can also determine some other limiting * conditions: * If 0<=r<=1 & 0<=s<=1, intersection exists * r<0 or r>1 or s<0 or s>1 line segments do not intersect * If the denominator in eqn 1 is zero, AB & CD are parallel * If the numerator in eqn 1 is also zero, AB & CD are collinear. */ double r_top = (A.Y - C.Y) * (D.X - C.X) - (A.X - C.X) * (D.Y - C.Y); double r_bot = (B.X - A.X) * (D.Y - C.Y) - (B.Y - A.Y) * (D.X - C.X); double s_top = (A.Y - C.Y) * (B.X - A.X) - (A.X - C.X) * (B.Y - A.Y); double s_bot = (B.X - A.X) * (D.Y - C.Y) - (B.Y - A.Y) * (D.X - C.X); if ((r_bot == 0) || (s_bot == 0)) { return(Math .Min( CGAlgorithms.DistancePointLine(A, C, D), Math.Min( CGAlgorithms.DistancePointLine(B, C, D), Math.Min(CGAlgorithms.DistancePointLine(C, A, B), CGAlgorithms.DistancePointLine(D, A, B))))); } double s = s_top / s_bot; double r = r_top / r_bot; if ((r < 0) || (r > 1) || (s < 0) || (s > 1)) { // no intersection return(Math .Min( CGAlgorithms.DistancePointLine(A, C, D), Math.Min( CGAlgorithms.DistancePointLine(B, C, D), Math.Min(CGAlgorithms.DistancePointLine(C, A, B), CGAlgorithms.DistancePointLine(D, A, B))))); } return(0.0); // intersection exists }
public override int ComputeIntersect(Coordinate p1, Coordinate p2, Coordinate q1, Coordinate q2) { IsProper = false; // first try a fast test to see if the envelopes of the lines intersect if (!Envelope.Intersects(p1, p2, q1, q2)) { return(NoIntersection); } // for each endpoint, compute which side of the other segment it lies // if both endpoints lie on the same side of the other segment, // the segments do not intersect int Pq1 = CGAlgorithms.OrientationIndex(p1, p2, q1); int Pq2 = CGAlgorithms.OrientationIndex(p1, p2, q2); if ((Pq1 > 0 && Pq2 > 0) || (Pq1 < 0 && Pq2 < 0)) { return(NoIntersection); } int Qp1 = CGAlgorithms.OrientationIndex(q1, q2, p1); int Qp2 = CGAlgorithms.OrientationIndex(q1, q2, p2); if ((Qp1 > 0 && Qp2 > 0) || (Qp1 < 0 && Qp2 < 0)) { return(NoIntersection); } bool collinear = Pq1 == 0 && Pq2 == 0 && Qp1 == 0 && Qp2 == 0; if (collinear) { return(ComputeCollinearIntersection(p1, p2, q1, q2)); } /* * At this point we know that there is a single intersection point * (since the lines are not collinear). */ /* * Check if the intersection is an endpoint. If it is, copy the endpoint as * the intersection point. Copying the point rather than computing it * ensures the point has the exact value, which is important for * robustness. It is sufficient to simply check for an endpoint which is on * the other line, since at this point we know that the inputLines must * intersect. */ if (Pq1 == 0 || Pq2 == 0 || Qp1 == 0 || Qp2 == 0) { IsProper = false; /* * Check for two equal endpoints. * This is done explicitly rather than by the orientation tests * below in order to improve robustness. * * [An example where the orientation tests fail to be consistent is * the following (where the true intersection is at the shared endpoint * POINT (19.850257749638203 46.29709338043669) * * LINESTRING ( 19.850257749638203 46.29709338043669, 20.31970698357233 46.76654261437082 ) * and * LINESTRING ( -48.51001596420236 -22.063180333403878, 19.850257749638203 46.29709338043669 ) * * which used to produce the INCORRECT result: (20.31970698357233, 46.76654261437082, NaN) * */ if (p1.Equals2D(q1) || p1.Equals2D(q2)) { IntersectionPoint[0] = p1; } else if (p2.Equals2D(q1) || p2.Equals2D(q2)) { IntersectionPoint[0] = p2; } else if (Pq1 == 0) { IntersectionPoint[0] = new Coordinate(q1); } else if (Pq2 == 0) { IntersectionPoint[0] = new Coordinate(q2); } else if (Qp1 == 0) { IntersectionPoint[0] = new Coordinate(p1); } else if (Qp2 == 0) { IntersectionPoint[0] = new Coordinate(p2); } } else { IsProper = true; IntersectionPoint[0] = Intersection(p1, p2, q1, q2); } return(PointIntersection); }
/// <summary> /// /// </summary> /// <param name="pt"></param> /// <returns></returns> public bool IsInside(Coordinate pt) { return(CGAlgorithms.IsPointInRing(pt, pts)); }