triangulator.cpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201
  1. // Begin License:
  2. // Copyright (C) 2006-2014 Tobias Sargeant (tobias.sargeant@gmail.com).
  3. // All rights reserved.
  4. //
  5. // This file is part of the Carve CSG Library (http://carve-csg.com/)
  6. //
  7. // This file may be used under the terms of either the GNU General
  8. // Public License version 2 or 3 (at your option) as published by the
  9. // Free Software Foundation and appearing in the files LICENSE.GPL2
  10. // and LICENSE.GPL3 included in the packaging of this file.
  11. //
  12. // This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
  13. // INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
  14. // A PARTICULAR PURPOSE.
  15. // End:
  16. #if defined(HAVE_CONFIG_H)
  17. # include <carve_config.h>
  18. #endif
  19. #include <carve/csg.hpp>
  20. #include <carve/triangulator.hpp>
  21. #include <fstream>
  22. #include <sstream>
  23. #include <algorithm>
  24. namespace {
  25. // private code related to hole patching.
  26. class order_h_loops_2d {
  27. order_h_loops_2d &operator=(const order_h_loops_2d &);
  28. const std::vector<std::vector<carve::geom2d::P2> > &poly;
  29. int axis;
  30. public:
  31. order_h_loops_2d(const std::vector<std::vector<carve::geom2d::P2> > &_poly, int _axis) :
  32. poly(_poly), axis(_axis) {
  33. }
  34. bool operator()(const std::pair<size_t, size_t> &a,
  35. const std::pair<size_t, size_t> &b) const {
  36. return carve::triangulate::detail::axisOrdering(poly[a.first][a.second], poly[b.first][b.second], axis);
  37. }
  38. };
  39. class heap_ordering_2d {
  40. heap_ordering_2d &operator=(const heap_ordering_2d &);
  41. const std::vector<std::vector<carve::geom2d::P2> > &poly;
  42. const std::vector<std::pair<size_t, size_t> > &loop;
  43. const carve::geom2d::P2 p;
  44. int axis;
  45. public:
  46. heap_ordering_2d(const std::vector<std::vector<carve::geom2d::P2> > &_poly,
  47. const std::vector<std::pair<size_t, size_t> > &_loop,
  48. const carve::geom2d::P2 _p,
  49. int _axis) : poly(_poly), loop(_loop), p(_p), axis(_axis) {
  50. }
  51. bool operator()(size_t a, size_t b) const {
  52. double da = carve::geom::distance2(p, poly[loop[a].first][loop[a].second]);
  53. double db = carve::geom::distance2(p, poly[loop[b].first][loop[b].second]);
  54. if (da > db) return true;
  55. if (da < db) return false;
  56. return carve::triangulate::detail::axisOrdering(poly[loop[a].first][loop[a].second], poly[loop[b].first][loop[b].second], axis);
  57. }
  58. };
  59. static inline void patchHoleIntoPolygon_2d(std::vector<std::pair<size_t, size_t> > &f_loop,
  60. size_t f_loop_attach,
  61. size_t h_loop,
  62. size_t h_loop_attach,
  63. size_t h_loop_size) {
  64. f_loop.insert(f_loop.begin() + f_loop_attach + 1, h_loop_size + 2, std::make_pair(h_loop, 0));
  65. size_t f = f_loop_attach + 1;
  66. for (size_t h = h_loop_attach; h != h_loop_size; ++h) {
  67. f_loop[f++].second = h;
  68. }
  69. for (size_t h = 0; h <= h_loop_attach; ++h) {
  70. f_loop[f++].second = h;
  71. }
  72. f_loop[f] = f_loop[f_loop_attach];
  73. }
  74. static inline const carve::geom2d::P2 &pvert(const std::vector<std::vector<carve::geom2d::P2> > &poly, const std::pair<size_t, size_t> &idx) {
  75. return poly[idx.first][idx.second];
  76. }
  77. }
  78. namespace {
  79. // private code related to triangulation.
  80. using carve::triangulate::detail::vertex_info;
  81. struct vertex_info_ordering {
  82. bool operator()(const vertex_info *a, const vertex_info *b) const {
  83. return a->score < b->score;
  84. }
  85. };
  86. struct vertex_info_l2norm_inc_ordering {
  87. const vertex_info *v;
  88. vertex_info_l2norm_inc_ordering(const vertex_info *_v) : v(_v) {
  89. }
  90. bool operator()(const vertex_info *a, const vertex_info *b) const {
  91. return carve::geom::distance2(v->p, a->p) > carve::geom::distance2(v->p, b->p);
  92. }
  93. };
  94. class EarQueue {
  95. std::vector<vertex_info *> queue;
  96. void checkheap() {
  97. #if defined(HAVE_IS_HEAP)
  98. CARVE_ASSERT(std::__is_heap(queue.begin(), queue.end(), vertex_info_ordering()));
  99. #endif
  100. }
  101. public:
  102. EarQueue() {
  103. }
  104. size_t size() const {
  105. return queue.size();
  106. }
  107. void push(vertex_info *v) {
  108. #if defined(CARVE_DEBUG)
  109. checkheap();
  110. #endif
  111. queue.push_back(v);
  112. std::push_heap(queue.begin(), queue.end(), vertex_info_ordering());
  113. }
  114. vertex_info *pop() {
  115. #if defined(CARVE_DEBUG)
  116. checkheap();
  117. #endif
  118. std::pop_heap(queue.begin(), queue.end(), vertex_info_ordering());
  119. vertex_info *v = queue.back();
  120. queue.pop_back();
  121. return v;
  122. }
  123. void remove(vertex_info *v) {
  124. #if defined(CARVE_DEBUG)
  125. checkheap();
  126. #endif
  127. CARVE_ASSERT(std::find(queue.begin(), queue.end(), v) != queue.end());
  128. double score = v->score;
  129. if (v != queue[0]) {
  130. v->score = queue[0]->score + 1;
  131. std::make_heap(queue.begin(), queue.end(), vertex_info_ordering());
  132. }
  133. CARVE_ASSERT(v == queue[0]);
  134. std::pop_heap(queue.begin(), queue.end(), vertex_info_ordering());
  135. CARVE_ASSERT(queue.back() == v);
  136. queue.pop_back();
  137. v->score = score;
  138. }
  139. void changeScore(vertex_info *v, double score) {
  140. #if defined(CARVE_DEBUG)
  141. checkheap();
  142. #endif
  143. CARVE_ASSERT(std::find(queue.begin(), queue.end(), v) != queue.end());
  144. if (v->score != score) {
  145. v->score = score;
  146. std::make_heap(queue.begin(), queue.end(), vertex_info_ordering());
  147. }
  148. }
  149. // 39% of execution time
  150. void updateVertex(vertex_info *v) {
  151. double spre = v->score;
  152. bool qpre = v->isCandidate();
  153. v->recompute();
  154. bool qpost = v->isCandidate();
  155. double spost = v->score;
  156. v->score = spre;
  157. if (qpre) {
  158. if (qpost) {
  159. if (v->score != spre) {
  160. changeScore(v, spost);
  161. }
  162. } else {
  163. remove(v);
  164. }
  165. } else {
  166. if (qpost) {
  167. push(v);
  168. }
  169. }
  170. }
  171. };
  172. int windingNumber(vertex_info *begin, const carve::geom2d::P2 &point) {
  173. int wn = 0;
  174. vertex_info *v = begin;
  175. do {
  176. if (v->p.y <= point.y) {
  177. if (v->next->p.y > point.y && carve::geom2d::orient2d(v->p, v->next->p, point) > 0.0) {
  178. ++wn;
  179. }
  180. } else {
  181. if (v->next->p.y <= point.y && carve::geom2d::orient2d(v->p, v->next->p, point) < 0.0) {
  182. --wn;
  183. }
  184. }
  185. v = v->next;
  186. } while (v != begin);
  187. return wn;
  188. }
  189. bool internalToAngle(const vertex_info *a,
  190. const vertex_info *b,
  191. const vertex_info *c,
  192. const carve::geom2d::P2 &p) {
  193. return carve::geom2d::internalToAngle(a->p, b->p, c->p, p);
  194. }
  195. bool findDiagonal(vertex_info *begin, vertex_info *&v1, vertex_info *&v2) {
  196. vertex_info *t;
  197. std::vector<vertex_info *> heap;
  198. v1 = begin;
  199. do {
  200. heap.clear();
  201. for (v2 = v1->next->next; v2 != v1->prev; v2 = v2->next) {
  202. if (!internalToAngle(v1->next, v1, v1->prev, v2->p) ||
  203. !internalToAngle(v2->next, v2, v2->prev, v1->p)) continue;
  204. heap.push_back(v2);
  205. std::push_heap(heap.begin(), heap.end(), vertex_info_l2norm_inc_ordering(v1));
  206. }
  207. while (heap.size()) {
  208. std::pop_heap(heap.begin(), heap.end(), vertex_info_l2norm_inc_ordering(v1));
  209. v2 = heap.back(); heap.pop_back();
  210. #if defined(CARVE_DEBUG)
  211. std::cerr << "testing: " << v1 << " - " << v2 << std::endl;
  212. std::cerr << " length = " << (v2->p - v1->p).length() << std::endl;
  213. std::cerr << " pos: " << v1->p << " - " << v2->p << std::endl;
  214. #endif
  215. // test whether v1-v2 is a valid diagonal.
  216. double v_min_x = std::min(v1->p.x, v2->p.x);
  217. double v_max_x = std::max(v1->p.x, v2->p.x);
  218. bool intersected = false;
  219. for (t = v1->next; !intersected && t != v1->prev; t = t->next) {
  220. vertex_info *u = t->next;
  221. if (t == v2 || u == v2) continue;
  222. double l1 = carve::geom2d::orient2d(v1->p, v2->p, t->p);
  223. double l2 = carve::geom2d::orient2d(v1->p, v2->p, u->p);
  224. if ((l1 > 0.0 && l2 > 0.0) || (l1 < 0.0 && l2 < 0.0)) {
  225. // both on the same side; no intersection
  226. continue;
  227. }
  228. double dx13 = v1->p.x - t->p.x;
  229. double dy13 = v1->p.y - t->p.y;
  230. double dx43 = u->p.x - t->p.x;
  231. double dy43 = u->p.y - t->p.y;
  232. double dx21 = v2->p.x - v1->p.x;
  233. double dy21 = v2->p.y - v1->p.y;
  234. double ua_n = dx43 * dy13 - dy43 * dx13;
  235. double ub_n = dx21 * dy13 - dy21 * dx13;
  236. double u_d = dy43 * dx21 - dx43 * dy21;
  237. if (carve::math::ZERO(u_d)) {
  238. // parallel
  239. if (carve::math::ZERO(ua_n)) {
  240. // colinear
  241. if (std::max(t->p.x, u->p.x) >= v_min_x && std::min(t->p.x, u->p.x) <= v_max_x) {
  242. // colinear and intersecting
  243. intersected = true;
  244. }
  245. }
  246. } else {
  247. // not parallel
  248. double ua = ua_n / u_d;
  249. double ub = ub_n / u_d;
  250. if (0.0 <= ua && ua <= 1.0 && 0.0 <= ub && ub <= 1.0) {
  251. intersected = true;
  252. }
  253. }
  254. #if defined(CARVE_DEBUG)
  255. if (intersected) {
  256. std::cerr << " failed on edge: " << t << " - " << u << std::endl;
  257. std::cerr << " pos: " << t->p << " - " << u->p << std::endl;
  258. }
  259. #endif
  260. }
  261. if (!intersected) {
  262. // test whether midpoint winding == 1
  263. carve::geom2d::P2 mid = (v1->p + v2->p) / 2;
  264. if (windingNumber(begin, mid) == 1) {
  265. // this diagonal is ok
  266. return true;
  267. }
  268. }
  269. }
  270. // couldn't find a diagonal from v1 that was ok.
  271. v1 = v1->next;
  272. } while (v1 != begin);
  273. return false;
  274. }
  275. #if defined(CARVE_DEBUG_WRITE_PLY_DATA)
  276. void dumpPoly(const std::vector<carve::geom2d::P2> &points,
  277. const std::vector<carve::triangulate::tri_idx> &result) {
  278. static int step = 0;
  279. std::ostringstream filename;
  280. filename << "poly_" << step++ << ".svg";
  281. std::cerr << "dumping to " << filename.str() << std::endl;
  282. std::ofstream out(filename.str().c_str());
  283. double minx = points[0].x, maxx = points[0].x;
  284. double miny = points[0].y, maxy = points[0].y;
  285. for (size_t i = 1; i < points.size(); ++i) {
  286. minx = std::min(points[i].x, minx); maxx = std::max(points[i].x, maxx);
  287. miny = std::min(points[i].y, miny); maxy = std::max(points[i].y, maxy);
  288. }
  289. double scale = 100 / std::max(maxx-minx, maxy-miny);
  290. maxx *= scale; minx *= scale;
  291. maxy *= scale; miny *= scale;
  292. double width = maxx - minx + 10;
  293. double height = maxy - miny + 10;
  294. out << "\
  295. <?xml version=\"1.0\"?>\n\
  296. <!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n\
  297. <svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"" << width << "\" height=\"" << height << "\">\n";
  298. out << "<polygon fill=\"rgb(0,0,0)\" stroke=\"blue\" stroke-width=\"0.1\" points=\"";
  299. for (size_t i = 0; i < points.size(); ++i) {
  300. if (i) out << ' ';
  301. double x, y;
  302. x = scale * (points[i].x) - minx + 5;
  303. y = scale * (points[i].y) - miny + 5;
  304. out << x << ',' << y;
  305. }
  306. out << "\" />" << std::endl;
  307. for (size_t i = 0; i < result.size(); ++i) {
  308. out << "<polygon fill=\"rgb(255,255,255)\" stroke=\"black\" stroke-width=\"0.1\" points=\"";
  309. double x, y;
  310. x = scale * (points[result[i].a].x) - minx + 5;
  311. y = scale * (points[result[i].a].y) - miny + 5;
  312. out << x << ',' << y << ' ';
  313. x = scale * (points[result[i].b].x) - minx + 5;
  314. y = scale * (points[result[i].b].y) - miny + 5;
  315. out << x << ',' << y << ' ';
  316. x = scale * (points[result[i].c].x) - minx + 5;
  317. y = scale * (points[result[i].c].y) - miny + 5;
  318. out << x << ',' << y;
  319. out << "\" />" << std::endl;
  320. }
  321. out << "</svg>" << std::endl;
  322. }
  323. #endif
  324. }
  325. double carve::triangulate::detail::vertex_info::triScore(const vertex_info *p, const vertex_info *v, const vertex_info *n) {
  326. // different scoring functions.
  327. #if 0
  328. bool convex = isLeft(p, v, n);
  329. if (!convex) return -1e-5;
  330. double a1 = carve::geom2d::atan2(p->p - v->p) - carve::geom2d::atan2(n->p - v->p);
  331. double a2 = carve::geom2d::atan2(v->p - n->p) - carve::geom2d::atan2(p->p - n->p);
  332. if (a1 < 0) a1 += M_PI * 2;
  333. if (a2 < 0) a2 += M_PI * 2;
  334. return std::min(a1, std::min(a2, M_PI - a1 - a2)) / (M_PI / 3);
  335. #endif
  336. #if 1
  337. // range: 0 - 1
  338. double a, b, c;
  339. bool convex = isLeft(p, v, n);
  340. if (!convex) return -1e-5;
  341. a = (n->p - v->p).length();
  342. b = (p->p - n->p).length();
  343. c = (v->p - p->p).length();
  344. if (a < 1e-10 || b < 1e-10 || c < 1e-10) return 0.0;
  345. return std::max(std::min((a+b)/c, std::min((a+c)/b, (b+c)/a)) - 1.0, 0.0);
  346. #endif
  347. }
  348. double carve::triangulate::detail::vertex_info::calcScore() const {
  349. #if 0
  350. // examine only this triangle.
  351. double this_tri = triScore(prev, this, next);
  352. return this_tri;
  353. #endif
  354. #if 1
  355. // attempt to look ahead in the neighbourhood to attempt to clip ears that have good neighbours.
  356. double this_tri = triScore(prev, this, next);
  357. double next_tri = triScore(prev, next, next->next);
  358. double prev_tri = triScore(prev->prev, prev, next);
  359. return this_tri + std::max(next_tri, prev_tri) * .2;
  360. #endif
  361. #if 0
  362. // attempt to penalise ears that will require producing a sliver triangle.
  363. double score = triScore(prev, this, next);
  364. double a1, a2;
  365. a1 = carve::geom2d::atan2(prev->p - next->p);
  366. a2 = carve::geom2d::atan2(next->next->p - next->p);
  367. if (fabs(a1 - a2) < 1e-5) score -= .5;
  368. a1 = carve::geom2d::atan2(next->p - prev->p);
  369. a2 = carve::geom2d::atan2(prev->prev->p - prev->p);
  370. if (fabs(a1 - a2) < 1e-5) score -= .5;
  371. return score;
  372. #endif
  373. }
  374. bool carve::triangulate::detail::vertex_info::isClipable() const {
  375. for (const vertex_info *v_test = next->next; v_test != prev; v_test = v_test->next) {
  376. if (v_test->convex) {
  377. continue;
  378. }
  379. if (v_test->p == prev->p ||
  380. v_test->p == next->p) {
  381. continue;
  382. }
  383. if (v_test->p == p) {
  384. if (v_test->next->p == prev->p &&
  385. v_test->prev->p == next->p) {
  386. return false;
  387. }
  388. if (v_test->next->p == prev->p ||
  389. v_test->prev->p == next->p) {
  390. continue;
  391. }
  392. }
  393. if (pointInTriangle(prev, this, next, v_test)) {
  394. return false;
  395. }
  396. }
  397. return true;
  398. }
  399. size_t carve::triangulate::detail::removeDegeneracies(vertex_info *&begin, std::vector<carve::triangulate::tri_idx> &result) {
  400. vertex_info *v;
  401. vertex_info *n;
  402. size_t count = 0;
  403. size_t remain = 0;
  404. v = begin;
  405. do {
  406. v = v->next;
  407. ++remain;
  408. } while (v != begin);
  409. v = begin;
  410. do {
  411. if (remain < 4) break;
  412. bool remove = false;
  413. if (v->p == v->next->p) {
  414. remove = true;
  415. } else if (v->p == v->next->next->p) {
  416. if (v->next->p == v->next->next->next->p) {
  417. // a 'z' in the loop: z (a) b a b c -> remove a-b-a -> z (a) a b c -> remove a-a-b (next loop) -> z a b c
  418. // z --(a)-- b
  419. // /
  420. // /
  421. // a -- b -- d
  422. remove = true;
  423. } else {
  424. // a 'shard' in the loop: z (a) b a c d -> remove a-b-a -> z (a) a b c d -> remove a-a-b (next loop) -> z a b c d
  425. // z --(a)-- b
  426. // /
  427. // /
  428. // a -- c -- d
  429. // n.b. can only do this if the shard is pointing out of the polygon. i.e. b is outside z-a-c
  430. remove = !internalToAngle(v->next->next->next, v, v->prev, v->next->p);
  431. }
  432. }
  433. if (remove) {
  434. result.push_back(carve::triangulate::tri_idx(v->idx, v->next->idx, v->next->next->idx));
  435. n = v->next;
  436. if (n == begin) begin = n->next;
  437. n->remove();
  438. count++;
  439. remain--;
  440. delete n;
  441. } else {
  442. v = v->next;
  443. }
  444. } while (v != begin);
  445. return count;
  446. }
  447. bool carve::triangulate::detail::splitAndResume(vertex_info *begin, std::vector<carve::triangulate::tri_idx> &result) {
  448. vertex_info *v1, *v2;
  449. #if defined(CARVE_DEBUG_WRITE_PLY_DATA)
  450. {
  451. std::vector<carve::triangulate::tri_idx> dummy;
  452. std::vector<carve::geom2d::P2> dummy_p;
  453. vertex_info *v = begin;
  454. do {
  455. dummy_p.push_back(v->p);
  456. v = v->next;
  457. } while (v != begin);
  458. std::cerr << "input to splitAndResume:" << std::endl;
  459. dumpPoly(dummy_p, dummy);
  460. }
  461. #endif
  462. if (!findDiagonal(begin, v1, v2)) return false;
  463. vertex_info *v1_copy = new vertex_info(*v1);
  464. vertex_info *v2_copy = new vertex_info(*v2);
  465. v1->next = v2;
  466. v2->prev = v1;
  467. v1_copy->next->prev = v1_copy;
  468. v2_copy->prev->next = v2_copy;
  469. v1_copy->prev = v2_copy;
  470. v2_copy->next = v1_copy;
  471. bool r1 = doTriangulate(v1, result);
  472. bool r2 = doTriangulate(v1_copy, result);
  473. return r1 && r2;
  474. }
  475. bool carve::triangulate::detail::doTriangulate(vertex_info *begin, std::vector<carve::triangulate::tri_idx> &result) {
  476. #if defined(CARVE_DEBUG)
  477. std::cerr << "entering doTriangulate" << std::endl;
  478. #endif
  479. #if defined(CARVE_DEBUG_WRITE_PLY_DATA)
  480. {
  481. std::vector<carve::triangulate::tri_idx> dummy;
  482. std::vector<carve::geom2d::P2> dummy_p;
  483. vertex_info *v = begin;
  484. do {
  485. dummy_p.push_back(v->p);
  486. v = v->next;
  487. } while (v != begin);
  488. dumpPoly(dummy_p, dummy);
  489. }
  490. #endif
  491. EarQueue vq;
  492. vertex_info *v = begin;
  493. size_t remain = 0;
  494. do {
  495. if (v->isCandidate()) vq.push(v);
  496. v = v->next;
  497. remain++;
  498. } while (v != begin);
  499. #if defined(CARVE_DEBUG)
  500. std::cerr << "remain = " << remain << std::endl;
  501. #endif
  502. while (remain > 3 && vq.size()) {
  503. vertex_info *v = vq.pop();
  504. if (!v->isClipable()) {
  505. v->failed = true;
  506. continue;
  507. }
  508. continue_clipping:
  509. vertex_info *n = v->next;
  510. vertex_info *p = v->prev;
  511. result.push_back(carve::triangulate::tri_idx(v->prev->idx, v->idx, v->next->idx));
  512. #if defined(CARVE_DEBUG)
  513. {
  514. std::vector<carve::geom2d::P2> temp;
  515. temp.push_back(v->prev->p);
  516. temp.push_back(v->p);
  517. temp.push_back(v->next->p);
  518. std::cerr << "clip " << v << " idx = " << v->idx << " score = " << v->score << " area = " << carve::geom2d::signedArea(temp) << " " << temp[0] << " " << temp[1] << " " << temp[2] << std::endl;
  519. }
  520. #endif
  521. v->remove();
  522. if (v == begin) begin = v->next;
  523. delete v;
  524. if (--remain == 3) break;
  525. vq.updateVertex(n);
  526. vq.updateVertex(p);
  527. if (n->score < p->score) { std::swap(n, p); }
  528. if (n->score > 0.25 && n->isCandidate() && n->isClipable()) {
  529. vq.remove(n);
  530. v = n;
  531. #if defined(CARVE_DEBUG)
  532. std::cerr << " continue clipping (n), score = " << n->score << std::endl;
  533. #endif
  534. goto continue_clipping;
  535. }
  536. if (p->score > 0.25 && p->isCandidate() && p->isClipable()) {
  537. vq.remove(p);
  538. v = p;
  539. #if defined(CARVE_DEBUG)
  540. std::cerr << " continue clipping (p), score = " << n->score << std::endl;
  541. #endif
  542. goto continue_clipping;
  543. }
  544. #if defined(CARVE_DEBUG)
  545. std::cerr << "looking for new start point" << std::endl;
  546. std::cerr << "remain = " << remain << std::endl;
  547. #endif
  548. }
  549. #if defined(CARVE_DEBUG)
  550. std::cerr << "doTriangulate complete; remain=" << remain << std::endl;
  551. #endif
  552. if (remain > 3) {
  553. #if defined(CARVE_DEBUG)
  554. std::cerr << "before removeDegeneracies: remain=" << remain << std::endl;
  555. #endif
  556. remain -= removeDegeneracies(begin, result);
  557. #if defined(CARVE_DEBUG)
  558. std::cerr << "after removeDegeneracies: remain=" << remain << std::endl;
  559. #endif
  560. if (remain > 3) {
  561. return splitAndResume(begin, result);
  562. }
  563. }
  564. if (remain == 3) {
  565. result.push_back(carve::triangulate::tri_idx(begin->idx, begin->next->idx, begin->next->next->idx));
  566. }
  567. vertex_info *d = begin;
  568. do {
  569. vertex_info *n = d->next;
  570. delete d;
  571. d = n;
  572. } while (d != begin);
  573. return true;
  574. }
  575. static bool testCandidateAttachment(const std::vector<std::vector<carve::geom2d::P2> > &poly,
  576. std::vector<std::pair<size_t, size_t> > &current_f_loop,
  577. size_t curr,
  578. carve::geom2d::P2 hole_min) {
  579. const size_t SZ = current_f_loop.size();
  580. if (!carve::geom2d::internalToAngle(pvert(poly, current_f_loop[(curr+1) % SZ]),
  581. pvert(poly, current_f_loop[curr]),
  582. pvert(poly, current_f_loop[(curr+SZ-1) % SZ]),
  583. hole_min)) {
  584. return false;
  585. }
  586. if (hole_min == pvert(poly, current_f_loop[curr])) {
  587. return true;
  588. }
  589. carve::geom2d::LineSegment2 test(hole_min, pvert(poly, current_f_loop[curr]));
  590. size_t v1 = current_f_loop.size() - 1;
  591. size_t v2 = 0;
  592. double v1_side = carve::geom2d::orient2d(test.v1, test.v2, pvert(poly, current_f_loop[v1]));
  593. double v2_side = 0;
  594. while (v2 != current_f_loop.size()) {
  595. v2_side = carve::geom2d::orient2d(test.v1, test.v2, pvert(poly, current_f_loop[v2]));
  596. if (v1_side != v2_side) {
  597. // XXX: need to test vertices, not indices, because they may
  598. // be duplicated.
  599. if (pvert(poly, current_f_loop[v1]) != pvert(poly, current_f_loop[curr]) &&
  600. pvert(poly, current_f_loop[v2]) != pvert(poly, current_f_loop[curr])) {
  601. carve::geom2d::LineSegment2 test2(pvert(poly, current_f_loop[v1]), pvert(poly, current_f_loop[v2]));
  602. if (carve::geom2d::lineSegmentIntersection_simple(test, test2)) {
  603. // intersection; failed.
  604. return false;
  605. }
  606. }
  607. }
  608. v1 = v2;
  609. v1_side = v2_side;
  610. ++v2;
  611. }
  612. return true;
  613. }
  614. void
  615. carve::triangulate::incorporateHolesIntoPolygon(
  616. const std::vector<std::vector<carve::geom2d::P2> > &poly,
  617. std::vector<std::pair<size_t, size_t> > &result,
  618. size_t poly_loop,
  619. const std::vector<size_t> &hole_loops) {
  620. typedef std::vector<carve::geom2d::P2> loop_t;
  621. size_t N = poly[poly_loop].size();
  622. // work out how much space to reserve for the patched in holes.
  623. for (size_t i = 0; i < hole_loops.size(); i++) {
  624. N += 2 + poly[hole_loops[i]].size();
  625. }
  626. // this is the vector that we will build the result in.
  627. result.clear();
  628. result.reserve(N);
  629. // this is a heap of result indices that defines the vertex test order.
  630. std::vector<size_t> f_loop_heap;
  631. f_loop_heap.reserve(N);
  632. // add the poly loop to result.
  633. for (size_t i = 0; i < poly[poly_loop].size(); ++i) {
  634. result.push_back(std::make_pair((size_t)poly_loop, i));
  635. }
  636. if (hole_loops.size() == 0) {
  637. return;
  638. }
  639. std::vector<std::pair<size_t, size_t> > h_loop_min_vertex;
  640. h_loop_min_vertex.reserve(hole_loops.size());
  641. // find the major axis for the holes - this is the axis that we
  642. // will sort on for finding vertices on the polygon to join
  643. // holes up to.
  644. //
  645. // it might also be nice to also look for whether it is better
  646. // to sort ascending or descending.
  647. //
  648. // another trick that could be used is to modify the projection
  649. // by 90 degree rotations or flipping about an axis. just as
  650. // long as we keep the carve::geom3d::Vector pointers for the
  651. // real data in sync, everything should be ok. then we wouldn't
  652. // need to accomodate axes or sort order in the main loop.
  653. // find the bounding box of all the holes.
  654. carve::geom2d::P2 h_min, h_max;
  655. h_min = h_max = poly[hole_loops[0]][0];
  656. for (size_t i = 0; i < hole_loops.size(); ++i) {
  657. const loop_t &hole = poly[hole_loops[i]];
  658. for (size_t j = 0; j < hole.size(); ++j) {
  659. assign_op(h_min, h_min, hole[j], carve::util::min_functor());
  660. assign_op(h_max, h_max, hole[j], carve::util::max_functor());
  661. }
  662. }
  663. // choose the axis for which the bbox is largest.
  664. int axis = (h_max.x - h_min.x) > (h_max.y - h_min.y) ? 0 : 1;
  665. // for each hole, find the minimum vertex in the chosen axis.
  666. for (size_t i = 0; i < hole_loops.size(); ++i) {
  667. const loop_t &hole = poly[hole_loops[i]];
  668. size_t best, curr;
  669. best = 0;
  670. for (curr = 1; curr != hole.size(); ++curr) {
  671. if (detail::axisOrdering(hole[curr], hole[best], axis)) {
  672. best = curr;
  673. }
  674. }
  675. h_loop_min_vertex.push_back(std::make_pair(hole_loops[i], best));
  676. }
  677. // sort the holes by the minimum vertex.
  678. std::sort(h_loop_min_vertex.begin(), h_loop_min_vertex.end(), order_h_loops_2d(poly, axis));
  679. // now, for each hole, find a vertex in the current polygon loop that it can be joined to.
  680. for (unsigned i = 0; i < h_loop_min_vertex.size(); ++i) {
  681. // the index of the vertex in the hole to connect.
  682. size_t hole_i = h_loop_min_vertex[i].first;
  683. size_t hole_i_connect = h_loop_min_vertex[i].second;
  684. carve::geom2d::P2 hole_min = poly[hole_i][hole_i_connect];
  685. f_loop_heap.clear();
  686. // we order polygon loop vertices that may be able to be connected
  687. // to the hole vertex by their distance to the hole vertex
  688. heap_ordering_2d _heap_ordering(poly, result, hole_min, axis);
  689. const size_t SZ = result.size();
  690. for (size_t j = 0; j < SZ; ++j) {
  691. // it is guaranteed that there exists a polygon vertex with
  692. // coord < the min hole coord chosen, which can be joined to
  693. // the min hole coord without crossing the polygon
  694. // boundary. also, because we merge holes in ascending
  695. // order, it is also true that this join can never cross
  696. // another hole (and that doesn't need to be tested for).
  697. if (pvert(poly, result[j]).v[axis] <= hole_min.v[axis]) {
  698. f_loop_heap.push_back(j);
  699. std::push_heap(f_loop_heap.begin(), f_loop_heap.end(), _heap_ordering);
  700. }
  701. }
  702. // we are going to test each potential (according to the
  703. // previous test) polygon vertex as a candidate join. we order
  704. // by closeness to the hole vertex, so that the join we make
  705. // is as small as possible. to test, we need to check the
  706. // joining line segment does not cross any other line segment
  707. // in the current polygon loop (excluding those that have the
  708. // vertex that we are attempting to join with as an endpoint).
  709. size_t attachment_point = result.size();
  710. while (f_loop_heap.size()) {
  711. std::pop_heap(f_loop_heap.begin(), f_loop_heap.end(), _heap_ordering);
  712. size_t curr = f_loop_heap.back();
  713. f_loop_heap.pop_back();
  714. // test the candidate join from result[curr] to hole_min
  715. if (!testCandidateAttachment(poly, result, curr, hole_min)) {
  716. continue;
  717. }
  718. attachment_point = curr;
  719. break;
  720. }
  721. if (attachment_point == result.size()) {
  722. CARVE_FAIL("didn't manage to link up hole!");
  723. }
  724. patchHoleIntoPolygon_2d(result, attachment_point, hole_i, hole_i_connect, poly[hole_i].size());
  725. }
  726. }
  727. std::vector<std::pair<size_t, size_t> >
  728. carve::triangulate::incorporateHolesIntoPolygon(const std::vector<std::vector<carve::geom2d::P2> > &poly) {
  729. #if 1
  730. std::vector<std::pair<size_t, size_t> > result;
  731. std::vector<size_t> hole_indices;
  732. hole_indices.reserve(poly.size() - 1);
  733. for (size_t i = 1; i < poly.size(); ++i) {
  734. hole_indices.push_back(i);
  735. }
  736. incorporateHolesIntoPolygon(poly, result, 0, hole_indices);
  737. return result;
  738. #else
  739. typedef std::vector<carve::geom2d::P2> loop_t;
  740. size_t N = poly[0].size();
  741. //
  742. // work out how much space to reserve for the patched in holes.
  743. for (size_t i = 0; i < poly.size(); i++) {
  744. N += 2 + poly[i].size();
  745. }
  746. // this is the vector that we will build the result in.
  747. std::vector<std::pair<size_t, size_t> > current_f_loop;
  748. current_f_loop.reserve(N);
  749. // this is a heap of current_f_loop indices that defines the vertex test order.
  750. std::vector<size_t> f_loop_heap;
  751. f_loop_heap.reserve(N);
  752. // add the poly loop to current_f_loop.
  753. for (size_t i = 0; i < poly[0].size(); ++i) {
  754. current_f_loop.push_back(std::make_pair((size_t)0, i));
  755. }
  756. if (poly.size() == 1) {
  757. return current_f_loop;
  758. }
  759. std::vector<std::pair<size_t, size_t> > h_loop_min_vertex;
  760. h_loop_min_vertex.reserve(poly.size() - 1);
  761. // find the major axis for the holes - this is the axis that we
  762. // will sort on for finding vertices on the polygon to join
  763. // holes up to.
  764. //
  765. // it might also be nice to also look for whether it is better
  766. // to sort ascending or descending.
  767. //
  768. // another trick that could be used is to modify the projection
  769. // by 90 degree rotations or flipping about an axis. just as
  770. // long as we keep the carve::geom3d::Vector pointers for the
  771. // real data in sync, everything should be ok. then we wouldn't
  772. // need to accomodate axes or sort order in the main loop.
  773. // find the bounding box of all the holes.
  774. double min_x, min_y, max_x, max_y;
  775. min_x = max_x = poly[1][0].x;
  776. min_y = max_y = poly[1][0].y;
  777. for (size_t i = 1; i < poly.size(); ++i) {
  778. const loop_t &hole = poly[i];
  779. for (size_t j = 0; j < hole.size(); ++j) {
  780. min_x = std::min(min_x, hole[j].x);
  781. min_y = std::min(min_y, hole[j].y);
  782. max_x = std::max(max_x, hole[j].x);
  783. max_y = std::max(max_y, hole[j].y);
  784. }
  785. }
  786. // choose the axis for which the bbox is largest.
  787. int axis = (max_x - min_x) > (max_y - min_y) ? 0 : 1;
  788. // for each hole, find the minimum vertex in the chosen axis.
  789. for (size_t i = 1; i < poly.size(); ++i) {
  790. const loop_t &hole = poly[i];
  791. size_t best, curr;
  792. best = 0;
  793. for (curr = 1; curr != hole.size(); ++curr) {
  794. if (detail::axisOrdering(hole[curr], hole[best], axis)) {
  795. best = curr;
  796. }
  797. }
  798. h_loop_min_vertex.push_back(std::make_pair(i, best));
  799. }
  800. // sort the holes by the minimum vertex.
  801. std::sort(h_loop_min_vertex.begin(), h_loop_min_vertex.end(), order_h_loops_2d(poly, axis));
  802. // now, for each hole, find a vertex in the current polygon loop that it can be joined to.
  803. for (unsigned i = 0; i < h_loop_min_vertex.size(); ++i) {
  804. // the index of the vertex in the hole to connect.
  805. size_t hole_i = h_loop_min_vertex[i].first;
  806. size_t hole_i_connect = h_loop_min_vertex[i].second;
  807. carve::geom2d::P2 hole_min = poly[hole_i][hole_i_connect];
  808. f_loop_heap.clear();
  809. // we order polygon loop vertices that may be able to be connected
  810. // to the hole vertex by their distance to the hole vertex
  811. heap_ordering_2d _heap_ordering(poly, current_f_loop, hole_min, axis);
  812. const size_t SZ = current_f_loop.size();
  813. for (size_t j = 0; j < SZ; ++j) {
  814. // it is guaranteed that there exists a polygon vertex with
  815. // coord < the min hole coord chosen, which can be joined to
  816. // the min hole coord without crossing the polygon
  817. // boundary. also, because we merge holes in ascending
  818. // order, it is also true that this join can never cross
  819. // another hole (and that doesn't need to be tested for).
  820. if (pvert(poly, current_f_loop[j]).v[axis] <= hole_min.v[axis]) {
  821. f_loop_heap.push_back(j);
  822. std::push_heap(f_loop_heap.begin(), f_loop_heap.end(), _heap_ordering);
  823. }
  824. }
  825. // we are going to test each potential (according to the
  826. // previous test) polygon vertex as a candidate join. we order
  827. // by closeness to the hole vertex, so that the join we make
  828. // is as small as possible. to test, we need to check the
  829. // joining line segment does not cross any other line segment
  830. // in the current polygon loop (excluding those that have the
  831. // vertex that we are attempting to join with as an endpoint).
  832. size_t attachment_point = current_f_loop.size();
  833. while (f_loop_heap.size()) {
  834. std::pop_heap(f_loop_heap.begin(), f_loop_heap.end(), _heap_ordering);
  835. size_t curr = f_loop_heap.back();
  836. f_loop_heap.pop_back();
  837. // test the candidate join from current_f_loop[curr] to hole_min
  838. if (!testCandidateAttachment(poly, current_f_loop, curr, hole_min)) {
  839. continue;
  840. }
  841. attachment_point = curr;
  842. break;
  843. }
  844. if (attachment_point == current_f_loop.size()) {
  845. CARVE_FAIL("didn't manage to link up hole!");
  846. }
  847. patchHoleIntoPolygon_2d(current_f_loop, attachment_point, hole_i, hole_i_connect, poly[hole_i].size());
  848. }
  849. return current_f_loop;
  850. #endif
  851. }
  852. std::vector<std::vector<std::pair<size_t, size_t> > >
  853. carve::triangulate::mergePolygonsAndHoles(const std::vector<std::vector<carve::geom2d::P2> > &poly) {
  854. std::vector<size_t> poly_indices, hole_indices;
  855. poly_indices.reserve(poly.size());
  856. hole_indices.reserve(poly.size());
  857. for (size_t i = 0; i < poly.size(); ++i) {
  858. if (carve::geom2d::signedArea(poly[i]) < 0) {
  859. poly_indices.push_back(i);
  860. } else {
  861. hole_indices.push_back(i);
  862. }
  863. }
  864. std::vector<std::vector<std::pair<size_t, size_t> > > result;
  865. result.resize(poly_indices.size());
  866. if (hole_indices.size() == 0) {
  867. for (size_t i = 0; i < poly.size(); ++i) {
  868. result[i].resize(poly[i].size());
  869. for (size_t j = 0; j < poly[i].size(); ++j) {
  870. result[i].push_back(std::make_pair(i, j));
  871. }
  872. }
  873. return result;
  874. }
  875. if (poly_indices.size() == 1) {
  876. incorporateHolesIntoPolygon(poly, result[0], poly_indices[0], hole_indices);
  877. return result;
  878. }
  879. throw carve::exception("not implemented");
  880. }
  881. void carve::triangulate::triangulate(const std::vector<carve::geom2d::P2> &poly,
  882. std::vector<carve::triangulate::tri_idx> &result) {
  883. std::vector<detail::vertex_info *> vinfo;
  884. const size_t N = poly.size();
  885. #if defined(CARVE_DEBUG)
  886. std::cerr << "TRIANGULATION BEGINS" << std::endl;
  887. #endif
  888. #if defined(CARVE_DEBUG_WRITE_PLY_DATA)
  889. dumpPoly(poly, result);
  890. #endif
  891. result.clear();
  892. if (N < 3) {
  893. return;
  894. }
  895. result.reserve(poly.size() - 2);
  896. if (N == 3) {
  897. result.push_back(tri_idx(0, 1, 2));
  898. return;
  899. }
  900. vinfo.resize(N);
  901. vinfo[0] = new detail::vertex_info(poly[0], 0);
  902. for (size_t i = 1; i < N-1; ++i) {
  903. vinfo[i] = new detail::vertex_info(poly[i], i);
  904. vinfo[i]->prev = vinfo[i-1];
  905. vinfo[i-1]->next = vinfo[i];
  906. }
  907. vinfo[N-1] = new detail::vertex_info(poly[N-1], N-1);
  908. vinfo[N-1]->prev = vinfo[N-2];
  909. vinfo[N-1]->next = vinfo[0];
  910. vinfo[0]->prev = vinfo[N-1];
  911. vinfo[N-2]->next = vinfo[N-1];
  912. for (size_t i = 0; i < N; ++i) {
  913. vinfo[i]->recompute();
  914. }
  915. detail::vertex_info *begin = vinfo[0];
  916. removeDegeneracies(begin, result);
  917. doTriangulate(begin, result);
  918. #if defined(CARVE_DEBUG)
  919. std::cerr << "TRIANGULATION ENDS" << std::endl;
  920. #endif
  921. #if defined(CARVE_DEBUG_WRITE_PLY_DATA)
  922. dumpPoly(poly, result);
  923. #endif
  924. }
  925. void carve::triangulate::detail::tri_pair_t::flip(vert_edge_t &old_edge,
  926. vert_edge_t &new_edge,
  927. vert_edge_t perim[4]) {
  928. unsigned ai, bi;
  929. unsigned cross_ai, cross_bi;
  930. findSharedEdge(ai, bi);
  931. old_edge = ordered_vert_edge_t(a->v[ai], b->v[bi]);
  932. cross_ai = P(ai);
  933. cross_bi = P(bi);
  934. new_edge = ordered_vert_edge_t(a->v[cross_ai], b->v[cross_bi]);
  935. score = -score;
  936. a->v[N(ai)] = b->v[cross_bi];
  937. b->v[N(bi)] = a->v[cross_ai];
  938. perim[0] = ordered_vert_edge_t(a->v[P(ai)], a->v[ai]);
  939. perim[1] = ordered_vert_edge_t(a->v[N(ai)], a->v[ai]); // this edge was a b-edge
  940. perim[2] = ordered_vert_edge_t(b->v[P(bi)], b->v[bi]);
  941. perim[3] = ordered_vert_edge_t(b->v[N(bi)], b->v[bi]); // this edge was an a-edge
  942. }
  943. void carve::triangulate::detail::tri_pairs_t::insert(unsigned a, unsigned b, carve::triangulate::tri_idx *t) {
  944. tri_pair_t *tp;
  945. if (a < b) {
  946. tp = storage[vert_edge_t(a,b)];
  947. if (!tp) {
  948. tp = storage[vert_edge_t(a,b)] = new tri_pair_t;
  949. }
  950. tp->a = t;
  951. } else {
  952. tp = storage[vert_edge_t(b,a)];
  953. if (!tp) {
  954. tp = storage[vert_edge_t(b,a)] = new tri_pair_t;
  955. }
  956. tp->b = t;
  957. }
  958. }