
William S. answered 04/26/21
Senior Software Engineer with 15+ Years of Professional C# Experience
This is an interesting problem, which I address below in pseudocode form. Unfortunately, there is a character limit for these answers, so I am not able to also include actual C# code. Perhaps it will be possible to attach a code sample as a comment.
We can make a couple of preliminary observations:
- Only polygons with four or more sides can have sides that cross each other.
- No two neighboring sides on the path defining the polygon can cross.
Consider the general case for an n-sided polygon. At a high level, a workable algorithm could go something like this:
- Establish an empty list, SidePairs.
- For each side S in the polygon:
- For each other side Sother in the polygon:
- Determine whether Sother is a neighbor of S along the point path.
- If S and Sother are not neighbors, AND if SidePairs does not already contain the pair (S, Sother), add the pair to SidePairs.
- For each side pair in SidePairs:
- Execute a function HasIntersection(Side1, Side2), to see if the two sides in the pair intersect
- If the side pair intersects, either return immediately, or flag the side pair and continue.
- Report out the result as a boolean, or as a list of all intersecting side pairs.
Now let's look at the function HasIntersection. Comparing two line segments to see if they intersect is somewhat like asking whether two geometric lines intersect, except that unlike geometric lines, line segments are defined only on a restricted domain:
xlower bound <= x <= xupper bound
This restricted domain is the "shadow" a line segment casts on the x-axis.
Two line segments can only intersect if their shadows overlap, because only then can there be an x-value for which both share the same y-value. This test should be the first step in HasIntersection.
Each line segment has two (x, y) endpoints. We need only look at the four endpoint x-coordinate values to determine whether there is overlap, and if so what the overlapping domain is:
- For each pair of line segments S1, S2, where S1 has lower and upper endpoint x-values xS1Low and xS1High, and S2 has lower and upper endpoint x-values xS2Low and xS2High:
- Find the maximum lower x- value: xLowerMax = MAX(xS1Min, xS2Min)
- Find the minimum upper x-value: xupperMin = MIN(xS1Min, xS2Min)
- Execute the following CASE logic:
- If xLowerMax < xupperMin the domains overlap, and the overlapping includes all x values between xLowerMax and xupperMin. An intersection of line segments is possible.
- Determine whether the segments actually intersect by calling another function, LinesIntersectOnSharedDomain. More about that later.
- If xLowerMax > xupperMin, the two line segment have no domain overlap, so there can be no intersection. No further analysis is needed.
- If xLowerMax = xupperMin, the two line segment domains overlap at a single point on the x-axis. If the y-values there are equal, the line segments touch to form a vertex. Since we have already excluded immediate neighbors, this happens when a line segment "re-contacts" an earlier-defined vertex point. This is not a true crossing, so no further analysis is needed.
Finally, here is the pseudocode for LinesIntersectOnSharedDomain:
- For the line segments S1, S2, obtain the equation of the lines passing through their endpoints.
- Determine the (x, y) intersection point of the two lines if they are not parallel.
- If the x-value in the (x, y) intersection point lies inside the overlapping domain xLowerMax <= x <= xupperMin, the line segments intersect. Otherwise, they do not.