/// <summary> /// Computes distance between two polygons. /// </summary> /// <remarks> /// To compute the distance, compute the distance /// between the rings of one polygon and the other polygon, /// and vice-versa. /// If the polygons intersect, then at least one ring must /// intersect the other polygon. /// Note that it is NOT sufficient to test only the shell rings. /// A counter-example is a "figure-8" polygon A /// and a simple polygon B at right angles to A, with the ring of B /// passing through the holes of A. /// The polygons intersect, /// but A's shell does not intersect B, and B's shell does not intersect A.</remarks> private void ComputeMinDistancePolygonPolygon(PlanarPolygon3D poly0, IPolygon poly1, bool flip) { ComputeMinDistancePolygonRings(poly0, poly1, flip); if (_isDone) { return; } var polyPlane1 = new PlanarPolygon3D(poly1); ComputeMinDistancePolygonRings(polyPlane1, poly0.Polygon, flip); }
private static Coordinate Intersection(PlanarPolygon3D poly, ILineString line) { var seq = line.CoordinateSequence; if (seq.Count == 0) { return(null); } // start point of line var p0 = new Coordinate(); seq.GetCoordinate(0, p0); double d0 = poly.Plane.OrientedDistance(p0); // for each segment in the line var p1 = new Coordinate(); for (int i = 0; i < seq.Count - 1; i++) { seq.GetCoordinate(i, p0); seq.GetCoordinate(i + 1, p1); double d1 = poly.Plane.OrientedDistance(p1); /** * If the oriented distances of the segment endpoints have the same sign, * the segment does not cross the plane, and is skipped. */ if (d0 * d1 > 0) { continue; } /** * Compute segment-plane intersection point * which is then used for a point-in-polygon test. * The endpoint distances to the plane d0 and d1 * give the proportional distance of the intersection point * along the segment. */ var intPt = SegmentPoint(p0, p1, d0, d1); // Coordinate intPt = polyPlane.intersection(p0, p1, s0, s1); if (poly.Intersects(intPt)) { return(intPt); } // shift to next segment d0 = d1; } return(null); }
/// <summary>Compute distance between a polygon and the rings of another.</summary> private void ComputeMinDistancePolygonRings(PlanarPolygon3D poly, IPolygon ringPoly, bool flip) { // compute shell ring ComputeMinDistancePolygonLine(poly, ringPoly.ExteriorRing, flip); if (_isDone) { return; } // compute hole rings int nHole = ringPoly.NumInteriorRings; for (int i = 0; i < nHole; i++) { ComputeMinDistancePolygonLine(poly, ringPoly.GetInteriorRingN(i), flip); if (_isDone) { return; } } }
/// <summary>Compute distance between a polygon and the rings of another.</summary> private void ComputeMinDistancePolygonRings(PlanarPolygon3D poly, IPolygon ringPoly, bool flip) { // compute shell ring ComputeMinDistancePolygonLine(poly, ringPoly.ExteriorRing, flip); if (_isDone) return; // compute hole rings int nHole = ringPoly.NumInteriorRings; for (int i = 0; i < nHole; i++) { ComputeMinDistancePolygonLine(poly, ringPoly.GetInteriorRingN(i), flip); if (_isDone) return; } }
/// <summary> /// Computes distance between two polygons. /// </summary> /// <remarks> /// To compute the distance, compute the distance /// between the rings of one polygon and the other polygon, /// and vice-versa. /// If the polygons intersect, then at least one ring must /// intersect the other polygon. /// Note that it is NOT sufficient to test only the shell rings. /// A counter-example is a "figure-8" polygon A /// and a simple polygon B at right angles to A, with the ring of B /// passing through the holes of A. /// The polygons intersect, /// but A's shell does not intersect B, and B's shell does not intersect A.</remarks> private void ComputeMinDistancePolygonPolygon(PlanarPolygon3D poly0, IPolygon poly1, bool flip) { ComputeMinDistancePolygonRings(poly0, poly1, flip); if (_isDone) return; var polyPlane1 = new PlanarPolygon3D(poly1); ComputeMinDistancePolygonRings(polyPlane1, poly0.Polygon, flip); }
private void ComputeMinDistancePolygonPoint(PlanarPolygon3D polyPlane, IPoint point, bool flip) { var pt = point.Coordinate; var shell = polyPlane.Polygon.ExteriorRing; if (polyPlane.Intersects(pt, shell)) { // point is either inside or in a hole var nHole = polyPlane.Polygon.NumInteriorRings; for (int i = 0; i < nHole; i++) { var hole = polyPlane.Polygon.GetInteriorRingN(i); if (polyPlane.Intersects(pt, hole)) { ComputeMinDistanceLinePoint(hole, point, flip); return; } } // point is in interior of polygon // distance is distance to polygon plane var dist = Math.Abs(polyPlane.Plane.OrientedDistance(pt)); UpdateDistance(dist, new GeometryLocation(polyPlane.Polygon, 0, pt), new GeometryLocation(point, 0, pt), flip ); } // point is outside polygon, so compute distance to shell linework ComputeMinDistanceLinePoint(shell, point, flip); }
private void ComputeMinDistancePolygonLine(PlanarPolygon3D poly, ILineString line, bool flip) { // first test if line intersects polygon var intPt = Intersection(poly, line); if (intPt != null) { UpdateDistance(0, new GeometryLocation(poly.Polygon, 0, intPt), new GeometryLocation(line, 0, intPt), flip ); return; } // if no intersection, then compute line distance to polygon rings ComputeMinDistanceLineLine(poly.Polygon.ExteriorRing, line, flip); if (_isDone) return; int nHole = poly.Polygon.NumInteriorRings; for (int i = 0; i < nHole; i++) { ComputeMinDistanceLineLine(poly.Polygon.GetInteriorRingN(i), line, flip); if (_isDone) return; } }
private void ComputeMinDistanceOneMulti(PlanarPolygon3D poly, IGeometry geom, bool flip) { if (geom is IGeometryCollection) { int n = geom.NumGeometries; for (int i = 0; i < n; i++) { var g = geom.GetGeometryN(i); ComputeMinDistanceOneMulti(poly, g, flip); if (_isDone) return; } } else { if (geom is IPoint) { ComputeMinDistancePolygonPoint(poly, (IPoint)geom, flip); return; } if (geom is ILineString) { ComputeMinDistancePolygonLine(poly, (ILineString)geom, flip); return; } if (geom is IPolygon) { ComputeMinDistancePolygonPolygon(poly, (IPolygon)geom, flip); //return; } } }
private static Coordinate Intersection(PlanarPolygon3D poly, ILineString line) { var seq = line.CoordinateSequence; if (seq.Count == 0) return null; // start point of line var p0 = new Coordinate(); seq.GetCoordinate(0, p0); var d0 = poly.Plane.OrientedDistance(p0); // for each segment in the line var p1 = new Coordinate(); for (var i = 0; i < seq.Count - 1; i++) { seq.GetCoordinate(i, p0); seq.GetCoordinate(i + 1, p1); var d1 = poly.Plane.OrientedDistance(p1); /** * If the oriented distances of the segment endpoints have the same sign, * the segment does not cross the plane, and is skipped. */ if (d0 * d1 > 0) continue; /** * Compute segment-plane intersection point * which is then used for a point-in-polygon test. * The endpoint distances to the plane d0 and d1 * give the proportional distance of the intersection point * along the segment. */ var intPt = SegmentPoint(p0, p1, d0, d1); // Coordinate intPt = polyPlane.intersection(p0, p1, s0, s1); if (poly.Intersects(intPt)) { return intPt; } // shift to next segment d0 = d1; } return null; }