Ejemplo n.º 1
0
        /// <summary>
        /// Returns the buffer edges that lie between the corresponding source edges.
        /// </summary>
        /// <param name="coordinates">The list of coordinates.</param>
        /// <param name="sourceIndex">Index of the source coordinate.</param>
        /// <returns>The list of edges.</returns>
        private List <Tuple <Coordinate, Coordinate> > GetConvolutionEdges(IReadOnlyList <Coordinate> coordinates, Int32 sourceIndex)
        {
            List <Tuple <Coordinate, Coordinate> > edges = new List <Tuple <Coordinate, Coordinate> >();
            Double previousElementX = sourceIndex != 0 ? coordinates[sourceIndex - 1].X : coordinates[coordinates.Count - 2].X;
            Double previousElementY = sourceIndex != 0 ? coordinates[sourceIndex - 1].Y : coordinates[coordinates.Count - 2].Y;

            Double firstAngle  = Math.Atan2(coordinates[sourceIndex].Y - previousElementY, coordinates[sourceIndex].X - previousElementX);
            Double secondAngle = Math.Atan2(coordinates[sourceIndex + 1].Y - coordinates[sourceIndex].Y, coordinates[sourceIndex + 1].X - coordinates[sourceIndex].X);

            if (firstAngle < 0 && secondAngle == 0)
            {
                secondAngle = 2 * Math.PI;
            }
            if (firstAngle < 0)
            {
                firstAngle = 2 * Math.PI + firstAngle;
            }
            if (secondAngle < 0)
            {
                secondAngle = 2 * Math.PI + secondAngle;
            }

            for (Int32 bufferIndex = 0; bufferIndex < this.bufferCoordinates.Count - 1; bufferIndex++)
            {
                Double middleAngle = Math.Atan2(this.bufferCoordinates[bufferIndex + 1].Y - this.bufferCoordinates[bufferIndex].Y, this.bufferCoordinates[bufferIndex + 1].X - this.bufferCoordinates[bufferIndex].X);
                if (middleAngle < 0)
                {
                    middleAngle = 2 * Math.PI + middleAngle;
                }

                Boolean addCondition = false;
                if (PolygonAlgorithms.Orientation(coordinates, this.PrecisionModel) == Orientation.Clockwise)
                {
                    if (firstAngle >= secondAngle)
                    {
                        addCondition = (middleAngle <= firstAngle) && (middleAngle >= secondAngle);
                    }
                    else
                    {
                        addCondition = middleAngle <= firstAngle || middleAngle >= secondAngle;
                    }
                }
                else
                {
                    if (firstAngle <= secondAngle)
                    {
                        addCondition = middleAngle >= firstAngle && middleAngle <= secondAngle;
                    }
                    else
                    {
                        addCondition = (middleAngle > firstAngle) || (middleAngle < secondAngle);
                    }
                }

                if (addCondition)
                {
                    edges.Add(
                        Tuple.Create(
                            this.PrecisionModel.MakePrecise(new Coordinate(coordinates[sourceIndex].X + this.bufferCoordinates[bufferIndex].X, coordinates[sourceIndex].Y + this.bufferCoordinates[bufferIndex].Y)),
                            this.PrecisionModel.MakePrecise(new Coordinate(coordinates[sourceIndex].X + this.bufferCoordinates[bufferIndex + 1].X, coordinates[sourceIndex].Y + this.bufferCoordinates[bufferIndex + 1].Y))));
                }
            }

            return(edges);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Creates the result polygon with separated shell and hole coordinates.
        /// </summary>
        /// <param name="coordinates">The list of coordinates.</param>
        /// <param name="isHole">A value indicating whether the coordinate list is a hole.</param>
        private void ComputeResultPolygon(IReadOnlyList <Coordinate> coordinates, Boolean isHole)
        {
            BentleyOttmannAlgorithm      algorithm     = new BentleyOttmannAlgorithm(coordinates, this.PrecisionModel);
            List <Coordinate>            intersections = new List <Coordinate>(algorithm.Intersections);
            List <Tuple <Int32, Int32> > edgeIndexes   = new List <Tuple <Int32, Int32> >(algorithm.EdgeIndexes);

            // add edge intersection coordinates to the list of coordinates in counterclockwise order
            List <Coordinate> coordinatesWithIntersections = new List <Coordinate>();

            coordinatesWithIntersections = this.GetCoordinatesWithIntersections(coordinates, intersections, edgeIndexes);

            // remove unnecessary internal coordinates and create holes
            List <List <Coordinate> > internalPolygons = new List <List <Coordinate> >();
            List <List <Coordinate> > holes            = new List <List <Coordinate> >();
            List <Int32> nonShellIndexes      = new List <Int32>();
            Int32        internalPolygonIndex = -1;

            for (Int32 coordinateIndex = 0; coordinateIndex < coordinatesWithIntersections.Count; coordinateIndex++)
            {
                if (internalPolygonIndex != -1)
                {
                    internalPolygons[internalPolygonIndex].Add(coordinatesWithIntersections[coordinateIndex]);
                    nonShellIndexes.Add(coordinateIndex);
                }

                if (intersections.Any(x => x.Equals(coordinatesWithIntersections[coordinateIndex])))
                {
                    Int32 matchingPolygonIndex = internalPolygons.FindIndex(x => x[0].Equals(coordinatesWithIntersections[coordinateIndex]));
                    if (internalPolygonIndex != -1 && internalPolygonIndex < internalPolygons.Count && matchingPolygonIndex != -1)
                    {
                        if (PolygonAlgorithms.Orientation(internalPolygons[matchingPolygonIndex], this.PrecisionModel) == Orientation.Clockwise)
                        {
                            holes.Add(internalPolygons[matchingPolygonIndex]);
                        }

                        for (Int32 polygonIndex = internalPolygons.Count - 1; polygonIndex >= matchingPolygonIndex; polygonIndex--)
                        {
                            internalPolygons.RemoveAt(polygonIndex);
                        }

                        internalPolygonIndex = matchingPolygonIndex - 1;
                    }
                    else
                    {
                        internalPolygonIndex++;
                        internalPolygons.Add(new List <Coordinate>()
                        {
                            coordinatesWithIntersections[coordinateIndex]
                        });
                    }
                }
            }

            for (Int32 index = 0; index < nonShellIndexes.Count; index++)
            {
                coordinatesWithIntersections.RemoveAt(nonShellIndexes[nonShellIndexes.Count - 1 - index]);
            }

            // add shell and hole coordinates to the result
            if (isHole)
            {
                this.resultHoleCoordinates.Add(new List <Coordinate>(coordinatesWithIntersections));
            }
            else
            {
                this.resultShellCoordinates = coordinatesWithIntersections;
                foreach (List <Coordinate> hole in holes)
                {
                    this.resultHoleCoordinates.Add(hole);
                }
            }
        }