Beispiel #1
0
        /// <summary>
        /// Computes the planar orientation of a polygon.
        /// </summary>
        /// <param name="shell">The coordinates of the polygon shell.</param>
        /// <param name="precisionModel">The precision model.</param>
        /// <returns>The orientation of the polygon. If the polygon is invalid <see cref="AEGIS.Orientation.Undefined" /> is returned.</returns>
        /// <exception cref="System.ArgumentNullException">The shell is null.</exception>
        public static Orientation Orientation(IEnumerable <Coordinate> shell, PrecisionModel precisionModel)
        {
            if (shell == null)
            {
                throw new ArgumentNullException(nameof(shell));
            }

            // check for polygon properties
            IEnumerator <Coordinate> enumerator = shell.GetEnumerator();

            Double sum   = 0;
            Int32  count = 1;

            if (!enumerator.MoveNext())
            {
                return(AEGIS.Orientation.Undefined);
            }

            Coordinate first = enumerator.Current, previous = first, current = first;

            while (enumerator.MoveNext())
            {
                current = enumerator.Current;
                sum    += (current.X - previous.X) * (current.Y + previous.Y);
                count++;

                previous = current;
            }

            if (count < 3)
            {
                return(AEGIS.Orientation.Undefined);
            }

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

            if (!precisionModel.AreEqual(first, current))
            {
                sum += (first.X - current.X) * (first.Y + current.Y);
            }

            if (Math.Abs(sum) <= precisionModel.Tolerance(shell))
            {
                return(AEGIS.Orientation.Collinear);
            }

            return((sum > 0) ? AEGIS.Orientation.Clockwise : AEGIS.Orientation.Counterclockwise);
        }
Beispiel #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);
        }