Beispiel #1
0
        /// <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);
        }