/// <summary> /// Partitions a polygon by triangles. /// </summary> public void Compute() { this.result = new List <Coordinate[]>(); List <Coordinate> shell = new List <Coordinate>(this.Source); List <Coordinate> nextShell = new List <Coordinate>(this.Source); Coordinate[] triangle; Int32 coordinateCount = shell.Count - 1; Int32 coordinateIndex = 1; while (shell.Count != 4) { Coordinate centroid = LineAlgorithms.Centroid(shell[(shell.Count + coordinateIndex - 1) % coordinateCount], shell[(shell.Count + coordinateIndex + 1) % coordinateCount], this.PrecisionModel); nextShell.Remove(nextShell[coordinateIndex]); if (!WindingNumberAlgorithm.InExterior(shell, centroid, this.PrecisionModel) && !ShamosHoeyAlgorithm.Intersects(nextShell, this.PrecisionModel)) { triangle = new Coordinate[3] { shell[(coordinateCount + coordinateIndex - 1) % coordinateCount], shell[coordinateIndex], shell[(coordinateCount + coordinateIndex + 1) % coordinateCount] }; this.result.Add(triangle); shell.Remove(shell[coordinateIndex]); coordinateIndex = 1; coordinateCount--; } else { coordinateIndex = (coordinateIndex + 1) % (shell.Count - 1); nextShell = new List <Coordinate>(shell); } } triangle = new Coordinate[3] { shell[0], shell[1], shell[2] }; this.result.Add(triangle); this.hasResult = true; }
/// <summary> /// Computes the distance between the specified geometries. /// </summary> /// <param name="lineString">The line string.</param> /// <param name="polygon">The polygon.</param> /// <param name="precisionModel">The precision model.</param> /// <returns>The distance between the specified geometries.</returns> /// <exception cref="System.ArgumentNullException"> /// The line string is null. /// or /// The polygon is null. /// </exception> public static Double Distance(IBasicLineString lineString, IBasicPolygon polygon, PrecisionModel precisionModel) { if (lineString == null) { throw new ArgumentNullException(nameof(lineString)); } if (polygon == null) { throw new ArgumentNullException(nameof(polygon)); } if (WindingNumberAlgorithm.InExterior(polygon, lineString[0])) { return(0); } if (polygon.HoleCount == 0) { return(Distance(lineString, polygon.Shell, precisionModel)); } return(Math.Min(Distance(lineString, polygon.Shell, precisionModel), polygon.Holes.Min(hole => Distance(lineString, hole, precisionModel)))); }
/// <summary> /// Computes the distance between the specified geometries. /// </summary> /// <param name="first">The line string.</param> /// <param name="second">The polygon.</param> /// <param name="precisionModel">The precision model.</param> /// <returns>The distance between the specified geometries.</returns> /// <exception cref="System.ArgumentNullException"> /// The first polygon is null. /// or /// The second polygon is null. /// </exception> public static Double Distance(IBasicPolygon first, IBasicPolygon second, PrecisionModel precisionModel) { if (first == null) { throw new ArgumentNullException(nameof(first)); } if (second == null) { throw new ArgumentNullException(nameof(second)); } if (WindingNumberAlgorithm.InExterior(first, second.Shell[0])) { return(0); } if (first.HoleCount == 0) { return(Distance(first.Shell, second, precisionModel)); } return(Math.Min(Distance(first.Shell, second, precisionModel), first.Holes.Min(hole => Distance(hole, second, precisionModel)))); }
/// <summary> /// Computes the distance between the specified geometries. /// </summary> /// <param name="point">The point.</param> /// <param name="polygon">The polygon.</param> /// <param name="precisionModel">The precision model.</param> /// <returns>The distance between the specified geometries.</returns> /// <exception cref="System.ArgumentNullException"> /// The point is null. /// or /// The polygon is null. /// </exception> public static Double Distance(IBasicPoint point, IBasicPolygon polygon, PrecisionModel precisionModel) { if (point == null) { throw new ArgumentNullException(nameof(point)); } if (polygon == null) { throw new ArgumentNullException(nameof(polygon)); } if (!WindingNumberAlgorithm.InExterior(polygon, point.Coordinate)) { return(0); } if (polygon.HoleCount == 0) { return(Distance(point, polygon.Shell, precisionModel)); } return(Math.Min(Distance(point, polygon.Shell, precisionModel), polygon.Holes.Min(hole => Distance(point, hole, precisionModel)))); }
/// <summary> /// Computes the location of the specified coordinate within a polygon. /// </summary> /// <param name="shell">The shell of the polygon.</param> /// <param name="holes">The holes of the polygon.</param> /// <param name="coordinate">The examined coordinate.</param> /// <param name="precisionModel">The precision model.</param> /// <returns>The location of the coordinate.</returns> private static RelativeLocation ComputeLocation(IEnumerable <Coordinate> shell, IEnumerable <IEnumerable <Coordinate> > holes, Coordinate coordinate, PrecisionModel precisionModel) { if (!coordinate.IsValid) { return(RelativeLocation.Undefined); } if (shell.Any(coord => coord == null || !coord.IsValid)) { return(RelativeLocation.Undefined); } if (!Envelope.Contains(shell, coordinate)) { return(RelativeLocation.Exterior); } WindingNumberAlgorithm algorithm = new WindingNumberAlgorithm(shell, coordinate, precisionModel); algorithm.Compute(); // probably the Winding Number algorithm already detected that the coordinate is on the boundary of the polygon shell if (algorithm.isCoordinateOnEdge) { return(RelativeLocation.Boundary); } // additionally check the boundary if (ComputeOnBoundary(shell, coordinate, precisionModel)) { return(RelativeLocation.Boundary); } if (algorithm.Result == 0) { return(RelativeLocation.Exterior); } // if the coordinate is not outside, the holes are also required to be checked if (holes != null) { foreach (IEnumerable <Coordinate> hole in holes) { if (hole == null) { continue; } if (hole.Any(coord => coord == null || !coord.IsValid)) { return(RelativeLocation.Undefined); } algorithm = new WindingNumberAlgorithm(hole, coordinate, precisionModel); algorithm.Compute(); if (algorithm.isCoordinateOnEdge) { return(RelativeLocation.Boundary); } // additionally check the boundary if (ComputeOnBoundary(hole, coordinate, precisionModel)) { return(RelativeLocation.Boundary); } if (algorithm.Result != 0) { return(RelativeLocation.Exterior); } } } return(RelativeLocation.Interior); }