/// <summary> /// Creates a new vector from a line segment, assuming that the direction is from the start point to the end point /// </summary> /// <param name="LineLineSegment">A Topology.LineSegment object to turn into a vector</param> public Vector(LineSegment LineLineSegment) { X = LineLineSegment.X2 - LineLineSegment.X1; Y = LineLineSegment.Y2 - LineLineSegment.Y1; Z = LineLineSegment.Z2 - LineLineSegment.Z1; }
/// <summary> /// Checks whether the borders of a polygon shape, lines of line shapes, or points of point shapes touch. /// </summary> /// <param name="Shape1">A MapWinGIS.Shape object to test</param> /// <param name="Shape2">A MapWinGIS.Shape object to test</param> /// <returns>True if the boundaries touch</returns> public static bool ShapeBoundariesTouch(MapWinGIS.Shape Shape1, MapWinGIS.Shape Shape2) { if (Shape1 == null || Shape1.ShapeType == MapWinGIS.ShpfileType.SHP_NULLSHAPE) { throw new ArgumentException("Argument Shape1 cannot be null"); } if (Shape2 == null || Shape2.ShapeType == MapWinGIS.ShpfileType.SHP_NULLSHAPE) { throw new ArgumentException("Argument Shape2 cannot be null"); } if (Shape1.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPATCH) { throw new ArgumentException("Multipatch is not supported"); } if (Shape2.ShapeType == MapWinGIS.ShpfileType.SHP_MULTIPATCH) { throw new ArgumentException("Multipatch is not supported"); } ShapeCategories Typ1, Typ2; Typ1 = GetCategory(Shape1); Typ2 = GetCategory(Shape2); // for single points, simply show if these specific points overlap if (Typ1 == ShapeCategories.Point && Typ2 == ShapeCategories.Point) { Point p1 = new Point(Shape1.get_Point(0)); Point p2 = new Point(Shape2.get_Point(0)); if (p1.Intersects(p2)) { return(true); } return(false); } // Point to Non-point if (Typ1 == ShapeCategories.Point) { Point p1 = new Point(Shape1.get_Point(0)); if (Typ2 == ShapeCategories.MultiPoint) { for (int I = 0; I < Shape2.numPoints; I++) { Point p2 = new Point(Shape2.get_Point(I)); if (p1.Intersects(p2)) { return(true); } } return(false); } else { for (int I = 0; I < Shape2.numPoints - 1; I++) { LineSegment seg = new LineSegment(Shape2.get_Point(I), Shape2.get_Point(I + 1)); if (seg.Intersects(p1)) { return(true); } } return(false); } } // Point2 to non-point if (Typ2 == ShapeCategories.Point) { Point p2 = new Point(Shape2.get_Point(0)); if (Typ1 == ShapeCategories.MultiPoint) { for (int I = 0; I < Shape1.numPoints; I++) { Point p1 = new Point(Shape1.get_Point(I)); if (p2.Intersects(p1)) { return(true); } } return(false); } else { for (int I = 0; I < Shape1.numPoints - 1; I++) { LineSegment seg = new LineSegment(Shape1.get_Point(I), Shape1.get_Point(I + 1)); if (seg.Intersects(p2)) { return(true); } } return(false); } } // for multipoint, test every point for intersection. if (Typ1 == ShapeCategories.MultiPoint && Typ2 == ShapeCategories.MultiPoint) { List <int> Points1 = PointsWithinEnvelope(Shape1, Shape2.Extents); List <int> Points2 = PointsWithinEnvelope(Shape2, Shape1.Extents); for (int I = 0; I < Points1.Count; I++) { for (int J = 0; J < Points2.Count; J++) { Point p1 = new Point(Shape1.get_Point(I)); Point p2 = new Point(Shape2.get_Point(J)); if (p1.Intersects(p2)) { return(true); } } } return(false); } // For lines and polygons simply test line segments in the area of interrest to see if they touch // (touching in this case just equates to having a minimum distance of 0. if ((Typ1 == ShapeCategories.Line || Typ1 == ShapeCategories.Polygon) && (Typ2 == ShapeCategories.Line || Typ2 == ShapeCategories.Polygon)) { List <LineSegment> Segs1 = LineSegmentsWithinEnvelope(Shape1, Shape2.Extents); List <LineSegment> Segs2 = LineSegmentsWithinEnvelope(Shape2, Shape1.Extents); for (int I = 0; I < Segs1.Count; I++) { for (int J = 0; J < Segs2.Count; J++) { if (Segs1[I].Intersects(Segs2[J])) { return(true); } } } return(false); } // multi-point to polygon if (Typ1 == ShapeCategories.MultiPoint) { List <int> Points1 = PointsWithinEnvelope(Shape1, Shape2.Extents); List <LineSegment> Segs2 = LineSegmentsWithinEnvelope(Shape2, Shape1.Extents); for (int I = 0; I < Points1.Count; I++) { for (int J = 0; J < Segs2.Count; J++) { if (Segs2[J].Intersects(Shape1.get_Point(Points1[I]))) { return(true); } } } return(false); } if (Typ2 == ShapeCategories.MultiPoint) { List <int> Points2 = PointsWithinEnvelope(Shape2, Shape1.Extents); List <LineSegment> Segs1 = LineSegmentsWithinEnvelope(Shape1, Shape2.Extents); for (int I = 0; I < Points2.Count; I++) { for (int J = 0; J < Segs1.Count; J++) { if (Segs1[J].Intersects(Shape2.get_Point(Points2[I]))) { return(true); } } } return(false); } return(false); }
/// <summary> /// Determines the shortest distance between two segments /// </summary> /// <param name="LineLineSegment">LineSegment, The line segment to test against this segment</param> /// <returns>Double, the shortest distance between two segments</returns> public double Distance(LineSegment LineLineSegment) { //http://www.geometryalgorithms.com/Archive/algorithm_0106/algorithm_0106.htm const double SMALL_NUM = 0.00000001; Vector u = new Vector(this); // LineSegment 1 Vector v = new Vector(LineLineSegment); // LineSegment 2 Vector w = new Vector(this.StartPoint, LineLineSegment.StartPoint); double a = u.Dot(u); // length of segment 1 double b = u.Dot(v); // length of segment 2 projected onto line 1 double c = v.Dot(v); // length of segment 2 double d = u.Dot(w); // double e = v.Dot(w); double D = a * c - b * b; double sc, sN, sD = D; double tc, tN, tD = D; // compute the line parameters of the two closest points if (D < SMALL_NUM) // the lines are almost parallel { // force using point P0 on segment 1 sN = 0.0; // to prevent possible division by 0 later sD = 1.0; tN = e; tD = c; } else // get the closest points on the infinite lines { sN = (b * e - c * d); tN = (a * e - b * d); if (sN < 0.0) // sc < 0 => the s=0 edge is visible { sN = 0.0; tN = e; tD = c; } else if (sN > sD) // sc > 1 => the s=1 edge is visible { sN = sD; tN = e + b; tD = c; } } if (tN < 0.0) // tc < 0 => the t=0 edge is visible { tN = 0.0; // recompute sc for this edge if (-d < 0.0) { sN = 0.0; } else if (-d > a) { sN = sD; } else { sN = -d; sD = a; } } else if (tN > tD) // tc > 1 => the t = 1 edge is visible { // recompute sc for this edge if ((-d + b) < 0.0) { sN = 0; } else if ((-d + b) > a) { sN = sD; } else { sN = (-d + b); sD = a; } } // finally do the division to get sc and tc if (Math.Abs(sN) < SMALL_NUM) { sc = 0.0; } else { sc = sN / sD; } if (Math.Abs(tN) < SMALL_NUM) { tc = 0.0; } else { tc = tN / tD; } // get the difference of the two closest points Vector dU = u.Times(sc); Vector dV = v.Times(tc); Vector dP = (w.Plus(dU)).Minus(dV); // S1(sc) - S2(tc) return(dP.Magnitude); }