1 module dkh.geo.polygon;
2 
3 import dkh.geo.primitive;
4 
5 inout(Point2D!R) at(R)(inout Point2D!R[] pol, size_t i) {
6     return pol[i<pol.length?i:i-pol.length];
7 }
8 
9 //0:P is out 1:P is on line 2:P is in
10 int contains(R)(Point2D!R[] pol, Point2D!R p) {
11     import std.algorithm : swap;
12     int res = -1;
13     foreach (i; 0..pol.length) {
14         auto a = pol.at(i) - p, b = pol.at(i+1) - p;
15         if (ccw(a, b, Point2D!R(0, 0)) == 0) return 1;
16         if (a.y > b.y) swap(a, b);
17         if (a.y <= 0 && 0 < b.y) {
18             if (cross(a, b) < 0) res *= -1;
19         }
20     }
21     return res+1;
22 }
23 
24 unittest {
25     alias P = Point2D!int;
26     P[] pol = [P(0, 0), P(2, 0), P(2, 2), P(0, 2)];
27     assert(contains(pol, P(-1, 0)) == 0);
28     assert(contains(pol, P(0, 0)) == 1);
29     assert(contains(pol, P(1, 1)) == 2);
30 }
31 
32 R area2(R)(Point2D!R[] pol) {
33     R u = 0;
34     foreach (i; 0..pol.length) {
35         auto a = pol.at(i), b = pol.at(i+1);
36         u += cross(a, b);
37     }
38     return u;
39 }
40 
41 unittest {
42     alias P = Point2D!int;
43     P[] pol = [P(0, 0), P(2, 0), P(2, 2), P(0, 2)];
44     assert(area2(pol) == 8);
45 }
46 
47 import dkh.container.stackpayload;
48 
49 Point2D!R[] convex(R)(Point2D!R[] _pol) {
50     import std.algorithm : sort;
51     import std.range : retro, array;
52     auto pol = _pol.dup;
53     pol.sort!((a, b) => robustCmp(a, b) == -1);
54     if (pol.length <= 2) return pol;
55     StackPayload!(Point2D!R) up;
56     foreach (d; pol) {
57         while (up.length >= 2 && ccw(up[$-2], up[$-1], d) == 1) up.removeBack();
58         up ~= d;
59     }
60     StackPayload!(Point2D!R) down;
61     foreach (d; pol) {
62         while (down.length >= 2 && ccw(down[$-2], down[$-1], d) == -1) down.removeBack();
63         down ~= d;
64     }
65     return up.data.retro.array[1..$-1] ~ down.data();
66 }
67 
68 unittest {
69     EPS!double = 1e-9;
70     alias P = Point2D!double;
71     P[] pol = [P(0, 0), P(2, 2), P(1, 1), P(0, 2), P(2, 0)];
72     import std.stdio;
73     assert(pol.convex.length == 4);
74 }