1 module measure.chull; 2 3 import std.algorithm; 4 import std.algorithm.sorting; 5 import std.stdio; 6 import std.math; 7 8 import measure.types; 9 import measure.regionprops; 10 11 /* https://rosettacode.org/wiki/Convex_hull 12 https://www.gnu.org/licenses/fdl-1.2.html 13 */ 14 15 XYList convexHull(XYList _p) { 16 auto n = _p.xs.length; 17 assert( n >= 3, "Convex hull not possible"); 18 19 Point[] p; p.length = n; foreach(i; 0..n) p[i] = Point(_p.xs[i], _p.ys[i]); 20 p.sort(); 21 Point[] h; 22 23 // lower hull 24 foreach (pt; p) { 25 while (h.length >= 2 && !ccw(h[$-2], h[$-1], pt)) { 26 h.length--; 27 } 28 h ~= pt; 29 } 30 31 // upper hull 32 auto t = h.length + 1; 33 foreach_reverse (i; 0..(p.length - 1)) { 34 auto pt = p[i]; 35 while (h.length >= t && !ccw(h[$-2], h[$-1], pt)) { 36 h.length--; 37 } 38 h ~= pt; 39 } 40 41 h.length--; 42 43 XYList xys; 44 foreach(i; 0..h.length) 45 { 46 xys.xs ~= h[i].x; 47 xys.ys ~= h[i].y; 48 } 49 return xys; 50 } 51 52 /* ccw returns true if the three points make a counter-clockwise turn */ 53 auto ccw(Point a, Point b, Point c) @nogc { 54 return ((b.x - a.x) * (c.y - a.y)) > ((b.y - a.y) * (c.x - a.x)); 55 } 56