예제 #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;
        }
예제 #2
0
        /// <summary>
        /// Determines whether the specified polygon is valid.
        /// </summary>
        /// <param name="shell">The coordinates of the polygon shell.</param>
        /// <param name="holes">The coordinates of the polygon holes.</param>
        /// <param name="validateIntersections">A value indicating whether to validate for intersections.</param>
        /// <param name="precisionModel">The precision model.</param>
        /// <returns><c>true</c> if the polygon is valid; otherwise false.</returns>
        /// <exception cref="System.ArgumentNullException">The shell is null.</exception>
        public static Boolean IsValid(IEnumerable <Coordinate> shell, IEnumerable <IEnumerable <Coordinate> > holes, Boolean validateIntersections, PrecisionModel precisionModel)
        {
            if (shell == null)
            {
                throw new ArgumentNullException(nameof(shell));
            }

            if (precisionModel == null)
            {
                precisionModel = PrecisionModel.Default;
            }

            // shell and holes existence
            IEnumerator <Coordinate> shellEnumerator = shell.GetEnumerator();

            if (!shellEnumerator.MoveNext())
            {
                // shell has no coordinates
                if (holes == null)
                {
                    return(true);
                }

                return(holes.Any(hole => holes.AnyElement()));
            }

            Int32      count = 1;
            Coordinate first = shellEnumerator.Current, previous = first, current = first;

            if (first == null || !first.IsValid)
            {
                return(false);
            }

            while (shellEnumerator.MoveNext())
            {
                current = shellEnumerator.Current;

                if (current == null || !current.IsValid || current.Z != first.Z || precisionModel.AreEqual(current, previous))
                {
                    return(false);
                }

                previous = current;
                count++;
            }

            if (count < 4 || !precisionModel.AreEqual(first, current))
            {
                return(false);
            }

            List <IEnumerable <Coordinate> > ringList = new List <IEnumerable <Coordinate> >();

            ringList.Add(shell);

            // holes
            if (holes != null)
            {
                foreach (IEnumerable <Coordinate> hole in holes)
                {
                    if (hole == null)
                    {
                        continue;
                    }

                    IEnumerator <Coordinate> holeEnumerator = hole.GetEnumerator();
                    if (!holeEnumerator.MoveNext())
                    {
                        continue;
                    }

                    count = 1;
                    first = holeEnumerator.Current;
                    if (first == null || !first.IsValid)
                    {
                        return(false);
                    }

                    while (holeEnumerator.MoveNext())
                    {
                        current = holeEnumerator.Current;

                        if (current == null || !current.IsValid || current.Z != first.Z || precisionModel.AreEqual(current, previous))
                        {
                            return(false);
                        }

                        previous = current;
                        count++;
                    }

                    if (count < 4 || !precisionModel.AreEqual(first, current))
                    {
                        return(false);
                    }

                    ringList.Add(hole);
                }
            }

            // check for any intersection
            if (validateIntersections && ShamosHoeyAlgorithm.Intersects(ringList, precisionModel))
            {
                return(false);
            }

            return(true);
        }