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); }
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); }