SweepLine.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812
  1. // -----------------------------------------------------------------------
  2. // <copyright file="SweepLine.cs">
  3. // Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
  4. // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
  5. // </copyright>
  6. // -----------------------------------------------------------------------
  7. namespace UnityEngine.U2D.Animation.TriangleNet
  8. .Meshing.Algorithm
  9. {
  10. using System;
  11. using System.Collections.Generic;
  12. using Animation.TriangleNet.Topology;
  13. using Animation.TriangleNet.Geometry;
  14. using Animation.TriangleNet.Tools;
  15. /// <summary>
  16. /// Builds a delaunay triangulation using the sweepline algorithm.
  17. /// </summary>
  18. internal class SweepLine : ITriangulator
  19. {
  20. static int randomseed = 1;
  21. static int SAMPLERATE = 10;
  22. static int randomnation(int choices)
  23. {
  24. randomseed = (randomseed * 1366 + 150889) % 714025;
  25. return randomseed / (714025 / choices + 1);
  26. }
  27. IPredicates predicates;
  28. Mesh mesh;
  29. double xminextreme; // Nonexistent x value used as a flag in sweepline.
  30. List<SplayNode> splaynodes;
  31. public IMesh Triangulate(IList<Vertex> points, Configuration config)
  32. {
  33. this.predicates = config.Predicates();
  34. this.mesh = new Mesh(config);
  35. this.mesh.TransferNodes(points);
  36. // Nonexistent x value used as a flag to mark circle events in sweepline
  37. // Delaunay algorithm.
  38. xminextreme = 10 * mesh.bounds.Left - 9 * mesh.bounds.Right;
  39. SweepEvent[] eventheap;
  40. SweepEvent nextevent;
  41. SweepEvent newevent;
  42. SplayNode splayroot;
  43. Otri bottommost = default(Otri);
  44. Otri searchtri = default(Otri);
  45. Otri fliptri;
  46. Otri lefttri = default(Otri);
  47. Otri righttri = default(Otri);
  48. Otri farlefttri = default(Otri);
  49. Otri farrighttri = default(Otri);
  50. Otri inserttri = default(Otri);
  51. Vertex firstvertex, secondvertex;
  52. Vertex nextvertex, lastvertex;
  53. Vertex connectvertex;
  54. Vertex leftvertex, midvertex, rightvertex;
  55. double lefttest, righttest;
  56. int heapsize;
  57. bool check4events, farrightflag = false;
  58. splaynodes = new List<SplayNode>();
  59. splayroot = null;
  60. heapsize = points.Count;
  61. CreateHeap(out eventheap, heapsize);//, out events, out freeevents);
  62. mesh.MakeTriangle(ref lefttri);
  63. mesh.MakeTriangle(ref righttri);
  64. lefttri.Bond(ref righttri);
  65. lefttri.Lnext();
  66. righttri.Lprev();
  67. lefttri.Bond(ref righttri);
  68. lefttri.Lnext();
  69. righttri.Lprev();
  70. lefttri.Bond(ref righttri);
  71. firstvertex = eventheap[0].vertexEvent;
  72. HeapDelete(eventheap, heapsize, 0);
  73. heapsize--;
  74. do
  75. {
  76. if (heapsize == 0)
  77. {
  78. Log.Instance.Error("Input vertices are all identical.", "SweepLine.Triangulate()");
  79. throw new Exception("Input vertices are all identical.");
  80. }
  81. secondvertex = eventheap[0].vertexEvent;
  82. HeapDelete(eventheap, heapsize, 0);
  83. heapsize--;
  84. if ((firstvertex.x == secondvertex.x) &&
  85. (firstvertex.y == secondvertex.y))
  86. {
  87. if (Log.Verbose)
  88. {
  89. Log.Instance.Warning("A duplicate vertex appeared and was ignored (ID " + secondvertex.id + ").",
  90. "SweepLine.Triangulate().1");
  91. }
  92. secondvertex.type = VertexType.UndeadVertex;
  93. mesh.undeads++;
  94. }
  95. }
  96. while ((firstvertex.x == secondvertex.x) &&
  97. (firstvertex.y == secondvertex.y));
  98. lefttri.SetOrg(firstvertex);
  99. lefttri.SetDest(secondvertex);
  100. righttri.SetOrg(secondvertex);
  101. righttri.SetDest(firstvertex);
  102. lefttri.Lprev(ref bottommost);
  103. lastvertex = secondvertex;
  104. while (heapsize > 0)
  105. {
  106. nextevent = eventheap[0];
  107. HeapDelete(eventheap, heapsize, 0);
  108. heapsize--;
  109. check4events = true;
  110. if (nextevent.xkey < mesh.bounds.Left)
  111. {
  112. fliptri = nextevent.otriEvent;
  113. fliptri.Oprev(ref farlefttri);
  114. Check4DeadEvent(ref farlefttri, eventheap, ref heapsize);
  115. fliptri.Onext(ref farrighttri);
  116. Check4DeadEvent(ref farrighttri, eventheap, ref heapsize);
  117. if (farlefttri.Equals(bottommost))
  118. {
  119. fliptri.Lprev(ref bottommost);
  120. }
  121. mesh.Flip(ref fliptri);
  122. fliptri.SetApex(null);
  123. fliptri.Lprev(ref lefttri);
  124. fliptri.Lnext(ref righttri);
  125. lefttri.Sym(ref farlefttri);
  126. if (randomnation(SAMPLERATE) == 0)
  127. {
  128. fliptri.Sym();
  129. leftvertex = fliptri.Dest();
  130. midvertex = fliptri.Apex();
  131. rightvertex = fliptri.Org();
  132. splayroot = CircleTopInsert(splayroot, lefttri, leftvertex, midvertex, rightvertex, nextevent.ykey);
  133. }
  134. }
  135. else
  136. {
  137. nextvertex = nextevent.vertexEvent;
  138. if ((nextvertex.x == lastvertex.x) &&
  139. (nextvertex.y == lastvertex.y))
  140. {
  141. if (Log.Verbose)
  142. {
  143. Log.Instance.Warning("A duplicate vertex appeared and was ignored (ID " + nextvertex.id + ").",
  144. "SweepLine.Triangulate().2");
  145. }
  146. nextvertex.type = VertexType.UndeadVertex;
  147. mesh.undeads++;
  148. check4events = false;
  149. }
  150. else
  151. {
  152. lastvertex = nextvertex;
  153. splayroot = FrontLocate(splayroot, bottommost, nextvertex, ref searchtri, ref farrightflag);
  154. //bottommost.Copy(ref searchtri);
  155. //farrightflag = false;
  156. //while (!farrightflag && RightOfHyperbola(ref searchtri, nextvertex))
  157. //{
  158. // searchtri.OnextSelf();
  159. // farrightflag = searchtri.Equal(bottommost);
  160. //}
  161. Check4DeadEvent(ref searchtri, eventheap, ref heapsize);
  162. searchtri.Copy(ref farrighttri);
  163. searchtri.Sym(ref farlefttri);
  164. mesh.MakeTriangle(ref lefttri);
  165. mesh.MakeTriangle(ref righttri);
  166. connectvertex = farrighttri.Dest();
  167. lefttri.SetOrg(connectvertex);
  168. lefttri.SetDest(nextvertex);
  169. righttri.SetOrg(nextvertex);
  170. righttri.SetDest(connectvertex);
  171. lefttri.Bond(ref righttri);
  172. lefttri.Lnext();
  173. righttri.Lprev();
  174. lefttri.Bond(ref righttri);
  175. lefttri.Lnext();
  176. righttri.Lprev();
  177. lefttri.Bond(ref farlefttri);
  178. righttri.Bond(ref farrighttri);
  179. if (!farrightflag && farrighttri.Equals(bottommost))
  180. {
  181. lefttri.Copy(ref bottommost);
  182. }
  183. if (randomnation(SAMPLERATE) == 0)
  184. {
  185. splayroot = SplayInsert(splayroot, lefttri, nextvertex);
  186. }
  187. else if (randomnation(SAMPLERATE) == 0)
  188. {
  189. righttri.Lnext(ref inserttri);
  190. splayroot = SplayInsert(splayroot, inserttri, nextvertex);
  191. }
  192. }
  193. }
  194. if (check4events)
  195. {
  196. leftvertex = farlefttri.Apex();
  197. midvertex = lefttri.Dest();
  198. rightvertex = lefttri.Apex();
  199. lefttest = predicates.CounterClockwise(leftvertex, midvertex, rightvertex);
  200. if (lefttest > 0.0)
  201. {
  202. newevent = new SweepEvent();
  203. newevent.xkey = xminextreme;
  204. newevent.ykey = CircleTop(leftvertex, midvertex, rightvertex, lefttest);
  205. newevent.otriEvent = lefttri;
  206. HeapInsert(eventheap, heapsize, newevent);
  207. heapsize++;
  208. lefttri.SetOrg(new SweepEventVertex(newevent));
  209. }
  210. leftvertex = righttri.Apex();
  211. midvertex = righttri.Org();
  212. rightvertex = farrighttri.Apex();
  213. righttest = predicates.CounterClockwise(leftvertex, midvertex, rightvertex);
  214. if (righttest > 0.0)
  215. {
  216. newevent = new SweepEvent();
  217. newevent.xkey = xminextreme;
  218. newevent.ykey = CircleTop(leftvertex, midvertex, rightvertex, righttest);
  219. newevent.otriEvent = farrighttri;
  220. HeapInsert(eventheap, heapsize, newevent);
  221. heapsize++;
  222. farrighttri.SetOrg(new SweepEventVertex(newevent));
  223. }
  224. }
  225. }
  226. splaynodes.Clear();
  227. bottommost.Lprev();
  228. this.mesh.hullsize = RemoveGhosts(ref bottommost);
  229. return this.mesh;
  230. }
  231. #region Heap
  232. void HeapInsert(SweepEvent[] heap, int heapsize, SweepEvent newevent)
  233. {
  234. double eventx, eventy;
  235. int eventnum;
  236. int parent;
  237. bool notdone;
  238. eventx = newevent.xkey;
  239. eventy = newevent.ykey;
  240. eventnum = heapsize;
  241. notdone = eventnum > 0;
  242. while (notdone)
  243. {
  244. parent = (eventnum - 1) >> 1;
  245. if ((heap[parent].ykey < eventy) ||
  246. ((heap[parent].ykey == eventy)
  247. && (heap[parent].xkey <= eventx)))
  248. {
  249. notdone = false;
  250. }
  251. else
  252. {
  253. heap[eventnum] = heap[parent];
  254. heap[eventnum].heapposition = eventnum;
  255. eventnum = parent;
  256. notdone = eventnum > 0;
  257. }
  258. }
  259. heap[eventnum] = newevent;
  260. newevent.heapposition = eventnum;
  261. }
  262. void Heapify(SweepEvent[] heap, int heapsize, int eventnum)
  263. {
  264. SweepEvent thisevent;
  265. double eventx, eventy;
  266. int leftchild, rightchild;
  267. int smallest;
  268. bool notdone;
  269. thisevent = heap[eventnum];
  270. eventx = thisevent.xkey;
  271. eventy = thisevent.ykey;
  272. leftchild = 2 * eventnum + 1;
  273. notdone = leftchild < heapsize;
  274. while (notdone)
  275. {
  276. if ((heap[leftchild].ykey < eventy) ||
  277. ((heap[leftchild].ykey == eventy)
  278. && (heap[leftchild].xkey < eventx)))
  279. {
  280. smallest = leftchild;
  281. }
  282. else
  283. {
  284. smallest = eventnum;
  285. }
  286. rightchild = leftchild + 1;
  287. if (rightchild < heapsize)
  288. {
  289. if ((heap[rightchild].ykey < heap[smallest].ykey) ||
  290. ((heap[rightchild].ykey == heap[smallest].ykey)
  291. && (heap[rightchild].xkey < heap[smallest].xkey)))
  292. {
  293. smallest = rightchild;
  294. }
  295. }
  296. if (smallest == eventnum)
  297. {
  298. notdone = false;
  299. }
  300. else
  301. {
  302. heap[eventnum] = heap[smallest];
  303. heap[eventnum].heapposition = eventnum;
  304. heap[smallest] = thisevent;
  305. thisevent.heapposition = smallest;
  306. eventnum = smallest;
  307. leftchild = 2 * eventnum + 1;
  308. notdone = leftchild < heapsize;
  309. }
  310. }
  311. }
  312. void HeapDelete(SweepEvent[] heap, int heapsize, int eventnum)
  313. {
  314. SweepEvent moveevent;
  315. double eventx, eventy;
  316. int parent;
  317. bool notdone;
  318. moveevent = heap[heapsize - 1];
  319. if (eventnum > 0)
  320. {
  321. eventx = moveevent.xkey;
  322. eventy = moveevent.ykey;
  323. do
  324. {
  325. parent = (eventnum - 1) >> 1;
  326. if ((heap[parent].ykey < eventy) ||
  327. ((heap[parent].ykey == eventy)
  328. && (heap[parent].xkey <= eventx)))
  329. {
  330. notdone = false;
  331. }
  332. else
  333. {
  334. heap[eventnum] = heap[parent];
  335. heap[eventnum].heapposition = eventnum;
  336. eventnum = parent;
  337. notdone = eventnum > 0;
  338. }
  339. }
  340. while (notdone);
  341. }
  342. heap[eventnum] = moveevent;
  343. moveevent.heapposition = eventnum;
  344. Heapify(heap, heapsize - 1, eventnum);
  345. }
  346. void CreateHeap(out SweepEvent[] eventheap, int size)
  347. {
  348. Vertex thisvertex;
  349. int maxevents;
  350. int i;
  351. SweepEvent evt;
  352. maxevents = (3 * size) / 2;
  353. eventheap = new SweepEvent[maxevents];
  354. i = 0;
  355. foreach (var v in mesh.vertices.Values)
  356. {
  357. thisvertex = v;
  358. evt = new SweepEvent();
  359. evt.vertexEvent = thisvertex;
  360. evt.xkey = thisvertex.x;
  361. evt.ykey = thisvertex.y;
  362. HeapInsert(eventheap, i++, evt);
  363. }
  364. }
  365. #endregion
  366. #region Splaytree
  367. SplayNode Splay(SplayNode splaytree, Point searchpoint, ref Otri searchtri)
  368. {
  369. SplayNode child, grandchild;
  370. SplayNode lefttree, righttree;
  371. SplayNode leftright;
  372. Vertex checkvertex;
  373. bool rightofroot, rightofchild;
  374. if (splaytree == null)
  375. {
  376. return null;
  377. }
  378. checkvertex = splaytree.keyedge.Dest();
  379. if (checkvertex == splaytree.keydest)
  380. {
  381. rightofroot = RightOfHyperbola(ref splaytree.keyedge, searchpoint);
  382. if (rightofroot)
  383. {
  384. splaytree.keyedge.Copy(ref searchtri);
  385. child = splaytree.rchild;
  386. }
  387. else
  388. {
  389. child = splaytree.lchild;
  390. }
  391. if (child == null)
  392. {
  393. return splaytree;
  394. }
  395. checkvertex = child.keyedge.Dest();
  396. if (checkvertex != child.keydest)
  397. {
  398. child = Splay(child, searchpoint, ref searchtri);
  399. if (child == null)
  400. {
  401. if (rightofroot)
  402. {
  403. splaytree.rchild = null;
  404. }
  405. else
  406. {
  407. splaytree.lchild = null;
  408. }
  409. return splaytree;
  410. }
  411. }
  412. rightofchild = RightOfHyperbola(ref child.keyedge, searchpoint);
  413. if (rightofchild)
  414. {
  415. child.keyedge.Copy(ref searchtri);
  416. grandchild = Splay(child.rchild, searchpoint, ref searchtri);
  417. child.rchild = grandchild;
  418. }
  419. else
  420. {
  421. grandchild = Splay(child.lchild, searchpoint, ref searchtri);
  422. child.lchild = grandchild;
  423. }
  424. if (grandchild == null)
  425. {
  426. if (rightofroot)
  427. {
  428. splaytree.rchild = child.lchild;
  429. child.lchild = splaytree;
  430. }
  431. else
  432. {
  433. splaytree.lchild = child.rchild;
  434. child.rchild = splaytree;
  435. }
  436. return child;
  437. }
  438. if (rightofchild)
  439. {
  440. if (rightofroot)
  441. {
  442. splaytree.rchild = child.lchild;
  443. child.lchild = splaytree;
  444. }
  445. else
  446. {
  447. splaytree.lchild = grandchild.rchild;
  448. grandchild.rchild = splaytree;
  449. }
  450. child.rchild = grandchild.lchild;
  451. grandchild.lchild = child;
  452. }
  453. else
  454. {
  455. if (rightofroot)
  456. {
  457. splaytree.rchild = grandchild.lchild;
  458. grandchild.lchild = splaytree;
  459. }
  460. else
  461. {
  462. splaytree.lchild = child.rchild;
  463. child.rchild = splaytree;
  464. }
  465. child.lchild = grandchild.rchild;
  466. grandchild.rchild = child;
  467. }
  468. return grandchild;
  469. }
  470. else
  471. {
  472. lefttree = Splay(splaytree.lchild, searchpoint, ref searchtri);
  473. righttree = Splay(splaytree.rchild, searchpoint, ref searchtri);
  474. splaynodes.Remove(splaytree);
  475. if (lefttree == null)
  476. {
  477. return righttree;
  478. }
  479. else if (righttree == null)
  480. {
  481. return lefttree;
  482. }
  483. else if (lefttree.rchild == null)
  484. {
  485. lefttree.rchild = righttree.lchild;
  486. righttree.lchild = lefttree;
  487. return righttree;
  488. }
  489. else if (righttree.lchild == null)
  490. {
  491. righttree.lchild = lefttree.rchild;
  492. lefttree.rchild = righttree;
  493. return lefttree;
  494. }
  495. else
  496. {
  497. // printf("Holy Toledo!!!\n");
  498. leftright = lefttree.rchild;
  499. while (leftright.rchild != null)
  500. {
  501. leftright = leftright.rchild;
  502. }
  503. leftright.rchild = righttree;
  504. return lefttree;
  505. }
  506. }
  507. }
  508. SplayNode SplayInsert(SplayNode splayroot, Otri newkey, Point searchpoint)
  509. {
  510. SplayNode newsplaynode;
  511. newsplaynode = new SplayNode(); //poolalloc(m.splaynodes);
  512. splaynodes.Add(newsplaynode);
  513. newkey.Copy(ref newsplaynode.keyedge);
  514. newsplaynode.keydest = newkey.Dest();
  515. if (splayroot == null)
  516. {
  517. newsplaynode.lchild = null;
  518. newsplaynode.rchild = null;
  519. }
  520. else if (RightOfHyperbola(ref splayroot.keyedge, searchpoint))
  521. {
  522. newsplaynode.lchild = splayroot;
  523. newsplaynode.rchild = splayroot.rchild;
  524. splayroot.rchild = null;
  525. }
  526. else
  527. {
  528. newsplaynode.lchild = splayroot.lchild;
  529. newsplaynode.rchild = splayroot;
  530. splayroot.lchild = null;
  531. }
  532. return newsplaynode;
  533. }
  534. SplayNode FrontLocate(SplayNode splayroot, Otri bottommost, Vertex searchvertex,
  535. ref Otri searchtri, ref bool farright)
  536. {
  537. bool farrightflag;
  538. bottommost.Copy(ref searchtri);
  539. splayroot = Splay(splayroot, searchvertex, ref searchtri);
  540. farrightflag = false;
  541. while (!farrightflag && RightOfHyperbola(ref searchtri, searchvertex))
  542. {
  543. searchtri.Onext();
  544. farrightflag = searchtri.Equals(bottommost);
  545. }
  546. farright = farrightflag;
  547. return splayroot;
  548. }
  549. SplayNode CircleTopInsert(SplayNode splayroot, Otri newkey,
  550. Vertex pa, Vertex pb, Vertex pc, double topy)
  551. {
  552. double ccwabc;
  553. double xac, yac, xbc, ybc;
  554. double aclen2, bclen2;
  555. Point searchpoint = new Point(); // TODO: mesh.nextras
  556. Otri dummytri = default(Otri);
  557. ccwabc = predicates.CounterClockwise(pa, pb, pc);
  558. xac = pa.x - pc.x;
  559. yac = pa.y - pc.y;
  560. xbc = pb.x - pc.x;
  561. ybc = pb.y - pc.y;
  562. aclen2 = xac * xac + yac * yac;
  563. bclen2 = xbc * xbc + ybc * ybc;
  564. searchpoint.x = pc.x - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
  565. searchpoint.y = topy;
  566. return SplayInsert(Splay(splayroot, searchpoint, ref dummytri), newkey, searchpoint);
  567. }
  568. #endregion
  569. bool RightOfHyperbola(ref Otri fronttri, Point newsite)
  570. {
  571. Vertex leftvertex, rightvertex;
  572. double dxa, dya, dxb, dyb;
  573. Statistic.HyperbolaCount++;
  574. leftvertex = fronttri.Dest();
  575. rightvertex = fronttri.Apex();
  576. if ((leftvertex.y < rightvertex.y) ||
  577. ((leftvertex.y == rightvertex.y) &&
  578. (leftvertex.x < rightvertex.x)))
  579. {
  580. if (newsite.x >= rightvertex.x)
  581. {
  582. return true;
  583. }
  584. }
  585. else
  586. {
  587. if (newsite.x <= leftvertex.x)
  588. {
  589. return false;
  590. }
  591. }
  592. dxa = leftvertex.x - newsite.x;
  593. dya = leftvertex.y - newsite.y;
  594. dxb = rightvertex.x - newsite.x;
  595. dyb = rightvertex.y - newsite.y;
  596. return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
  597. }
  598. double CircleTop(Vertex pa, Vertex pb, Vertex pc, double ccwabc)
  599. {
  600. double xac, yac, xbc, ybc, xab, yab;
  601. double aclen2, bclen2, ablen2;
  602. Statistic.CircleTopCount++;
  603. xac = pa.x - pc.x;
  604. yac = pa.y - pc.y;
  605. xbc = pb.x - pc.x;
  606. ybc = pb.y - pc.y;
  607. xab = pa.x - pb.x;
  608. yab = pa.y - pb.y;
  609. aclen2 = xac * xac + yac * yac;
  610. bclen2 = xbc * xbc + ybc * ybc;
  611. ablen2 = xab * xab + yab * yab;
  612. return pc.y + (xac * bclen2 - xbc * aclen2 + Math.Sqrt(aclen2 * bclen2 * ablen2)) / (2.0 * ccwabc);
  613. }
  614. void Check4DeadEvent(ref Otri checktri, SweepEvent[] eventheap, ref int heapsize)
  615. {
  616. SweepEvent deadevent;
  617. SweepEventVertex eventvertex;
  618. int eventnum = -1;
  619. eventvertex = checktri.Org() as SweepEventVertex;
  620. if (eventvertex != null)
  621. {
  622. deadevent = eventvertex.evt;
  623. eventnum = deadevent.heapposition;
  624. HeapDelete(eventheap, heapsize, eventnum);
  625. heapsize--;
  626. checktri.SetOrg(null);
  627. }
  628. }
  629. /// <summary>
  630. /// Removes ghost triangles.
  631. /// </summary>
  632. /// <param name="startghost"></param>
  633. /// <returns>Number of vertices on the hull.</returns>
  634. int RemoveGhosts(ref Otri startghost)
  635. {
  636. Otri searchedge = default(Otri);
  637. Otri dissolveedge = default(Otri);
  638. Otri deadtriangle = default(Otri);
  639. Vertex markorg;
  640. int hullsize;
  641. bool noPoly = !mesh.behavior.Poly;
  642. var dummytri = mesh.dummytri;
  643. // Find an edge on the convex hull to start point location from.
  644. startghost.Lprev(ref searchedge);
  645. searchedge.Sym();
  646. dummytri.neighbors[0] = searchedge;
  647. // Remove the bounding box and count the convex hull edges.
  648. startghost.Copy(ref dissolveedge);
  649. hullsize = 0;
  650. do
  651. {
  652. hullsize++;
  653. dissolveedge.Lnext(ref deadtriangle);
  654. dissolveedge.Lprev();
  655. dissolveedge.Sym();
  656. // If no PSLG is involved, set the boundary markers of all the vertices
  657. // on the convex hull. If a PSLG is used, this step is done later.
  658. if (noPoly)
  659. {
  660. // Watch out for the case where all the input vertices are collinear.
  661. if (dissolveedge.tri.id != Mesh.DUMMY)
  662. {
  663. markorg = dissolveedge.Org();
  664. if (markorg.label == 0)
  665. {
  666. markorg.label = 1;
  667. }
  668. }
  669. }
  670. // Remove a bounding triangle from a convex hull triangle.
  671. dissolveedge.Dissolve(dummytri);
  672. // Find the next bounding triangle.
  673. deadtriangle.Sym(ref dissolveedge);
  674. // Delete the bounding triangle.
  675. mesh.TriangleDealloc(deadtriangle.tri);
  676. }
  677. while (!dissolveedge.Equals(startghost));
  678. return hullsize;
  679. }
  680. #region Internal classes
  681. /// <summary>
  682. /// A node in a heap used to store events for the sweepline Delaunay algorithm.
  683. /// </summary>
  684. /// <remarks>
  685. /// Only used in the sweepline algorithm.
  686. ///
  687. /// Nodes do not point directly to their parents or children in the heap. Instead, each
  688. /// node knows its position in the heap, and can look up its parent and children in a
  689. /// separate array. To distinguish site events from circle events, all circle events are
  690. /// given an invalid (smaller than 'xmin') x-coordinate 'xkey'.
  691. /// </remarks>
  692. class SweepEvent
  693. {
  694. public double xkey, ykey; // Coordinates of the event.
  695. public Vertex vertexEvent; // Vertex event.
  696. public Otri otriEvent; // Circle event.
  697. public int heapposition; // Marks this event's position in the heap.
  698. }
  699. /// <summary>
  700. /// Introducing a new class which aggregates a sweep event is the easiest way
  701. /// to handle the pointer magic of the original code (casting a sweep event
  702. /// to vertex etc.).
  703. /// </summary>
  704. class SweepEventVertex : Vertex
  705. {
  706. public SweepEvent evt;
  707. public SweepEventVertex(SweepEvent e)
  708. {
  709. evt = e;
  710. }
  711. }
  712. /// <summary>
  713. /// A node in the splay tree.
  714. /// </summary>
  715. /// <remarks>
  716. /// Only used in the sweepline algorithm.
  717. ///
  718. /// Each node holds an oriented ghost triangle that represents a boundary edge
  719. /// of the growing triangulation. When a circle event covers two boundary edges
  720. /// with a triangle, so that they are no longer boundary edges, those edges are
  721. /// not immediately deleted from the tree; rather, they are lazily deleted when
  722. /// they are next encountered. (Since only a random sample of boundary edges are
  723. /// kept in the tree, lazy deletion is faster.) 'keydest' is used to verify that
  724. /// a triangle is still the same as when it entered the splay tree; if it has
  725. /// been rotated (due to a circle event), it no longer represents a boundary
  726. /// edge and should be deleted.
  727. /// </remarks>
  728. class SplayNode
  729. {
  730. public Otri keyedge; // Lprev of an edge on the front.
  731. public Vertex keydest; // Used to verify that splay node is still live.
  732. public SplayNode lchild, rchild; // Children in splay tree.
  733. }
  734. #endregion
  735. }
  736. }