TriangulateEC.h 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2020.01.10
  7. #pragma once
  8. #include <Mathematics/Logger.h>
  9. #include <Mathematics/PrimalQuery2.h>
  10. #include <memory>
  11. #include <map>
  12. #include <queue>
  13. #include <vector>
  14. // Triangulate polygons using ear clipping. The algorithm is described in
  15. // https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf
  16. // The algorithm for processing nested polygons involves a division, so the
  17. // ComputeType must be rational-based, say, BSRational. If you process only
  18. // triangles that are simple, you may use BSNumber for the ComputeType.
  19. namespace WwiseGTE
  20. {
  21. template <typename InputType, typename ComputeType>
  22. class TriangulateEC
  23. {
  24. public:
  25. // The class is a functor to support triangulating multiple polygons
  26. // that share vertices in a collection of points. The interpretation
  27. // of 'numPoints' and 'points' is described before each operator()
  28. // function. Preconditions are numPoints >= 3 and points is a nonnull
  29. // pointer to an array of at least numPoints elements. If the
  30. // preconditions are satisfied, then operator() functions will return
  31. // 'true'; otherwise, they return 'false'.
  32. TriangulateEC(int numPoints, Vector2<InputType> const* points)
  33. :
  34. mNumPoints(numPoints),
  35. mPoints(points)
  36. {
  37. LogAssert(numPoints >= 3 && points != nullptr, "Invalid input.");
  38. mComputePoints.resize(mNumPoints);
  39. mIsConverted.resize(mNumPoints);
  40. std::fill(mIsConverted.begin(), mIsConverted.end(), false);
  41. mQuery.Set(mNumPoints, &mComputePoints[0]);
  42. }
  43. TriangulateEC(std::vector<Vector2<InputType>> const& points)
  44. :
  45. mNumPoints(static_cast<int>(points.size())),
  46. mPoints(points.data())
  47. {
  48. LogAssert(mNumPoints >= 3 && mPoints != nullptr, "Invalid input.");
  49. mComputePoints.resize(mNumPoints);
  50. mIsConverted.resize(mNumPoints);
  51. std::fill(mIsConverted.begin(), mIsConverted.end(), false);
  52. mQuery.Set(mNumPoints, &mComputePoints[0]);
  53. }
  54. // Access the triangulation after each operator() call.
  55. inline std::vector<std::array<int, 3>> const& GetTriangles() const
  56. {
  57. return mTriangles;
  58. }
  59. // The outer polygons have counterclockwise ordered vertices. The
  60. // inner polygons have clockwise ordered vertices.
  61. typedef std::vector<int> Polygon;
  62. // The input 'points' represents an array of vertices for a simple
  63. // polygon. The vertices are points[0] through points[numPoints-1] and
  64. // are listed in counterclockwise order.
  65. bool operator()()
  66. {
  67. mTriangles.clear();
  68. if (mPoints)
  69. {
  70. // Compute the points for the queries.
  71. for (int i = 0; i < mNumPoints; ++i)
  72. {
  73. if (!mIsConverted[i])
  74. {
  75. mIsConverted[i] = true;
  76. for (int j = 0; j < 2; ++j)
  77. {
  78. mComputePoints[i][j] = mPoints[i][j];
  79. }
  80. }
  81. }
  82. // Triangulate the unindexed polygon.
  83. InitializeVertices(mNumPoints, nullptr);
  84. DoEarClipping(mNumPoints, nullptr);
  85. return true;
  86. }
  87. else
  88. {
  89. return false;
  90. }
  91. }
  92. // The input 'points' represents an array of vertices that contains
  93. // the vertices of a simple polygon.
  94. bool operator()(Polygon const& polygon)
  95. {
  96. mTriangles.clear();
  97. if (mPoints)
  98. {
  99. // Compute the points for the queries.
  100. int const numIndices = static_cast<int>(polygon.size());
  101. int const* indices = polygon.data();
  102. for (int i = 0; i < numIndices; ++i)
  103. {
  104. int index = indices[i];
  105. if (!mIsConverted[index])
  106. {
  107. mIsConverted[index] = true;
  108. for (int j = 0; j < 2; ++j)
  109. {
  110. mComputePoints[index][j] = mPoints[index][j];
  111. }
  112. }
  113. }
  114. // Triangulate the indexed polygon.
  115. InitializeVertices(numIndices, indices);
  116. DoEarClipping(numIndices, indices);
  117. return true;
  118. }
  119. else
  120. {
  121. return false;
  122. }
  123. }
  124. // The input 'points' is a shared array of vertices that contains the
  125. // vertices for two simple polygons, an outer polygon and an inner
  126. // polygon. The inner polygon must be strictly inside the outer
  127. // polygon.
  128. bool operator()(Polygon const& outer, Polygon const& inner)
  129. {
  130. mTriangles.clear();
  131. if (mPoints)
  132. {
  133. // Two extra elements are needed to duplicate the endpoints of
  134. // the edge introduced to combine outer and inner polygons.
  135. int numPointsPlusExtras = mNumPoints + 2;
  136. if (numPointsPlusExtras > static_cast<int>(mComputePoints.size()))
  137. {
  138. mComputePoints.resize(numPointsPlusExtras);
  139. mIsConverted.resize(numPointsPlusExtras);
  140. mIsConverted[mNumPoints] = false;
  141. mIsConverted[mNumPoints + 1] = false;
  142. mQuery.Set(numPointsPlusExtras, &mComputePoints[0]);
  143. }
  144. // Convert any points that have not been encountered in other
  145. // triangulation calls.
  146. int const numOuterIndices = static_cast<int>(outer.size());
  147. int const* outerIndices = outer.data();
  148. for (int i = 0; i < numOuterIndices; ++i)
  149. {
  150. int index = outerIndices[i];
  151. if (!mIsConverted[index])
  152. {
  153. mIsConverted[index] = true;
  154. for (int j = 0; j < 2; ++j)
  155. {
  156. mComputePoints[index][j] = mPoints[index][j];
  157. }
  158. }
  159. }
  160. int const numInnerIndices = static_cast<int>(inner.size());
  161. int const* innerIndices = inner.data();
  162. for (int i = 0; i < numInnerIndices; ++i)
  163. {
  164. int index = innerIndices[i];
  165. if (!mIsConverted[index])
  166. {
  167. mIsConverted[index] = true;
  168. for (int j = 0; j < 2; ++j)
  169. {
  170. mComputePoints[index][j] = mPoints[index][j];
  171. }
  172. }
  173. }
  174. // Combine the outer polygon and the inner polygon into a
  175. // simple polygon by inserting two edges connecting mutually
  176. // visible vertices, one from the outer polygon and one from
  177. // the inner polygon.
  178. int nextElement = mNumPoints; // The next available element.
  179. std::map<int, int> indexMap;
  180. std::vector<int> combined;
  181. if (!CombinePolygons(nextElement, outer, inner, indexMap, combined))
  182. {
  183. // An unexpected condition was encountered.
  184. return false;
  185. }
  186. // The combined polygon is now in the format of a simple
  187. // polygon, albeit one with coincident edges.
  188. int numVertices = static_cast<int>(combined.size());
  189. int* const indices = &combined[0];
  190. InitializeVertices(numVertices, indices);
  191. DoEarClipping(numVertices, indices);
  192. // Map the duplicate indices back to the original indices.
  193. RemapIndices(indexMap);
  194. return true;
  195. }
  196. else
  197. {
  198. return false;
  199. }
  200. }
  201. // The input 'points' is a shared array of vertices that contains the
  202. // vertices for multiple simple polygons, an outer polygon and one or
  203. // more inner polygons. The inner polygons must be nonoverlapping and
  204. // strictly inside the outer polygon.
  205. bool operator()(Polygon const& outer, std::vector<Polygon> const& inners)
  206. {
  207. mTriangles.clear();
  208. if (mPoints)
  209. {
  210. // Two extra elements per inner polygon are needed to
  211. // duplicate the endpoints of the edges introduced to combine
  212. // outer and inner polygons.
  213. int numPointsPlusExtras = mNumPoints + 2 * (int)inners.size();
  214. if (numPointsPlusExtras > static_cast<int>(mComputePoints.size()))
  215. {
  216. mComputePoints.resize(numPointsPlusExtras);
  217. mIsConverted.resize(numPointsPlusExtras);
  218. for (int i = mNumPoints; i < numPointsPlusExtras; ++i)
  219. {
  220. mIsConverted[i] = false;
  221. }
  222. mQuery.Set(numPointsPlusExtras, &mComputePoints[0]);
  223. }
  224. // Convert any points that have not been encountered in other
  225. // triangulation calls.
  226. int const numOuterIndices = static_cast<int>(outer.size());
  227. int const* outerIndices = outer.data();
  228. for (int i = 0; i < numOuterIndices; ++i)
  229. {
  230. int index = outerIndices[i];
  231. if (!mIsConverted[index])
  232. {
  233. mIsConverted[index] = true;
  234. for (int j = 0; j < 2; ++j)
  235. {
  236. mComputePoints[index][j] = mPoints[index][j];
  237. }
  238. }
  239. }
  240. for (auto const& inner : inners)
  241. {
  242. int const numInnerIndices = static_cast<int>(inner.size());
  243. int const* innerIndices = inner.data();
  244. for (int i = 0; i < numInnerIndices; ++i)
  245. {
  246. int index = innerIndices[i];
  247. if (!mIsConverted[index])
  248. {
  249. mIsConverted[index] = true;
  250. for (int j = 0; j < 2; ++j)
  251. {
  252. mComputePoints[index][j] = mPoints[index][j];
  253. }
  254. }
  255. }
  256. }
  257. // Combine the outer polygon and the inner polygons into a
  258. // simple polygon by inserting two edges per inner polygon
  259. // connecting mutually visible vertices.
  260. int nextElement = mNumPoints; // The next available element.
  261. std::map<int, int> indexMap;
  262. std::vector<int> combined;
  263. if (!ProcessOuterAndInners(nextElement, outer, inners, indexMap, combined))
  264. {
  265. // An unexpected condition was encountered.
  266. return false;
  267. }
  268. // The combined polygon is now in the format of a simple
  269. // polygon, albeit with coincident edges.
  270. int numVertices = static_cast<int>(combined.size());
  271. int* const indices = &combined[0];
  272. InitializeVertices(numVertices, indices);
  273. DoEarClipping(numVertices, indices);
  274. // Map the duplicate indices back to the original indices.
  275. RemapIndices(indexMap);
  276. return true;
  277. }
  278. else
  279. {
  280. return false;
  281. }
  282. }
  283. // A tree of nested polygons. The root node corresponds to an outer
  284. // polygon. The children of the root correspond to inner polygons,
  285. // which are nonoverlapping polygons strictly contained in the outer
  286. // polygon. Each inner polygon may itself contain an outer polygon,
  287. // thus leading to a hierarchy of polygons. The outer polygons have
  288. // vertices listed in counterclockwise order. The inner polygons have
  289. // vertices listed in clockwise order.
  290. class Tree
  291. {
  292. public:
  293. Polygon polygon;
  294. std::vector<std::shared_ptr<Tree>> child;
  295. };
  296. // The input 'positions' is a shared array of vertices that contains
  297. // the vertices for multiple simple polygons in a tree of polygons.
  298. bool operator()(std::shared_ptr<Tree> const& tree)
  299. {
  300. mTriangles.clear();
  301. if (mPoints)
  302. {
  303. // Two extra elements per inner polygon are needed to
  304. // duplicate the endpoints of the edges introduced to combine
  305. // outer and inner polygons.
  306. int numPointsPlusExtras = mNumPoints + InitializeFromTree(tree);
  307. if (numPointsPlusExtras > static_cast<int>(mComputePoints.size()))
  308. {
  309. mComputePoints.resize(numPointsPlusExtras);
  310. mIsConverted.resize(numPointsPlusExtras);
  311. for (int i = mNumPoints; i < numPointsPlusExtras; ++i)
  312. {
  313. mIsConverted[i] = false;
  314. }
  315. mQuery.Set(numPointsPlusExtras, &mComputePoints[0]);
  316. }
  317. int nextElement = mNumPoints;
  318. std::map<int, int> indexMap;
  319. std::queue<std::shared_ptr<Tree>> treeQueue;
  320. treeQueue.push(tree);
  321. while (treeQueue.size() > 0)
  322. {
  323. std::shared_ptr<Tree> outer = treeQueue.front();
  324. treeQueue.pop();
  325. int numChildren = static_cast<int>(outer->child.size());
  326. int numVertices;
  327. int const* indices;
  328. if (numChildren == 0)
  329. {
  330. // The outer polygon is a simple polygon (no nested
  331. // inner polygons). Triangulate the simple polygon.
  332. numVertices = static_cast<int>(outer->polygon.size());
  333. indices = outer->polygon.data();
  334. InitializeVertices(numVertices, indices);
  335. DoEarClipping(numVertices, indices);
  336. }
  337. else
  338. {
  339. // Place the next level of outer polygon nodes on the
  340. // queue for triangulation.
  341. std::vector<Polygon> inners(numChildren);
  342. for (int c = 0; c < numChildren; ++c)
  343. {
  344. std::shared_ptr<Tree> inner = outer->child[c];
  345. inners[c] = inner->polygon;
  346. int numGrandChildren = static_cast<int>(inner->child.size());
  347. for (int g = 0; g < numGrandChildren; ++g)
  348. {
  349. treeQueue.push(inner->child[g]);
  350. }
  351. }
  352. // Combine the outer polygon and the inner polygons
  353. // into a simple polygon by inserting two edges per
  354. // inner polygon connecting mutually visible vertices.
  355. std::vector<int> combined;
  356. ProcessOuterAndInners(nextElement, outer->polygon, inners, indexMap, combined);
  357. // The combined polygon is now in the format of a
  358. // simple polygon, albeit with coincident edges.
  359. numVertices = static_cast<int>(combined.size());
  360. indices = &combined[0];
  361. InitializeVertices(numVertices, indices);
  362. DoEarClipping(numVertices, indices);
  363. }
  364. }
  365. // Map the duplicate indices back to the original indices.
  366. RemapIndices(indexMap);
  367. return true;
  368. }
  369. else
  370. {
  371. return false;
  372. }
  373. }
  374. private:
  375. // Create the vertex objects that store the various lists required by
  376. // the ear-clipping algorithm.
  377. void InitializeVertices(int numVertices, int const* indices)
  378. {
  379. mVertices.clear();
  380. mVertices.resize(numVertices);
  381. mCFirst = -1;
  382. mCLast = -1;
  383. mRFirst = -1;
  384. mRLast = -1;
  385. mEFirst = -1;
  386. mELast = -1;
  387. // Create a circular list of the polygon vertices for dynamic
  388. // removal of vertices.
  389. int numVerticesM1 = numVertices - 1;
  390. for (int i = 0; i <= numVerticesM1; ++i)
  391. {
  392. Vertex& vertex = V(i);
  393. vertex.index = (indices ? indices[i] : i);
  394. vertex.vPrev = (i > 0 ? i - 1 : numVerticesM1);
  395. vertex.vNext = (i < numVerticesM1 ? i + 1 : 0);
  396. }
  397. // Create a circular list of the polygon vertices for dynamic
  398. // removal of vertices. Keep track of two linear sublists, one
  399. // for the convex vertices and one for the reflex vertices.
  400. // This is an O(N) process where N is the number of polygon
  401. // vertices.
  402. for (int i = 0; i <= numVerticesM1; ++i)
  403. {
  404. if (IsConvex(i))
  405. {
  406. InsertAfterC(i);
  407. }
  408. else
  409. {
  410. InsertAfterR(i);
  411. }
  412. }
  413. }
  414. // Apply ear clipping to the input polygon. Polygons with holes are
  415. // preprocessed to obtain an index array that is nearly a simple
  416. // polygon. This outer polygon has a pair of coincident edges per
  417. // inner polygon.
  418. void DoEarClipping(int numVertices, int const* indices)
  419. {
  420. // If the polygon is convex, just create a triangle fan.
  421. if (mRFirst == -1)
  422. {
  423. int numVerticesM1 = numVertices - 1;
  424. if (indices)
  425. {
  426. for (int i = 1; i < numVerticesM1; ++i)
  427. {
  428. mTriangles.push_back( { indices[0], indices[i], indices[i + 1] } );
  429. }
  430. }
  431. else
  432. {
  433. for (int i = 1; i < numVerticesM1; ++i)
  434. {
  435. mTriangles.push_back( { 0, i, i + 1 } );
  436. }
  437. }
  438. return;
  439. }
  440. // Identify the ears and build a circular list of them. Let V0,
  441. // V1, and V2 be consecutive vertices forming a triangle T. The
  442. // vertex V1 is an ear if no other vertices of the polygon lie
  443. // inside T. Although it is enough to show that V1 is not an ear
  444. // by finding at least one other vertex inside T, it is sufficient
  445. // to search only the reflex vertices. This is an O(C*R) process,
  446. // where C is the number of convex vertices and R is the number of
  447. // reflex vertices with N = C+R. The order is O(N^2), for example
  448. // when C = R = N/2.
  449. for (int i = mCFirst; i != -1; i = V(i).sNext)
  450. {
  451. if (IsEar(i))
  452. {
  453. InsertEndE(i);
  454. }
  455. }
  456. V(mEFirst).ePrev = mELast;
  457. V(mELast).eNext = mEFirst;
  458. // Remove the ears, one at a time.
  459. bool bRemoveAnEar = true;
  460. while (bRemoveAnEar)
  461. {
  462. // Add the triangle with the ear to the output list of
  463. // triangles.
  464. int iVPrev = V(mEFirst).vPrev;
  465. int iVNext = V(mEFirst).vNext;
  466. mTriangles.push_back( { V(iVPrev).index, V(mEFirst).index, V(iVNext).index } );
  467. // Remove the vertex corresponding to the ear.
  468. RemoveV(mEFirst);
  469. if (--numVertices == 3)
  470. {
  471. // Only one triangle remains, just remove the ear and
  472. // copy it.
  473. mEFirst = RemoveE(mEFirst);
  474. iVPrev = V(mEFirst).vPrev;
  475. iVNext = V(mEFirst).vNext;
  476. mTriangles.push_back( { V(iVPrev).index, V(mEFirst).index, V(iVNext).index } );
  477. bRemoveAnEar = false;
  478. continue;
  479. }
  480. // Removal of the ear can cause an adjacent vertex to become
  481. // an ear or to stop being an ear.
  482. Vertex& vPrev = V(iVPrev);
  483. if (vPrev.isEar)
  484. {
  485. if (!IsEar(iVPrev))
  486. {
  487. RemoveE(iVPrev);
  488. }
  489. }
  490. else
  491. {
  492. bool wasReflex = !vPrev.isConvex;
  493. if (IsConvex(iVPrev))
  494. {
  495. if (wasReflex)
  496. {
  497. RemoveR(iVPrev);
  498. }
  499. if (IsEar(iVPrev))
  500. {
  501. InsertBeforeE(iVPrev);
  502. }
  503. }
  504. }
  505. Vertex& vNext = V(iVNext);
  506. if (vNext.isEar)
  507. {
  508. if (!IsEar(iVNext))
  509. {
  510. RemoveE(iVNext);
  511. }
  512. }
  513. else
  514. {
  515. bool wasReflex = !vNext.isConvex;
  516. if (IsConvex(iVNext))
  517. {
  518. if (wasReflex)
  519. {
  520. RemoveR(iVNext);
  521. }
  522. if (IsEar(iVNext))
  523. {
  524. InsertAfterE(iVNext);
  525. }
  526. }
  527. }
  528. // Remove the ear.
  529. mEFirst = RemoveE(mEFirst);
  530. }
  531. }
  532. // Given an outer polygon that contains an inner polygon, this
  533. // function determines a pair of visible vertices and inserts two
  534. // coincident edges to generate a nearly simple polygon.
  535. bool CombinePolygons(int nextElement, Polygon const& outer,
  536. Polygon const& inner, std::map<int, int>& indexMap,
  537. std::vector<int>& combined)
  538. {
  539. int const numOuterIndices = static_cast<int>(outer.size());
  540. int const* outerIndices = outer.data();
  541. int const numInnerIndices = static_cast<int>(inner.size());
  542. int const* innerIndices = inner.data();
  543. // Locate the inner-polygon vertex of maximum x-value, call this
  544. // vertex M.
  545. ComputeType xmax = mComputePoints[innerIndices[0]][0];
  546. int xmaxIndex = 0;
  547. for (int i = 1; i < numInnerIndices; ++i)
  548. {
  549. ComputeType x = mComputePoints[innerIndices[i]][0];
  550. if (x > xmax)
  551. {
  552. xmax = x;
  553. xmaxIndex = i;
  554. }
  555. }
  556. Vector2<ComputeType> M = mComputePoints[innerIndices[xmaxIndex]];
  557. // Find the edge whose intersection Intr with the ray M+t*(1,0)
  558. // minimizes
  559. // the ray parameter t >= 0.
  560. ComputeType const cmax = static_cast<ComputeType>(std::numeric_limits<InputType>::max());
  561. ComputeType const zero = static_cast<ComputeType>(0);
  562. Vector2<ComputeType> intr{ cmax, M[1] };
  563. int v0min = -1, v1min = -1, endMin = -1;
  564. int i0, i1;
  565. ComputeType s = cmax;
  566. ComputeType t = cmax;
  567. for (i0 = numOuterIndices - 1, i1 = 0; i1 < numOuterIndices; i0 = i1++)
  568. {
  569. // Consider only edges for which the first vertex is below
  570. // (or on) the ray and the second vertex is above (or on)
  571. // the ray.
  572. Vector2<ComputeType> diff0 = mComputePoints[outerIndices[i0]] - M;
  573. if (diff0[1] > zero)
  574. {
  575. continue;
  576. }
  577. Vector2<ComputeType> diff1 = mComputePoints[outerIndices[i1]] - M;
  578. if (diff1[1] < zero)
  579. {
  580. continue;
  581. }
  582. // At this time, diff0.y <= 0 and diff1.y >= 0.
  583. int currentEndMin = -1;
  584. if (diff0[1] < zero)
  585. {
  586. if (diff1[1] > zero)
  587. {
  588. // The intersection of the edge and ray occurs at an
  589. // interior edge point.
  590. s = diff0[1] / (diff0[1] - diff1[1]);
  591. t = diff0[0] + s * (diff1[0] - diff0[0]);
  592. }
  593. else // diff1.y == 0
  594. {
  595. // The vertex Outer[i1] is the intersection of the
  596. // edge and the ray.
  597. t = diff1[0];
  598. currentEndMin = i1;
  599. }
  600. }
  601. else // diff0.y == 0
  602. {
  603. if (diff1[1] > zero)
  604. {
  605. // The vertex Outer[i0] is the intersection of the
  606. // edge and the ray;
  607. t = diff0[0];
  608. currentEndMin = i0;
  609. }
  610. else // diff1.y == 0
  611. {
  612. if (diff0[0] < diff1[0])
  613. {
  614. t = diff0[0];
  615. currentEndMin = i0;
  616. }
  617. else
  618. {
  619. t = diff1[0];
  620. currentEndMin = i1;
  621. }
  622. }
  623. }
  624. if (zero <= t && t < intr[0])
  625. {
  626. intr[0] = t;
  627. v0min = i0;
  628. v1min = i1;
  629. if (currentEndMin == -1)
  630. {
  631. // The current closest point is an edge-interior
  632. // point.
  633. endMin = -1;
  634. }
  635. else
  636. {
  637. // The current closest point is a vertex.
  638. endMin = currentEndMin;
  639. }
  640. }
  641. else if (t == intr[0])
  642. {
  643. // The current closest point is a vertex shared by
  644. // multiple edges; thus, endMin and currentMin refer to
  645. // the same point.
  646. LogAssert(endMin != -1 && currentEndMin != -1, "Unexpected condition.");
  647. // We need to select the edge closest to M. The previous
  648. // closest edge is <outer[v0min],outer[v1min]>. The
  649. // current candidate is <outer[i0],outer[i1]>.
  650. Vector2<ComputeType> shared = mComputePoints[outerIndices[i1]];
  651. // For the previous closest edge, endMin refers to a
  652. // vertex of the edge. Get the index of the other vertex.
  653. int other = (endMin == v0min ? v1min : v0min);
  654. // The new edge is closer if the other vertex of the old
  655. // edge is left-of the new edge.
  656. diff0 = mComputePoints[outerIndices[i0]] - shared;
  657. diff1 = mComputePoints[outerIndices[other]] - shared;
  658. ComputeType dotperp = DotPerp(diff0, diff1);
  659. if (dotperp > zero)
  660. {
  661. // The new edge is closer to M.
  662. v0min = i0;
  663. v1min = i1;
  664. endMin = currentEndMin;
  665. }
  666. }
  667. }
  668. // The intersection intr[0] stored only the t-value of the ray.
  669. // The actual point is (mx,my)+t*(1,0), so intr[0] must be
  670. // adjusted.
  671. intr[0] += M[0];
  672. int maxCosIndex;
  673. if (endMin == -1)
  674. {
  675. // If you reach this assert, there is a good chance that you
  676. // have two inner polygons that share a vertex or an edge.
  677. LogAssert(v0min >= 0 && v1min >= 0, "Is this an invalid nested polygon?");
  678. // Select one of Outer[v0min] and Outer[v1min] that has an
  679. // x-value larger than M.x, call this vertex P. The triangle
  680. // <M,I,P> must contain an outer-polygon vertex that is
  681. // visible to M, which is possibly P itself.
  682. Vector2<ComputeType> sTriangle[3]; // <P,M,I> or <P,I,M>
  683. int pIndex;
  684. if (mComputePoints[outerIndices[v0min]][0] > mComputePoints[outerIndices[v1min]][0])
  685. {
  686. sTriangle[0] = mComputePoints[outerIndices[v0min]];
  687. sTriangle[1] = intr;
  688. sTriangle[2] = M;
  689. pIndex = v0min;
  690. }
  691. else
  692. {
  693. sTriangle[0] = mComputePoints[outerIndices[v1min]];
  694. sTriangle[1] = M;
  695. sTriangle[2] = intr;
  696. pIndex = v1min;
  697. }
  698. // If any outer-polygon vertices other than P are inside the
  699. // triangle <M,I,P>, then at least one of these vertices must
  700. // be a reflex vertex. It is sufficient to locate the reflex
  701. // vertex R (if any) in <M,I,P> that minimizes the angle
  702. // between R-M and (1,0). The data member mQuery is used for
  703. // the reflex query.
  704. Vector2<ComputeType> diff = sTriangle[0] - M;
  705. ComputeType maxSqrLen = Dot(diff, diff);
  706. ComputeType maxCos = diff[0] * diff[0] / maxSqrLen;
  707. PrimalQuery2<ComputeType> localQuery(3, sTriangle);
  708. maxCosIndex = pIndex;
  709. for (int i = 0; i < numOuterIndices; ++i)
  710. {
  711. if (i == pIndex)
  712. {
  713. continue;
  714. }
  715. int curr = outerIndices[i];
  716. int prev = outerIndices[(i + numOuterIndices - 1) % numOuterIndices];
  717. int next = outerIndices[(i + 1) % numOuterIndices];
  718. if (mQuery.ToLine(curr, prev, next) <= 0
  719. && localQuery.ToTriangle(mComputePoints[curr], 0, 1, 2) <= 0)
  720. {
  721. // The vertex is reflex and inside the <M,I,P>
  722. // triangle.
  723. diff = mComputePoints[curr] - M;
  724. ComputeType sqrLen = Dot(diff, diff);
  725. ComputeType cs = diff[0] * diff[0] / sqrLen;
  726. if (cs > maxCos)
  727. {
  728. // The reflex vertex forms a smaller angle with
  729. // the positive x-axis, so it becomes the new
  730. // visible candidate.
  731. maxSqrLen = sqrLen;
  732. maxCos = cs;
  733. maxCosIndex = i;
  734. }
  735. else if (cs == maxCos && sqrLen < maxSqrLen)
  736. {
  737. // The reflex vertex has angle equal to the
  738. // current minimum but the length is smaller, so
  739. // it becomes the new visible candidate.
  740. maxSqrLen = sqrLen;
  741. maxCosIndex = i;
  742. }
  743. }
  744. }
  745. }
  746. else
  747. {
  748. maxCosIndex = endMin;
  749. }
  750. // The visible vertices are Position[Inner[xmaxIndex]] and
  751. // Position[Outer[maxCosIndex]]. Two coincident edges with
  752. // these endpoints are inserted to connect the outer and inner
  753. // polygons into a simple polygon. Each of the two Position[]
  754. // values must be duplicated, because the original might be
  755. // convex (or reflex) and the duplicate is reflex (or convex).
  756. // The ear-clipping algorithm needs to distinguish between them.
  757. combined.resize(numOuterIndices + numInnerIndices + 2);
  758. int cIndex = 0;
  759. for (int i = 0; i <= maxCosIndex; ++i, ++cIndex)
  760. {
  761. combined[cIndex] = outerIndices[i];
  762. }
  763. for (int i = 0; i < numInnerIndices; ++i, ++cIndex)
  764. {
  765. int j = (xmaxIndex + i) % numInnerIndices;
  766. combined[cIndex] = innerIndices[j];
  767. }
  768. int innerIndex = innerIndices[xmaxIndex];
  769. mComputePoints[nextElement] = mComputePoints[innerIndex];
  770. combined[cIndex] = nextElement;
  771. auto iter = indexMap.find(innerIndex);
  772. if (iter != indexMap.end())
  773. {
  774. innerIndex = iter->second;
  775. }
  776. indexMap[nextElement] = innerIndex;
  777. ++cIndex;
  778. ++nextElement;
  779. int outerIndex = outerIndices[maxCosIndex];
  780. mComputePoints[nextElement] = mComputePoints[outerIndex];
  781. combined[cIndex] = nextElement;
  782. iter = indexMap.find(outerIndex);
  783. if (iter != indexMap.end())
  784. {
  785. outerIndex = iter->second;
  786. }
  787. indexMap[nextElement] = outerIndex;
  788. ++cIndex;
  789. ++nextElement;
  790. for (int i = maxCosIndex + 1; i < numOuterIndices; ++i, ++cIndex)
  791. {
  792. combined[cIndex] = outerIndices[i];
  793. }
  794. return true;
  795. }
  796. // Given an outer polygon that contains a set of nonoverlapping inner
  797. // polygons, this function determines pairs of visible vertices and
  798. // inserts coincident edges to generate a nearly simple polygon. It
  799. // repeatedly calls CombinePolygons for each inner polygon of the
  800. // outer polygon.
  801. bool ProcessOuterAndInners(int& nextElement, Polygon const& outer,
  802. std::vector<Polygon> const& inners, std::map<int, int>& indexMap,
  803. std::vector<int>& combined)
  804. {
  805. // Sort the inner polygons based on maximum x-values.
  806. int numInners = static_cast<int>(inners.size());
  807. std::vector<std::pair<ComputeType, int>> pairs(numInners);
  808. for (int p = 0; p < numInners; ++p)
  809. {
  810. int numIndices = static_cast<int>(inners[p].size());
  811. int const* indices = inners[p].data();
  812. ComputeType xmax = mComputePoints[indices[0]][0];
  813. for (int j = 1; j < numIndices; ++j)
  814. {
  815. ComputeType x = mComputePoints[indices[j]][0];
  816. if (x > xmax)
  817. {
  818. xmax = x;
  819. }
  820. }
  821. pairs[p].first = xmax;
  822. pairs[p].second = p;
  823. }
  824. std::sort(pairs.begin(), pairs.end());
  825. // Merge the inner polygons with the outer polygon.
  826. Polygon currentPolygon = outer;
  827. for (int p = numInners - 1; p >= 0; --p)
  828. {
  829. Polygon const& polygon = inners[pairs[p].second];
  830. Polygon currentCombined;
  831. if (!CombinePolygons(nextElement, currentPolygon, polygon, indexMap, currentCombined))
  832. {
  833. return false;
  834. }
  835. currentPolygon = std::move(currentCombined);
  836. nextElement += 2;
  837. }
  838. for (auto index : currentPolygon)
  839. {
  840. combined.push_back(index);
  841. }
  842. return true;
  843. }
  844. // The insertion of coincident edges to obtain a nearly simple polygon
  845. // requires duplication of vertices in order that the ear-clipping
  846. // algorithm work correctly. After the triangulation, the indices of
  847. // the duplicated vertices are converted to the original indices.
  848. void RemapIndices(std::map<int, int> const& indexMap)
  849. {
  850. // The triangulation includes indices to the duplicated outer and
  851. // inner vertices. These indices must be mapped back to the
  852. // original ones.
  853. for (auto& tri : mTriangles)
  854. {
  855. for (int i = 0; i < 3; ++i)
  856. {
  857. auto iter = indexMap.find(tri[i]);
  858. if (iter != indexMap.end())
  859. {
  860. tri[i] = iter->second;
  861. }
  862. }
  863. }
  864. }
  865. // Two extra elements are needed in the position array per
  866. // outer-inners polygon. This function computes the total number of
  867. // extra elements needed for the input tree and it converts InputType
  868. // vertices to ComputeType values.
  869. int InitializeFromTree(std::shared_ptr<Tree> const& tree)
  870. {
  871. // Use a breadth-first search to process the outer-inners pairs
  872. // of the tree of nested polygons.
  873. int numExtraPoints = 0;
  874. std::queue<std::shared_ptr<Tree>> treeQueue;
  875. treeQueue.push(tree);
  876. while (treeQueue.size() > 0)
  877. {
  878. // The 'root' is an outer polygon.
  879. std::shared_ptr<Tree> outer = treeQueue.front();
  880. treeQueue.pop();
  881. // Count number of extra points for this outer-inners pair.
  882. int numChildren = static_cast<int>(outer->child.size());
  883. numExtraPoints += 2 * numChildren;
  884. // Convert outer points from InputType to ComputeType.
  885. int const numOuterIndices = static_cast<int>(outer->polygon.size());
  886. int const* outerIndices = outer->polygon.data();
  887. for (int i = 0; i < numOuterIndices; ++i)
  888. {
  889. int index = outerIndices[i];
  890. if (!mIsConverted[index])
  891. {
  892. mIsConverted[index] = true;
  893. for (int j = 0; j < 2; ++j)
  894. {
  895. mComputePoints[index][j] = mPoints[index][j];
  896. }
  897. }
  898. }
  899. // The grandchildren of the outer polygon are also outer
  900. // polygons. Insert them into the queue for processing.
  901. for (int c = 0; c < numChildren; ++c)
  902. {
  903. // The 'child' is an inner polygon.
  904. std::shared_ptr<Tree> inner = outer->child[c];
  905. // Convert inner points from InputType to ComputeType.
  906. int const numInnerIndices = static_cast<int>(inner->polygon.size());
  907. int const* innerIndices = inner->polygon.data();
  908. for (int i = 0; i < numInnerIndices; ++i)
  909. {
  910. int index = innerIndices[i];
  911. if (!mIsConverted[index])
  912. {
  913. mIsConverted[index] = true;
  914. for (int j = 0; j < 2; ++j)
  915. {
  916. mComputePoints[index][j] = mPoints[index][j];
  917. }
  918. }
  919. }
  920. int numGrandChildren = static_cast<int>(inner->child.size());
  921. for (int g = 0; g < numGrandChildren; ++g)
  922. {
  923. treeQueue.push(inner->child[g]);
  924. }
  925. }
  926. }
  927. return numExtraPoints;
  928. }
  929. // The input polygon.
  930. int mNumPoints;
  931. Vector2<InputType> const* mPoints;
  932. // The output triangulation.
  933. std::vector<std::array<int, 3>> mTriangles;
  934. // The array of points used for geometric queries. If you want to be
  935. // certain of a correct result, choose ComputeType to be BSNumber.
  936. // The InputType points are convertex to ComputeType points on demand;
  937. // the mIsConverted array keeps track of which input points have been
  938. // converted.
  939. std::vector<Vector2<ComputeType>> mComputePoints;
  940. std::vector<bool> mIsConverted;
  941. PrimalQuery2<ComputeType> mQuery;
  942. // Doubly linked lists for storing specially tagged vertices.
  943. class Vertex
  944. {
  945. public:
  946. Vertex()
  947. :
  948. index(-1),
  949. vPrev(-1),
  950. vNext(-1),
  951. sPrev(-1),
  952. sNext(-1),
  953. ePrev(-1),
  954. eNext(-1),
  955. isConvex(false),
  956. isEar(false)
  957. {
  958. }
  959. int index; // index of vertex in position array
  960. int vPrev, vNext; // vertex links for polygon
  961. int sPrev, sNext; // convex/reflex vertex links (disjoint lists)
  962. int ePrev, eNext; // ear links
  963. bool isConvex, isEar;
  964. };
  965. inline Vertex& V(int i)
  966. {
  967. return mVertices[i];
  968. }
  969. bool IsConvex(int i)
  970. {
  971. Vertex& vertex = V(i);
  972. int curr = vertex.index;
  973. int prev = V(vertex.vPrev).index;
  974. int next = V(vertex.vNext).index;
  975. vertex.isConvex = (mQuery.ToLine(curr, prev, next) > 0);
  976. return vertex.isConvex;
  977. }
  978. bool IsEar(int i)
  979. {
  980. Vertex& vertex = V(i);
  981. if (mRFirst == -1)
  982. {
  983. // The remaining polygon is convex.
  984. vertex.isEar = true;
  985. return true;
  986. }
  987. // Search the reflex vertices and test if any are in the triangle
  988. // <V[prev],V[curr],V[next]>.
  989. int prev = V(vertex.vPrev).index;
  990. int curr = vertex.index;
  991. int next = V(vertex.vNext).index;
  992. vertex.isEar = true;
  993. for (int j = mRFirst; j != -1; j = V(j).sNext)
  994. {
  995. // Check if the test vertex is already one of the triangle
  996. // vertices.
  997. if (j == vertex.vPrev || j == i || j == vertex.vNext)
  998. {
  999. continue;
  1000. }
  1001. // V[j] has been ruled out as one of the original vertices of
  1002. // the triangle <V[prev],V[curr],V[next]>. When triangulating
  1003. // polygons with holes, V[j] might be a duplicated vertex, in
  1004. // which case it does not affect the earness of V[curr].
  1005. int test = V(j).index;
  1006. if (mComputePoints[test] == mComputePoints[prev]
  1007. || mComputePoints[test] == mComputePoints[curr]
  1008. || mComputePoints[test] == mComputePoints[next])
  1009. {
  1010. continue;
  1011. }
  1012. // Test if the vertex is inside or on the triangle. When it
  1013. // is, it causes V[curr] not to be an ear.
  1014. if (mQuery.ToTriangle(test, prev, curr, next) <= 0)
  1015. {
  1016. vertex.isEar = false;
  1017. break;
  1018. }
  1019. }
  1020. return vertex.isEar;
  1021. }
  1022. // insert convex vertex
  1023. void InsertAfterC(int i)
  1024. {
  1025. if (mCFirst == -1)
  1026. {
  1027. // Add the first convex vertex.
  1028. mCFirst = i;
  1029. }
  1030. else
  1031. {
  1032. V(mCLast).sNext = i;
  1033. V(i).sPrev = mCLast;
  1034. }
  1035. mCLast = i;
  1036. }
  1037. // insert reflex vertesx
  1038. void InsertAfterR(int i)
  1039. {
  1040. if (mRFirst == -1)
  1041. {
  1042. // Add the first reflex vertex.
  1043. mRFirst = i;
  1044. }
  1045. else
  1046. {
  1047. V(mRLast).sNext = i;
  1048. V(i).sPrev = mRLast;
  1049. }
  1050. mRLast = i;
  1051. }
  1052. // insert ear at end of list
  1053. void InsertEndE(int i)
  1054. {
  1055. if (mEFirst == -1)
  1056. {
  1057. // Add the first ear.
  1058. mEFirst = i;
  1059. mELast = i;
  1060. }
  1061. V(mELast).eNext = i;
  1062. V(i).ePrev = mELast;
  1063. mELast = i;
  1064. }
  1065. // insert ear after efirst
  1066. void InsertAfterE(int i)
  1067. {
  1068. Vertex& first = V(mEFirst);
  1069. int currENext = first.eNext;
  1070. Vertex& vertex = V(i);
  1071. vertex.ePrev = mEFirst;
  1072. vertex.eNext = currENext;
  1073. first.eNext = i;
  1074. V(currENext).ePrev = i;
  1075. }
  1076. // insert ear before efirst
  1077. void InsertBeforeE(int i)
  1078. {
  1079. Vertex& first = V(mEFirst);
  1080. int currEPrev = first.ePrev;
  1081. Vertex& vertex = V(i);
  1082. vertex.ePrev = currEPrev;
  1083. vertex.eNext = mEFirst;
  1084. first.ePrev = i;
  1085. V(currEPrev).eNext = i;
  1086. }
  1087. // remove vertex
  1088. void RemoveV(int i)
  1089. {
  1090. int currVPrev = V(i).vPrev;
  1091. int currVNext = V(i).vNext;
  1092. V(currVPrev).vNext = currVNext;
  1093. V(currVNext).vPrev = currVPrev;
  1094. }
  1095. // remove ear at i
  1096. int RemoveE(int i)
  1097. {
  1098. int currEPrev = V(i).ePrev;
  1099. int currENext = V(i).eNext;
  1100. V(currEPrev).eNext = currENext;
  1101. V(currENext).ePrev = currEPrev;
  1102. return currENext;
  1103. }
  1104. // remove reflex vertex
  1105. void RemoveR(int i)
  1106. {
  1107. LogAssert(mRFirst != -1 && mRLast != -1, "Reflex vertices must exist.");
  1108. if (i == mRFirst)
  1109. {
  1110. mRFirst = V(i).sNext;
  1111. if (mRFirst != -1)
  1112. {
  1113. V(mRFirst).sPrev = -1;
  1114. }
  1115. V(i).sNext = -1;
  1116. }
  1117. else if (i == mRLast)
  1118. {
  1119. mRLast = V(i).sPrev;
  1120. if (mRLast != -1)
  1121. {
  1122. V(mRLast).sNext = -1;
  1123. }
  1124. V(i).sPrev = -1;
  1125. }
  1126. else
  1127. {
  1128. int currSPrev = V(i).sPrev;
  1129. int currSNext = V(i).sNext;
  1130. V(currSPrev).sNext = currSNext;
  1131. V(currSNext).sPrev = currSPrev;
  1132. V(i).sNext = -1;
  1133. V(i).sPrev = -1;
  1134. }
  1135. }
  1136. // The doubly linked list.
  1137. std::vector<Vertex> mVertices;
  1138. int mCFirst, mCLast; // linear list of convex vertices
  1139. int mRFirst, mRLast; // linear list of reflex vertices
  1140. int mEFirst, mELast; // cyclical list of ears
  1141. };
  1142. }