earcut.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. #pragma once
  2. #include <algorithm>
  3. #include <cassert>
  4. #include <cmath>
  5. #include <cstddef>
  6. #include <cstdint>
  7. #include <limits>
  8. #include <memory>
  9. #include <utility>
  10. #include <vector>
  11. namespace mapbox {
  12. namespace util {
  13. template <std::size_t I, typename T> struct nth {
  14. inline static typename std::tuple_element<I, T>::type
  15. get(const T& t) { return std::get<I>(t); };
  16. };
  17. }
  18. namespace detail {
  19. template <typename N = uint32_t>
  20. class Earcut {
  21. public:
  22. std::vector<N> indices;
  23. std::size_t vertices = 0;
  24. template <typename Polygon>
  25. void operator()(const Polygon& points);
  26. private:
  27. struct Node {
  28. Node(N index, double x_, double y_) : i(index), x(x_), y(y_) {}
  29. Node(const Node&) = delete;
  30. Node& operator=(const Node&) = delete;
  31. Node(Node&&) = delete;
  32. Node& operator=(Node&&) = delete;
  33. const N i;
  34. const double x;
  35. const double y;
  36. // previous and next vertice nodes in a polygon ring
  37. Node* prev = nullptr;
  38. Node* next = nullptr;
  39. // z-order curve value
  40. int32_t z = 0;
  41. // previous and next nodes in z-order
  42. Node* prevZ = nullptr;
  43. Node* nextZ = nullptr;
  44. // indicates whether this is a steiner point
  45. bool steiner = false;
  46. };
  47. template <typename Ring> Node* linkedList(const Ring& points, const bool clockwise);
  48. Node* filterPoints(Node* start, Node* end = nullptr);
  49. void earcutLinked(Node* ear, int pass = 0);
  50. bool isEar(Node* ear);
  51. bool isEarHashed(Node* ear);
  52. Node* cureLocalIntersections(Node* start);
  53. void splitEarcut(Node* start);
  54. template <typename Polygon> Node* eliminateHoles(const Polygon& points, Node* outerNode);
  55. Node* eliminateHole(Node* hole, Node* outerNode);
  56. Node* findHoleBridge(Node* hole, Node* outerNode);
  57. bool sectorContainsSector(const Node* m, const Node* p);
  58. void indexCurve(Node* start);
  59. Node* sortLinked(Node* list);
  60. int32_t zOrder(const double x_, const double y_);
  61. Node* getLeftmost(Node* start);
  62. bool pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const;
  63. bool isValidDiagonal(Node* a, Node* b);
  64. double area(const Node* p, const Node* q, const Node* r) const;
  65. bool equals(const Node* p1, const Node* p2);
  66. bool intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2);
  67. bool onSegment(const Node* p, const Node* q, const Node* r);
  68. int sign(double val);
  69. bool intersectsPolygon(const Node* a, const Node* b);
  70. bool locallyInside(const Node* a, const Node* b);
  71. bool middleInside(const Node* a, const Node* b);
  72. Node* splitPolygon(Node* a, Node* b);
  73. template <typename Point> Node* insertNode(std::size_t i, const Point& p, Node* last);
  74. void removeNode(Node* p);
  75. bool hashing;
  76. double minX, maxX;
  77. double minY, maxY;
  78. double inv_size = 0;
  79. template <typename T, typename Alloc = std::allocator<T>>
  80. class ObjectPool {
  81. public:
  82. ObjectPool() { }
  83. ObjectPool(std::size_t blockSize_) {
  84. reset(blockSize_);
  85. }
  86. ~ObjectPool() {
  87. clear();
  88. }
  89. template <typename... Args>
  90. T* construct(Args&&... args) {
  91. if (currentIndex >= blockSize) {
  92. currentBlock = alloc_traits::allocate(alloc, blockSize);
  93. allocations.emplace_back(currentBlock);
  94. currentIndex = 0;
  95. }
  96. T* object = &currentBlock[currentIndex++];
  97. alloc_traits::construct(alloc, object, std::forward<Args>(args)...);
  98. return object;
  99. }
  100. void reset(std::size_t newBlockSize) {
  101. for (auto allocation : allocations) {
  102. alloc_traits::deallocate(alloc, allocation, blockSize);
  103. }
  104. allocations.clear();
  105. blockSize = std::max<std::size_t>(1, newBlockSize);
  106. currentBlock = nullptr;
  107. currentIndex = blockSize;
  108. }
  109. void clear() { reset(blockSize); }
  110. private:
  111. T* currentBlock = nullptr;
  112. std::size_t currentIndex = 1;
  113. std::size_t blockSize = 1;
  114. std::vector<T*> allocations;
  115. Alloc alloc;
  116. typedef typename std::allocator_traits<Alloc> alloc_traits;
  117. };
  118. ObjectPool<Node> nodes;
  119. };
  120. template <typename N> template <typename Polygon>
  121. void Earcut<N>::operator()(const Polygon& points) {
  122. // reset
  123. indices.clear();
  124. vertices = 0;
  125. if (points.empty()) return;
  126. double x;
  127. double y;
  128. int threshold = 80;
  129. std::size_t len = 0;
  130. for (size_t i = 0; threshold >= 0 && i < points.size(); i++) {
  131. threshold -= static_cast<int>(points[i].size());
  132. len += points[i].size();
  133. }
  134. //estimate size of nodes and indices
  135. nodes.reset(len * 3 / 2);
  136. indices.reserve(len + points[0].size());
  137. Node* outerNode = linkedList(points[0], true);
  138. if (!outerNode || outerNode->prev == outerNode->next) return;
  139. if (points.size() > 1) outerNode = eliminateHoles(points, outerNode);
  140. // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
  141. hashing = threshold < 0;
  142. if (hashing) {
  143. Node* p = outerNode->next;
  144. minX = maxX = outerNode->x;
  145. minY = maxY = outerNode->y;
  146. do {
  147. x = p->x;
  148. y = p->y;
  149. minX = std::min<double>(minX, x);
  150. minY = std::min<double>(minY, y);
  151. maxX = std::max<double>(maxX, x);
  152. maxY = std::max<double>(maxY, y);
  153. p = p->next;
  154. } while (p != outerNode);
  155. // minX, minY and inv_size are later used to transform coords into integers for z-order calculation
  156. inv_size = std::max<double>(maxX - minX, maxY - minY);
  157. inv_size = inv_size != .0 ? (32767. / inv_size) : .0;
  158. }
  159. earcutLinked(outerNode);
  160. nodes.clear();
  161. }
  162. // create a circular doubly linked list from polygon points in the specified winding order
  163. template <typename N> template <typename Ring>
  164. typename Earcut<N>::Node*
  165. Earcut<N>::linkedList(const Ring& points, const bool clockwise) {
  166. using Point = typename Ring::value_type;
  167. double sum = 0;
  168. const std::size_t len = points.size();
  169. std::size_t i, j;
  170. Node* last = nullptr;
  171. // calculate original winding order of a polygon ring
  172. for (i = 0, j = len > 0 ? len - 1 : 0; i < len; j = i++) {
  173. const auto& p1 = points[i];
  174. const auto& p2 = points[j];
  175. const double p20 = util::nth<0, Point>::get(p2);
  176. const double p10 = util::nth<0, Point>::get(p1);
  177. const double p11 = util::nth<1, Point>::get(p1);
  178. const double p21 = util::nth<1, Point>::get(p2);
  179. sum += (p20 - p10) * (p11 + p21);
  180. }
  181. // link points into circular doubly-linked list in the specified winding order
  182. if (clockwise == (sum > 0)) {
  183. for (i = 0; i < len; i++) last = insertNode(vertices + i, points[i], last);
  184. } else {
  185. for (i = len; i-- > 0;) last = insertNode(vertices + i, points[i], last);
  186. }
  187. if (last && equals(last, last->next)) {
  188. removeNode(last);
  189. last = last->next;
  190. }
  191. vertices += len;
  192. return last;
  193. }
  194. // eliminate colinear or duplicate points
  195. template <typename N>
  196. typename Earcut<N>::Node*
  197. Earcut<N>::filterPoints(Node* start, Node* end) {
  198. if (!end) end = start;
  199. Node* p = start;
  200. bool again;
  201. do {
  202. again = false;
  203. if (!p->steiner && (equals(p, p->next) || area(p->prev, p, p->next) == 0)) {
  204. removeNode(p);
  205. p = end = p->prev;
  206. if (p == p->next) break;
  207. again = true;
  208. } else {
  209. p = p->next;
  210. }
  211. } while (again || p != end);
  212. return end;
  213. }
  214. // main ear slicing loop which triangulates a polygon (given as a linked list)
  215. template <typename N>
  216. void Earcut<N>::earcutLinked(Node* ear, int pass) {
  217. if (!ear) return;
  218. // interlink polygon nodes in z-order
  219. if (!pass && hashing) indexCurve(ear);
  220. Node* stop = ear;
  221. Node* prev;
  222. Node* next;
  223. // iterate through ears, slicing them one by one
  224. while (ear->prev != ear->next) {
  225. prev = ear->prev;
  226. next = ear->next;
  227. if (hashing ? isEarHashed(ear) : isEar(ear)) {
  228. // cut off the triangle
  229. indices.emplace_back(prev->i);
  230. indices.emplace_back(ear->i);
  231. indices.emplace_back(next->i);
  232. removeNode(ear);
  233. // skipping the next vertice leads to less sliver triangles
  234. ear = next->next;
  235. stop = next->next;
  236. continue;
  237. }
  238. ear = next;
  239. // if we looped through the whole remaining polygon and can't find any more ears
  240. if (ear == stop) {
  241. // try filtering points and slicing again
  242. if (!pass) earcutLinked(filterPoints(ear), 1);
  243. // if this didn't work, try curing all small self-intersections locally
  244. else if (pass == 1) {
  245. ear = cureLocalIntersections(filterPoints(ear));
  246. earcutLinked(ear, 2);
  247. // as a last resort, try splitting the remaining polygon into two
  248. } else if (pass == 2) splitEarcut(ear);
  249. break;
  250. }
  251. }
  252. }
  253. // check whether a polygon node forms a valid ear with adjacent nodes
  254. template <typename N>
  255. bool Earcut<N>::isEar(Node* ear) {
  256. const Node* a = ear->prev;
  257. const Node* b = ear;
  258. const Node* c = ear->next;
  259. if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
  260. // now make sure we don't have other points inside the potential ear
  261. Node* p = ear->next->next;
  262. while (p != ear->prev) {
  263. if (pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
  264. area(p->prev, p, p->next) >= 0) return false;
  265. p = p->next;
  266. }
  267. return true;
  268. }
  269. template <typename N>
  270. bool Earcut<N>::isEarHashed(Node* ear) {
  271. const Node* a = ear->prev;
  272. const Node* b = ear;
  273. const Node* c = ear->next;
  274. if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
  275. // triangle bbox; min & max are calculated like this for speed
  276. const double minTX = std::min<double>(a->x, std::min<double>(b->x, c->x));
  277. const double minTY = std::min<double>(a->y, std::min<double>(b->y, c->y));
  278. const double maxTX = std::max<double>(a->x, std::max<double>(b->x, c->x));
  279. const double maxTY = std::max<double>(a->y, std::max<double>(b->y, c->y));
  280. // z-order range for the current triangle bbox;
  281. const int32_t minZ = zOrder(minTX, minTY);
  282. const int32_t maxZ = zOrder(maxTX, maxTY);
  283. // first look for points inside the triangle in increasing z-order
  284. Node* p = ear->nextZ;
  285. while (p && p->z <= maxZ) {
  286. if (p != ear->prev && p != ear->next &&
  287. pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
  288. area(p->prev, p, p->next) >= 0) return false;
  289. p = p->nextZ;
  290. }
  291. // then look for points in decreasing z-order
  292. p = ear->prevZ;
  293. while (p && p->z >= minZ) {
  294. if (p != ear->prev && p != ear->next &&
  295. pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
  296. area(p->prev, p, p->next) >= 0) return false;
  297. p = p->prevZ;
  298. }
  299. return true;
  300. }
  301. // go through all polygon nodes and cure small local self-intersections
  302. template <typename N>
  303. typename Earcut<N>::Node*
  304. Earcut<N>::cureLocalIntersections(Node* start) {
  305. Node* p = start;
  306. do {
  307. Node* a = p->prev;
  308. Node* b = p->next->next;
  309. // a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2])
  310. if (!equals(a, b) && intersects(a, p, p->next, b) && locallyInside(a, b) && locallyInside(b, a)) {
  311. indices.emplace_back(a->i);
  312. indices.emplace_back(p->i);
  313. indices.emplace_back(b->i);
  314. // remove two nodes involved
  315. removeNode(p);
  316. removeNode(p->next);
  317. p = start = b;
  318. }
  319. p = p->next;
  320. } while (p != start);
  321. return filterPoints(p);
  322. }
  323. // try splitting polygon into two and triangulate them independently
  324. template <typename N>
  325. void Earcut<N>::splitEarcut(Node* start) {
  326. // look for a valid diagonal that divides the polygon into two
  327. Node* a = start;
  328. do {
  329. Node* b = a->next->next;
  330. while (b != a->prev) {
  331. if (a->i != b->i && isValidDiagonal(a, b)) {
  332. // split the polygon in two by the diagonal
  333. Node* c = splitPolygon(a, b);
  334. // filter colinear points around the cuts
  335. a = filterPoints(a, a->next);
  336. c = filterPoints(c, c->next);
  337. // run earcut on each half
  338. earcutLinked(a);
  339. earcutLinked(c);
  340. return;
  341. }
  342. b = b->next;
  343. }
  344. a = a->next;
  345. } while (a != start);
  346. }
  347. // link every hole into the outer loop, producing a single-ring polygon without holes
  348. template <typename N> template <typename Polygon>
  349. typename Earcut<N>::Node*
  350. Earcut<N>::eliminateHoles(const Polygon& points, Node* outerNode) {
  351. const size_t len = points.size();
  352. std::vector<Node*> queue;
  353. for (size_t i = 1; i < len; i++) {
  354. Node* list = linkedList(points[i], false);
  355. if (list) {
  356. if (list == list->next) list->steiner = true;
  357. queue.push_back(getLeftmost(list));
  358. }
  359. }
  360. std::sort(queue.begin(), queue.end(), [](const Node* a, const Node* b) {
  361. return a->x < b->x;
  362. });
  363. // process holes from left to right
  364. for (size_t i = 0; i < queue.size(); i++) {
  365. outerNode = eliminateHole(queue[i], outerNode);
  366. }
  367. return outerNode;
  368. }
  369. // find a bridge between vertices that connects hole with an outer ring and and link it
  370. template <typename N>
  371. typename Earcut<N>::Node*
  372. Earcut<N>::eliminateHole(Node* hole, Node* outerNode) {
  373. Node* bridge = findHoleBridge(hole, outerNode);
  374. if (!bridge) {
  375. return outerNode;
  376. }
  377. Node* bridgeReverse = splitPolygon(bridge, hole);
  378. // filter collinear points around the cuts
  379. filterPoints(bridgeReverse, bridgeReverse->next);
  380. // Check if input node was removed by the filtering
  381. return filterPoints(bridge, bridge->next);
  382. }
  383. // David Eberly's algorithm for finding a bridge between hole and outer polygon
  384. template <typename N>
  385. typename Earcut<N>::Node*
  386. Earcut<N>::findHoleBridge(Node* hole, Node* outerNode) {
  387. Node* p = outerNode;
  388. double hx = hole->x;
  389. double hy = hole->y;
  390. double qx = -std::numeric_limits<double>::infinity();
  391. Node* m = nullptr;
  392. // find a segment intersected by a ray from the hole's leftmost Vertex to the left;
  393. // segment's endpoint with lesser x will be potential connection Vertex
  394. do {
  395. if (hy <= p->y && hy >= p->next->y && p->next->y != p->y) {
  396. double x = p->x + (hy - p->y) * (p->next->x - p->x) / (p->next->y - p->y);
  397. if (x <= hx && x > qx) {
  398. qx = x;
  399. m = p->x < p->next->x ? p : p->next;
  400. if (x == hx) return m; // hole touches outer segment; pick leftmost endpoint
  401. }
  402. }
  403. p = p->next;
  404. } while (p != outerNode);
  405. if (!m) return 0;
  406. // look for points inside the triangle of hole Vertex, segment intersection and endpoint;
  407. // if there are no points found, we have a valid connection;
  408. // otherwise choose the Vertex of the minimum angle with the ray as connection Vertex
  409. const Node* stop = m;
  410. double tanMin = std::numeric_limits<double>::infinity();
  411. double tanCur = 0;
  412. p = m;
  413. double mx = m->x;
  414. double my = m->y;
  415. do {
  416. if (hx >= p->x && p->x >= mx && hx != p->x &&
  417. pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p->x, p->y)) {
  418. tanCur = std::abs(hy - p->y) / (hx - p->x); // tangential
  419. if (locallyInside(p, hole) &&
  420. (tanCur < tanMin || (tanCur == tanMin && (p->x > m->x || sectorContainsSector(m, p))))) {
  421. m = p;
  422. tanMin = tanCur;
  423. }
  424. }
  425. p = p->next;
  426. } while (p != stop);
  427. return m;
  428. }
  429. // whether sector in vertex m contains sector in vertex p in the same coordinates
  430. template <typename N>
  431. bool Earcut<N>::sectorContainsSector(const Node* m, const Node* p) {
  432. return area(m->prev, m, p->prev) < 0 && area(p->next, m, m->next) < 0;
  433. }
  434. // interlink polygon nodes in z-order
  435. template <typename N>
  436. void Earcut<N>::indexCurve(Node* start) {
  437. assert(start);
  438. Node* p = start;
  439. do {
  440. p->z = p->z ? p->z : zOrder(p->x, p->y);
  441. p->prevZ = p->prev;
  442. p->nextZ = p->next;
  443. p = p->next;
  444. } while (p != start);
  445. p->prevZ->nextZ = nullptr;
  446. p->prevZ = nullptr;
  447. sortLinked(p);
  448. }
  449. // Simon Tatham's linked list merge sort algorithm
  450. // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
  451. template <typename N>
  452. typename Earcut<N>::Node*
  453. Earcut<N>::sortLinked(Node* list) {
  454. assert(list);
  455. Node* p;
  456. Node* q;
  457. Node* e;
  458. Node* tail;
  459. int i, numMerges, pSize, qSize;
  460. int inSize = 1;
  461. for (;;) {
  462. p = list;
  463. list = nullptr;
  464. tail = nullptr;
  465. numMerges = 0;
  466. while (p) {
  467. numMerges++;
  468. q = p;
  469. pSize = 0;
  470. for (i = 0; i < inSize; i++) {
  471. pSize++;
  472. q = q->nextZ;
  473. if (!q) break;
  474. }
  475. qSize = inSize;
  476. while (pSize > 0 || (qSize > 0 && q)) {
  477. if (pSize == 0) {
  478. e = q;
  479. q = q->nextZ;
  480. qSize--;
  481. } else if (qSize == 0 || !q) {
  482. e = p;
  483. p = p->nextZ;
  484. pSize--;
  485. } else if (p->z <= q->z) {
  486. e = p;
  487. p = p->nextZ;
  488. pSize--;
  489. } else {
  490. e = q;
  491. q = q->nextZ;
  492. qSize--;
  493. }
  494. if (tail) tail->nextZ = e;
  495. else list = e;
  496. e->prevZ = tail;
  497. tail = e;
  498. }
  499. p = q;
  500. }
  501. tail->nextZ = nullptr;
  502. if (numMerges <= 1) return list;
  503. inSize *= 2;
  504. }
  505. }
  506. // z-order of a Vertex given coords and size of the data bounding box
  507. template <typename N>
  508. int32_t Earcut<N>::zOrder(const double x_, const double y_) {
  509. // coords are transformed into non-negative 15-bit integer range
  510. int32_t x = static_cast<int32_t>((x_ - minX) * inv_size);
  511. int32_t y = static_cast<int32_t>((y_ - minY) * inv_size);
  512. x = (x | (x << 8)) & 0x00FF00FF;
  513. x = (x | (x << 4)) & 0x0F0F0F0F;
  514. x = (x | (x << 2)) & 0x33333333;
  515. x = (x | (x << 1)) & 0x55555555;
  516. y = (y | (y << 8)) & 0x00FF00FF;
  517. y = (y | (y << 4)) & 0x0F0F0F0F;
  518. y = (y | (y << 2)) & 0x33333333;
  519. y = (y | (y << 1)) & 0x55555555;
  520. return x | (y << 1);
  521. }
  522. // find the leftmost node of a polygon ring
  523. template <typename N>
  524. typename Earcut<N>::Node*
  525. Earcut<N>::getLeftmost(Node* start) {
  526. Node* p = start;
  527. Node* leftmost = start;
  528. do {
  529. if (p->x < leftmost->x || (p->x == leftmost->x && p->y < leftmost->y))
  530. leftmost = p;
  531. p = p->next;
  532. } while (p != start);
  533. return leftmost;
  534. }
  535. // check if a point lies within a convex triangle
  536. template <typename N>
  537. bool Earcut<N>::pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const {
  538. return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&
  539. (ax - px) * (by - py) >= (bx - px) * (ay - py) &&
  540. (bx - px) * (cy - py) >= (cx - px) * (by - py);
  541. }
  542. // check if a diagonal between two polygon nodes is valid (lies in polygon interior)
  543. template <typename N>
  544. bool Earcut<N>::isValidDiagonal(Node* a, Node* b) {
  545. return a->next->i != b->i && a->prev->i != b->i && !intersectsPolygon(a, b) && // dones't intersect other edges
  546. ((locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
  547. (area(a->prev, a, b->prev) != 0.0 || area(a, b->prev, b) != 0.0)) || // does not create opposite-facing sectors
  548. (equals(a, b) && area(a->prev, a, a->next) > 0 && area(b->prev, b, b->next) > 0)); // special zero-length case
  549. }
  550. // signed area of a triangle
  551. template <typename N>
  552. double Earcut<N>::area(const Node* p, const Node* q, const Node* r) const {
  553. return (q->y - p->y) * (r->x - q->x) - (q->x - p->x) * (r->y - q->y);
  554. }
  555. // check if two points are equal
  556. template <typename N>
  557. bool Earcut<N>::equals(const Node* p1, const Node* p2) {
  558. return p1->x == p2->x && p1->y == p2->y;
  559. }
  560. // check if two segments intersect
  561. template <typename N>
  562. bool Earcut<N>::intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2) {
  563. int o1 = sign(area(p1, q1, p2));
  564. int o2 = sign(area(p1, q1, q2));
  565. int o3 = sign(area(p2, q2, p1));
  566. int o4 = sign(area(p2, q2, q1));
  567. if (o1 != o2 && o3 != o4) return true; // general case
  568. if (o1 == 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
  569. if (o2 == 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
  570. if (o3 == 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
  571. if (o4 == 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
  572. return false;
  573. }
  574. // for collinear points p, q, r, check if point q lies on segment pr
  575. template <typename N>
  576. bool Earcut<N>::onSegment(const Node* p, const Node* q, const Node* r) {
  577. return q->x <= std::max<double>(p->x, r->x) &&
  578. q->x >= std::min<double>(p->x, r->x) &&
  579. q->y <= std::max<double>(p->y, r->y) &&
  580. q->y >= std::min<double>(p->y, r->y);
  581. }
  582. template <typename N>
  583. int Earcut<N>::sign(double val) {
  584. return (0.0 < val) - (val < 0.0);
  585. }
  586. // check if a polygon diagonal intersects any polygon segments
  587. template <typename N>
  588. bool Earcut<N>::intersectsPolygon(const Node* a, const Node* b) {
  589. const Node* p = a;
  590. do {
  591. if (p->i != a->i && p->next->i != a->i && p->i != b->i && p->next->i != b->i &&
  592. intersects(p, p->next, a, b)) return true;
  593. p = p->next;
  594. } while (p != a);
  595. return false;
  596. }
  597. // check if a polygon diagonal is locally inside the polygon
  598. template <typename N>
  599. bool Earcut<N>::locallyInside(const Node* a, const Node* b) {
  600. return area(a->prev, a, a->next) < 0 ?
  601. area(a, b, a->next) >= 0 && area(a, a->prev, b) >= 0 :
  602. area(a, b, a->prev) < 0 || area(a, a->next, b) < 0;
  603. }
  604. // check if the middle Vertex of a polygon diagonal is inside the polygon
  605. template <typename N>
  606. bool Earcut<N>::middleInside(const Node* a, const Node* b) {
  607. const Node* p = a;
  608. bool inside = false;
  609. double px = (a->x + b->x) / 2;
  610. double py = (a->y + b->y) / 2;
  611. do {
  612. if (((p->y > py) != (p->next->y > py)) && p->next->y != p->y &&
  613. (px < (p->next->x - p->x) * (py - p->y) / (p->next->y - p->y) + p->x))
  614. inside = !inside;
  615. p = p->next;
  616. } while (p != a);
  617. return inside;
  618. }
  619. // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits
  620. // polygon into two; if one belongs to the outer ring and another to a hole, it merges it into a
  621. // single ring
  622. template <typename N>
  623. typename Earcut<N>::Node*
  624. Earcut<N>::splitPolygon(Node* a, Node* b) {
  625. Node* a2 = nodes.construct(a->i, a->x, a->y);
  626. Node* b2 = nodes.construct(b->i, b->x, b->y);
  627. Node* an = a->next;
  628. Node* bp = b->prev;
  629. a->next = b;
  630. b->prev = a;
  631. a2->next = an;
  632. an->prev = a2;
  633. b2->next = a2;
  634. a2->prev = b2;
  635. bp->next = b2;
  636. b2->prev = bp;
  637. return b2;
  638. }
  639. // create a node and util::optionally link it with previous one (in a circular doubly linked list)
  640. template <typename N> template <typename Point>
  641. typename Earcut<N>::Node*
  642. Earcut<N>::insertNode(std::size_t i, const Point& pt, Node* last) {
  643. Node* p = nodes.construct(static_cast<N>(i), util::nth<0, Point>::get(pt), util::nth<1, Point>::get(pt));
  644. if (!last) {
  645. p->prev = p;
  646. p->next = p;
  647. } else {
  648. assert(last);
  649. p->next = last->next;
  650. p->prev = last;
  651. last->next->prev = p;
  652. last->next = p;
  653. }
  654. return p;
  655. }
  656. template <typename N>
  657. void Earcut<N>::removeNode(Node* p) {
  658. p->next->prev = p->prev;
  659. p->prev->next = p->next;
  660. if (p->prevZ) p->prevZ->nextZ = p->nextZ;
  661. if (p->nextZ) p->nextZ->prevZ = p->prevZ;
  662. }
  663. }
  664. template <typename N = uint32_t, typename Polygon>
  665. std::vector<N> earcut(const Polygon& poly) {
  666. mapbox::detail::Earcut<N> earcut;
  667. earcut(poly);
  668. return std::move(earcut.indices);
  669. }
  670. }