示例#1
0
        private List <Geometry> IntersectionNaive(Edge edge)
        {
            List <Geometry> intersections = new List <Geometry>();

            if (this.BoundingBox.Intersects(edge.BoundingBox))
            {
                for (int i = 0; i < this.Edges.Count; i++)
                {
                    var side         = this.Edges[i];
                    var intersection = edge.Intersection(side);
                    if (intersection != null)
                    {
                        if (!intersections.Any() && !intersections.Last().Equals(intersection))
                        {
                            intersections.Add(intersection);
                        }
                    }
                }
            }

            return(intersections);
        }
示例#2
0
        public List <Geometry> Intersection(Edge edge)
        {
            // No fast algorithm yet to calculate intersection on concave polygons
            if (!this.IsConvex())
            {
                return(this.IntersectionNaive(edge));
            }

            //https://stackoverflow.com/questions/4497841/asymptotically-optimal-algorithm-to-compute-if-a-line-intersects-a-convex-polygo

            List <Geometry> intersections = new List <Geometry>();

            if (!this.BoundingBox.Intersects(edge.BoundingBox))
            {
                return(intersections);
            }

            var  vertexCount      = this.Vertices.Count;
            int  midIndex         = (int)(vertexCount / 2);
            Edge diagonal         = this.DiagonalByVertexIndex(0, midIndex);
            int  polygonDirection = this.Vertices[1].IsLeftFrom(diagonal);

            Geometry intersection = diagonal.Intersection(edge);

            while (intersection == null)
            {
                // If midIndex is any neighbour from the start vertex
                // means the whole line is to one side or the other and doesn't intersect.
                if (midIndex == 1 || midIndex == vertexCount - 1)
                {
                    return(intersections);
                }

                int startSide = edge.StartVertex.IsLeftFrom(diagonal);
                int endSide   = edge.EndVertex.IsLeftFrom(diagonal);

                // If same side, don't intersect
                if (startSide == polygonDirection && endSide == polygonDirection)
                {
                    return(intersections);
                }
                // Is on other side from the polygonDirection (Vertices[1])
                else if (startSide != polygonDirection)
                {
                    midIndex += (int)((vertexCount - midIndex) / 2);
                }
                else
                {
                    midIndex = (int)(midIndex / 2);
                }

                diagonal     = this.DiagonalByVertexIndex(0, midIndex);
                intersection = edge.Intersection(diagonal);
            }

            // If intersection is an Edge
            if (intersection is Edge edgeIntersection)
            {
                // If diagonal other edge is any neighbour, intersection is on one of the sides
                if (midIndex == 1 || midIndex == vertexCount - 1)
                {
                    intersections.Add(edgeIntersection);
                    return(intersections);
                }

                // If not, the intersection can pass through both diagonal extremes, so its external.
                // Through just on, so only one intersection, or non and endge is inside polygon.

                if (this.Vertices.First().OnEdge(edgeIntersection))
                {
                    intersections.Add(this.Vertices.First());
                }
                if (this.Vertices[midIndex].OnEdge(edgeIntersection))
                {
                    intersections.Add(this.Vertices[midIndex]);
                }

                return(intersections);
            }

            // If intersection is a Vertex
            if (intersection is Vertex vertexIntersection)
            {
                if (vertexIntersection.Equals(this.Vertices.First()))
                {
                    throw new NotImplementedException();
                }

                if (vertexIntersection.Equals(this.Vertices[midIndex]))
                {
                    throw new NotImplementedException();
                }

                // Else the intersection is between the diagonal's extremes
                // find intersection at each side of the mid vertex

                // Going from midVertex to 0
                for (int i = midIndex; i > 0; i--)
                {
                    var    side             = DiagonalByVertexIndex(i, i - 1);
                    Vertex sideIntersection = edge.Intersection(side) as Vertex;
                    if (sideIntersection != null)
                    {
                        intersections.Add(sideIntersection);
                        break;
                    }
                }

                for (int j = midIndex; j < vertexCount; j++)
                {
                    int    next             = (j + 1) % vertexCount;
                    var    side             = DiagonalByVertexIndex(j, next);
                    Vertex sideIntersection = edge.Intersection(side) as Vertex;
                    if (sideIntersection != null)
                    {
                        intersections.Add(sideIntersection);
                        break;
                    }
                }

                return(intersections);
            }

            return(intersections);
        }