The original algorithm is given here. I post the slightly revised version since it perfectly fits the question.
The "deintersection" algorithm
Let us start from some random polygon with $n$ randomly placed vertices. Initially, it has a lot of self-intersections
SeedRandom[0];
n = 10;
p = RandomReal[1.0, {n, 2}];
Graphics[{Lighter@Red, EdgeForm@Thickness[0.01], EdgeForm@Red,
Polygon[p]}]
We want to change the order of these points to get rid of the intersections.
Line segments $(p_1,p_2)$ and $(p_3,p_4)$ intersect if and only if the signs of areas of triangles $p_1p_2p_3$ and $p_1p_2p_4$ are different and the signs of areas of triangles $p_3p_4p_1$ and $p_3p_4p_1$ are also different.
Corresponding function
SignedArea[p1_, p2_, p3_] :=
0.5 (#1[[2]] #2[[1]] - #1[[1]] #2[[2]]) &[p2 - p1, p3 - p1];
IntersectionQ[p1_, p2_, p3_, p4_] :=
SignedArea[p1, p2, p3] SignedArea[p1, p2, p4] < 0 &&
SignedArea[p3, p4, p1] SignedArea[p3, p4, p2] < 0;
The main step:
Patterns in Mathematica are very convenient for searching and removing intersections.
Deintersect[p_] :=
Append[p, p[[1]]] //.
{s1___, p1_, p2_, s2___, p3_, p4_, s3___} /; IntersectionQ[p1, p2, p3, p4] :>
({s1, p1, p3, Sequence @@ Reverse@{s2}, p2, p4, s3}) // Most;
To add the segment between the last and the first point I use Append
and Most
.
As a result we obtain the polygon without intersections
p2 = Deintersect[p];
Graphics[{Lighter@Red, EdgeForm@Thickness[0.01], EdgeForm@Red,
Polygon[p2]}]
p = {{-1, 1}, {1, 1}, {-1, -1}, {1, -1}, {0, 0}}
; what polygon should be plotted? $\endgroup$