PageRenderTime 43ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/branches/CFDIR/lib/nn/delaunay.c

#
C | 731 lines | 510 code | 109 blank | 112 comment | 154 complexity | 23909320c79e5e2c2646066122592605 MD5 | raw file
Possible License(s): LGPL-2.0, BSD-3-Clause-No-Nuclear-License-2014, Apache-2.0, GPL-2.0
  1. /******************************************************************************
  2. *
  3. * File: delaunay.c
  4. *
  5. * Created: 04/08/2000
  6. *
  7. * Author: Pavel Sakov
  8. * CSIRO Marine Research
  9. *
  10. * Purpose: Delaunay triangulation - a wrapper to triangulate()
  11. *
  12. * Description: None
  13. *
  14. * Revisions: 10/06/2003 PS: delaunay_build(); delaunay_destroy();
  15. * struct delaunay: from now on, only shallow copy of the
  16. * input data is contained in struct delaunay. This saves
  17. * memory and is consistent with libcsa.
  18. *
  19. * Modified: Joao Cardoso, 4/2/2003
  20. * Adapted for use with Qhull instead of "triangle".
  21. *
  22. *****************************************************************************/
  23. #define USE_QHULL
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <assert.h>
  27. #include <math.h>
  28. #include <string.h>
  29. #include <limits.h>
  30. #include <float.h>
  31. #ifdef USE_QHULL
  32. #include <qhull/qhull_a.h>
  33. #else
  34. #include "triangle.h"
  35. #endif
  36. #include "istack.h"
  37. #include "nan.h"
  38. #include "delaunay.h"
  39. int circle_build(circle* c, point* p0, point* p1, point* p2);
  40. int circle_contains(circle* c, point* p);
  41. #ifdef USE_QHULL
  42. static int cw(delaunay *d, triangle *t);
  43. #endif
  44. #ifndef USE_QHULL
  45. static void tio_init(struct triangulateio* tio)
  46. {
  47. tio->pointlist = NULL;
  48. tio->pointattributelist = NULL;
  49. tio->pointmarkerlist = NULL;
  50. tio->numberofpoints = 0;
  51. tio->numberofpointattributes = 0;
  52. tio->trianglelist = NULL;
  53. tio->triangleattributelist = NULL;
  54. tio->trianglearealist = NULL;
  55. tio->neighborlist = NULL;
  56. tio->numberoftriangles = 0;
  57. tio->numberofcorners = 0;
  58. tio->numberoftriangleattributes = 0;
  59. tio->segmentlist = 0;
  60. tio->segmentmarkerlist = NULL;
  61. tio->numberofsegments = 0;
  62. tio->holelist = NULL;
  63. tio->numberofholes = 0;
  64. tio->regionlist = NULL;
  65. tio->numberofregions = 0;
  66. tio->edgelist = NULL;
  67. tio->edgemarkerlist = NULL;
  68. tio->normlist = NULL;
  69. tio->numberofedges = 0;
  70. }
  71. static void tio_destroy(struct triangulateio* tio)
  72. {
  73. if (tio->pointlist != NULL)
  74. free(tio->pointlist);
  75. if (tio->pointattributelist != NULL)
  76. free(tio->pointattributelist);
  77. if (tio->pointmarkerlist != NULL)
  78. free(tio->pointmarkerlist);
  79. if (tio->trianglelist != NULL)
  80. free(tio->trianglelist);
  81. if (tio->triangleattributelist != NULL)
  82. free(tio->triangleattributelist);
  83. if (tio->trianglearealist != NULL)
  84. free(tio->trianglearealist);
  85. if (tio->neighborlist != NULL)
  86. free(tio->neighborlist);
  87. if (tio->segmentlist != NULL)
  88. free(tio->segmentlist);
  89. if (tio->segmentmarkerlist != NULL)
  90. free(tio->segmentmarkerlist);
  91. if (tio->holelist != NULL)
  92. free(tio->holelist);
  93. if (tio->regionlist != NULL)
  94. free(tio->regionlist);
  95. if (tio->edgelist != NULL)
  96. free(tio->edgelist);
  97. if (tio->edgemarkerlist != NULL)
  98. free(tio->edgemarkerlist);
  99. if (tio->normlist != NULL)
  100. free(tio->normlist);
  101. }
  102. static delaunay* delaunay_create()
  103. {
  104. delaunay* d = malloc(sizeof(delaunay));
  105. d->npoints = 0;
  106. d->points = NULL;
  107. d->xmin = DBL_MAX;
  108. d->xmax = -DBL_MAX;
  109. d->ymin = DBL_MAX;
  110. d->ymax = -DBL_MAX;
  111. d->ntriangles = 0;
  112. d->triangles = NULL;
  113. d->circles = NULL;
  114. d->neighbours = NULL;
  115. d->n_point_triangles = NULL;
  116. d->point_triangles = NULL;
  117. d->nedges = 0;
  118. d->edges = NULL;
  119. d->flags = NULL;
  120. d->first_id = -1;
  121. d->t_in = NULL;
  122. d->t_out = NULL;
  123. return d;
  124. }
  125. static void tio2delaunay(struct triangulateio* tio_out, delaunay* d)
  126. {
  127. int i, j;
  128. /*
  129. * I assume that all input points appear in tio_out in the same order as
  130. * they were written to tio_in. I have seen no exceptions so far, even
  131. * if duplicate points were presented. Just in case, let us make a couple
  132. * of checks.
  133. */
  134. assert(tio_out->numberofpoints == d->npoints);
  135. assert(tio_out->pointlist[2 * d->npoints - 2] == d->points[d->npoints - 1].x && tio_out->pointlist[2 * d->npoints - 1] == d->points[d->npoints - 1].y);
  136. for (i = 0, j = 0; i < d->npoints; ++i) {
  137. point* p = &d->points[i];
  138. if (p->x < d->xmin)
  139. d->xmin = p->x;
  140. if (p->x > d->xmax)
  141. d->xmax = p->x;
  142. if (p->y < d->ymin)
  143. d->ymin = p->y;
  144. if (p->y > d->ymax)
  145. d->ymax = p->y;
  146. }
  147. if (nn_verbose) {
  148. fprintf(stderr, "input:\n");
  149. for (i = 0, j = 0; i < d->npoints; ++i) {
  150. point* p = &d->points[i];
  151. fprintf(stderr, " %d: %15.7g %15.7g %15.7g\n", i, p->x, p->y, p->z);
  152. }
  153. }
  154. d->ntriangles = tio_out->numberoftriangles;
  155. if (d->ntriangles > 0) {
  156. d->triangles = malloc(d->ntriangles * sizeof(triangle));
  157. d->neighbours = malloc(d->ntriangles * sizeof(triangle_neighbours));
  158. d->circles = malloc(d->ntriangles * sizeof(circle));
  159. d->n_point_triangles = calloc(d->npoints, sizeof(int));
  160. d->point_triangles = malloc(d->npoints * sizeof(int*));
  161. d->flags = calloc(d->ntriangles, sizeof(int));
  162. }
  163. if (nn_verbose)
  164. fprintf(stderr, "triangles:\n");
  165. for (i = 0; i < d->ntriangles; ++i) {
  166. int offset = i * 3;
  167. triangle* t = &d->triangles[i];
  168. triangle_neighbours* n = &d->neighbours[i];
  169. circle* c = &d->circles[i];
  170. t->vids[0] = tio_out->trianglelist[offset];
  171. t->vids[1] = tio_out->trianglelist[offset + 1];
  172. t->vids[2] = tio_out->trianglelist[offset + 2];
  173. n->tids[0] = tio_out->neighborlist[offset];
  174. n->tids[1] = tio_out->neighborlist[offset + 1];
  175. n->tids[2] = tio_out->neighborlist[offset + 2];
  176. circle_build(c, &d->points[t->vids[0]], &d->points[t->vids[1]], &d->points[t->vids[2]]);
  177. if (nn_verbose)
  178. fprintf(stderr, " %d: (%d,%d,%d)\n", i, t->vids[0], t->vids[1], t->vids[2]);
  179. }
  180. for (i = 0; i < d->ntriangles; ++i) {
  181. triangle* t = &d->triangles[i];
  182. for (j = 0; j < 3; ++j)
  183. d->n_point_triangles[t->vids[j]]++;
  184. }
  185. if (d->ntriangles > 0) {
  186. for (i = 0; i < d->npoints; ++i) {
  187. if (d->n_point_triangles[i] > 0)
  188. d->point_triangles[i] = malloc(d->n_point_triangles[i] * sizeof(int));
  189. else
  190. d->point_triangles[i] = NULL;
  191. d->n_point_triangles[i] = 0;
  192. }
  193. }
  194. for (i = 0; i < d->ntriangles; ++i) {
  195. triangle* t = &d->triangles[i];
  196. for (j = 0; j < 3; ++j) {
  197. int vid = t->vids[j];
  198. d->point_triangles[vid][d->n_point_triangles[vid]] = i;
  199. d->n_point_triangles[vid]++;
  200. }
  201. }
  202. if (tio_out->edgelist != NULL) {
  203. d->nedges = tio_out->numberofedges;
  204. d->edges = malloc(d->nedges * 2 * sizeof(int));
  205. memcpy(d->edges, tio_out->edgelist, d->nedges * 2 * sizeof(int));
  206. }
  207. }
  208. #endif
  209. /* Builds Delaunay triangulation of the given array of points.
  210. *
  211. * @param np Number of points
  212. * @param points Array of points [np] (input)
  213. * @param ns Number of forced segments
  214. * @param segments Array of (forced) segment endpoint indices [2*ns]
  215. * @param nh Number of holes
  216. * @param holes Array of hole (x,y) coordinates [2*nh]
  217. * @return Delaunay triangulation structure with triangulation results
  218. */
  219. delaunay* delaunay_build(int np, point points[], int ns, int segments[], int nh, double holes[])
  220. #ifndef USE_QHULL
  221. {
  222. delaunay* d = delaunay_create();
  223. struct triangulateio tio_in;
  224. struct triangulateio tio_out;
  225. char cmd[64] = "eznC";
  226. int i, j;
  227. assert(sizeof(REAL) == sizeof(double));
  228. tio_init(&tio_in);
  229. if (np == 0) {
  230. free(d);
  231. return NULL;
  232. }
  233. tio_in.pointlist = malloc(np * 2 * sizeof(double));
  234. tio_in.numberofpoints = np;
  235. for (i = 0, j = 0; i < np; ++i) {
  236. tio_in.pointlist[j++] = points[i].x;
  237. tio_in.pointlist[j++] = points[i].y;
  238. }
  239. if (ns > 0) {
  240. tio_in.segmentlist = malloc(ns * 2 * sizeof(int));
  241. tio_in.numberofsegments = ns;
  242. memcpy(tio_in.segmentlist, segments, ns * 2 * sizeof(int));
  243. }
  244. if (nh > 0) {
  245. tio_in.holelist = malloc(nh * 2 * sizeof(double));
  246. tio_in.numberofholes = nh;
  247. memcpy(tio_in.holelist, holes, nh * 2 * sizeof(double));
  248. }
  249. tio_init(&tio_out);
  250. if (!nn_verbose)
  251. strcat(cmd, "Q");
  252. else if (nn_verbose > 1)
  253. strcat(cmd, "VV");
  254. if (ns != 0)
  255. strcat(cmd, "p");
  256. if (nn_verbose)
  257. fflush(stderr);
  258. /*
  259. * climax
  260. */
  261. triangulate(cmd, &tio_in, &tio_out, NULL);
  262. if (nn_verbose)
  263. fflush(stderr);
  264. d->npoints = np;
  265. d->points = points;
  266. tio2delaunay(&tio_out, d);
  267. tio_destroy(&tio_in);
  268. tio_destroy(&tio_out);
  269. return d;
  270. }
  271. #else /* USE_QHULL */
  272. {
  273. delaunay* d = malloc(sizeof(delaunay));
  274. coordT *qpoints; /* array of coordinates for each point */
  275. boolT ismalloc = False; /* True if qhull should free points */
  276. char flags[64] = "qhull d Qbb Qt"; /* option flags for qhull */
  277. facetT *facet,*neighbor,**neighborp; /* variables to walk through facets */
  278. vertexT *vertex, **vertexp; /* variables to walk through vertex */
  279. int curlong, totlong; /* memory remaining after qh_memfreeshort */
  280. FILE *outfile = stdout;
  281. FILE *errfile = stderr; /* error messages from qhull code */
  282. int i, j;
  283. int exitcode;
  284. int dim, ntriangles;
  285. int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
  286. dim = 2;
  287. assert(sizeof(realT) == sizeof(double)); /* Qhull was compiled with doubles? */
  288. if (np == 0 || ns > 0 || nh > 0) {
  289. fprintf(stderr, "segments=%d holes=%d\n, aborting Qhull implementation, use 'triangle' instead.\n", ns, nh);
  290. free(d);
  291. return NULL;
  292. }
  293. qpoints = (coordT *) malloc(np * (dim+1) * sizeof(coordT));
  294. for (i=0; i<np; i++) {
  295. qpoints[i*dim] = points[i].x;
  296. qpoints[i*dim+1] = points[i].y;
  297. }
  298. if (!nn_verbose)
  299. outfile = NULL;
  300. if (nn_verbose)
  301. strcat(flags, " s");
  302. if (nn_verbose > 1)
  303. strcat(flags, " Ts");
  304. if (nn_verbose)
  305. fflush(stderr);
  306. /*
  307. * climax
  308. */
  309. exitcode = qh_new_qhull (dim, np, qpoints, ismalloc,
  310. flags, outfile, errfile);
  311. if(!exitcode) {
  312. if (nn_verbose)
  313. fflush(stderr);
  314. d->xmin = DBL_MAX;
  315. d->xmax = -DBL_MAX;
  316. d->ymin = DBL_MAX;
  317. d->ymax = -DBL_MAX;
  318. d->npoints = np;
  319. d->points = malloc(np * sizeof(point));
  320. for (i = 0; i < np; ++i) {
  321. point* p = &d->points[i];
  322. p->x = points[i].x;
  323. p->y = points[i].y;
  324. p->z = points[i].z;
  325. if (p->x < d->xmin)
  326. d->xmin = p->x;
  327. if (p->x > d->xmax)
  328. d->xmax = p->x;
  329. if (p->y < d->ymin)
  330. d->ymin = p->y;
  331. if (p->y > d->ymax)
  332. d->ymax = p->y;
  333. }
  334. if (nn_verbose) {
  335. fprintf(stderr, "input:\n");
  336. for (i = 0; i < np; ++i) {
  337. point* p = &d->points[i];
  338. fprintf(stderr, " %d: %15.7g %15.7g %15.7g\n",
  339. i, p->x, p->y, p->z);
  340. }
  341. }
  342. qh_findgood_all (qh facet_list);
  343. qh_countfacets (qh facet_list, NULL, !qh_ALL, &numfacets,
  344. &numsimplicial, &totneighbors, &numridges,
  345. &numcoplanars, &numtricoplanars);
  346. ntriangles = 0;
  347. FORALLfacets {
  348. if (!facet->upperdelaunay && facet->simplicial)
  349. ntriangles++;
  350. }
  351. d->ntriangles = ntriangles;
  352. d->triangles = malloc(d->ntriangles * sizeof(triangle));
  353. d->neighbours = malloc(d->ntriangles * sizeof(triangle_neighbours));
  354. d->circles = malloc(d->ntriangles * sizeof(circle));
  355. if (nn_verbose)
  356. fprintf(stderr, "triangles:\tneighbors:\n");
  357. i = 0;
  358. FORALLfacets {
  359. if (!facet->upperdelaunay && facet->simplicial) {
  360. triangle* t = &d->triangles[i];
  361. triangle_neighbours* n = &d->neighbours[i];
  362. circle* c = &d->circles[i];
  363. j = 0;
  364. FOREACHvertex_(facet->vertices)
  365. t->vids[j++] = qh_pointid(vertex->point);
  366. j = 0;
  367. FOREACHneighbor_(facet)
  368. n->tids[j++] = neighbor->visitid ? neighbor->visitid - 1 : - 1;
  369. /* Put triangle vertices in counterclockwise order, as
  370. * 'triangle' do.
  371. * The same needs to be done with the neighbors.
  372. *
  373. * The following works, i.e., it seems that Qhull maintains a
  374. * relationship between the vertices and the neighbors
  375. * triangles, but that is not said anywhere, so if this stop
  376. * working in a future Qhull release, you know what you have
  377. * to do, reorder the neighbors.
  378. */
  379. if(cw(d, t)) {
  380. int tmp = t->vids[1];
  381. t->vids[1] = t->vids[2];
  382. t->vids[2] = tmp;
  383. tmp = n->tids[1];
  384. n->tids[1] = n->tids[2];
  385. n->tids[2] = tmp;
  386. }
  387. circle_build(c, &d->points[t->vids[0]], &d->points[t->vids[1]],
  388. &d->points[t->vids[2]]);
  389. if (nn_verbose)
  390. fprintf(stderr, " %d: (%d,%d,%d)\t(%d,%d,%d)\n",
  391. i, t->vids[0], t->vids[1], t->vids[2], n->tids[0],
  392. n->tids[1], n->tids[2]);
  393. i++;
  394. }
  395. }
  396. d->flags = calloc(d->ntriangles, sizeof(int));
  397. d->n_point_triangles = calloc(d->npoints, sizeof(int));
  398. for (i = 0; i < d->ntriangles; ++i) {
  399. triangle* t = &d->triangles[i];
  400. for (j = 0; j < 3; ++j)
  401. d->n_point_triangles[t->vids[j]]++;
  402. }
  403. d->point_triangles = malloc(d->npoints * sizeof(int*));
  404. for (i = 0; i < d->npoints; ++i) {
  405. if (d->n_point_triangles[i] > 0)
  406. d->point_triangles[i] = malloc(d->n_point_triangles[i] * sizeof(int));
  407. else
  408. d->point_triangles[i] = NULL;
  409. d->n_point_triangles[i] = 0;
  410. }
  411. for (i = 0; i < d->ntriangles; ++i) {
  412. triangle* t = &d->triangles[i];
  413. for (j = 0; j < 3; ++j) {
  414. int vid = t->vids[j];
  415. d->point_triangles[vid][d->n_point_triangles[vid]] = i;
  416. d->n_point_triangles[vid]++;
  417. }
  418. }
  419. d->nedges = 0;
  420. d->edges = NULL;
  421. d->t_in = NULL;
  422. d->t_out = NULL;
  423. d->first_id = -1;
  424. } else {
  425. free(d);
  426. d = NULL;
  427. }
  428. free(qpoints);
  429. qh_freeqhull(!qh_ALL); /* free long memory */
  430. qh_memfreeshort (&curlong, &totlong); /* free short memory and memory allocator */
  431. if (curlong || totlong)
  432. fprintf (errfile,
  433. "qhull: did not free %d bytes of long memory (%d pieces)\n",
  434. totlong, curlong);
  435. return d;
  436. }
  437. /* returns 1 if a,b,c are clockwise ordered */
  438. static int cw(delaunay *d, triangle *t)
  439. {
  440. point* pa = &d->points[t->vids[0]];
  441. point* pb = &d->points[t->vids[1]];
  442. point* pc = &d->points[t->vids[2]];
  443. return ((pb->x - pa->x)*(pc->y - pa->y) <
  444. (pc->x - pa->x)*(pb->y - pa->y));
  445. }
  446. #endif
  447. /* Releases memory engaged in the Delaunay triangulation structure.
  448. *
  449. * @param d Structure to be destroyed
  450. */
  451. void delaunay_destroy(delaunay* d)
  452. {
  453. if (d == NULL)
  454. return;
  455. if (d->point_triangles != NULL) {
  456. int i;
  457. for (i = 0; i < d->npoints; ++i)
  458. if (d->point_triangles[i] != NULL)
  459. free(d->point_triangles[i]);
  460. free(d->point_triangles);
  461. }
  462. if (d->nedges > 0)
  463. free(d->edges);
  464. #ifdef USE_QHULL
  465. /* This is a shallow copy if we're not using qhull so we don't
  466. * need to free it */
  467. if (d->points != NULL)
  468. free(d->points);
  469. #endif
  470. if (d->n_point_triangles != NULL)
  471. free(d->n_point_triangles);
  472. if (d->flags != NULL)
  473. free(d->flags);
  474. if (d->circles != NULL)
  475. free(d->circles);
  476. if (d->neighbours != NULL)
  477. free(d->neighbours);
  478. if (d->triangles != NULL)
  479. free(d->triangles);
  480. if (d->t_in != NULL)
  481. istack_destroy(d->t_in);
  482. if (d->t_out != NULL)
  483. istack_destroy(d->t_out);
  484. free(d);
  485. }
  486. /* Returns whether the point p is on the right side of the vector (p0, p1).
  487. */
  488. static int on_right_side(point* p, point* p0, point* p1)
  489. {
  490. return (p1->x - p->x) * (p0->y - p->y) > (p0->x - p->x) * (p1->y - p->y);
  491. }
  492. /* Finds triangle specified point belongs to (if any).
  493. *
  494. * @param d Delaunay triangulation
  495. * @param p Point to be mapped
  496. * @param seed Triangle index to start with
  497. * @return Triangle id if successful, -1 otherwhile
  498. */
  499. int delaunay_xytoi(delaunay* d, point* p, int id)
  500. {
  501. triangle* t;
  502. int i;
  503. if (p->x < d->xmin || p->x > d->xmax || p->y < d->ymin || p->y > d->ymax)
  504. return -1;
  505. if (id < 0 || id > d->ntriangles)
  506. id = 0;
  507. t = &d->triangles[id];
  508. do {
  509. for (i = 0; i < 3; ++i) {
  510. int i1 = (i + 1) % 3;
  511. if (on_right_side(p, &d->points[t->vids[i]], &d->points[t->vids[i1]])) {
  512. id = d->neighbours[id].tids[(i + 2) % 3];
  513. if (id < 0)
  514. return id;
  515. t = &d->triangles[id];
  516. break;
  517. }
  518. }
  519. } while (i < 3);
  520. return id;
  521. }
  522. /* Finds all tricircles specified point belongs to.
  523. *
  524. * @param d Delaunay triangulation
  525. * @param p Point to be mapped
  526. * @param n Pointer to the number of tricircles within `d' containing `p'
  527. * (output)
  528. * @param out Pointer to an array of indices of the corresponding triangles
  529. * [n] (output)
  530. *
  531. * There is a standard search procedure involving search through triangle
  532. * neighbours (not through vertex neighbours). It must be a bit faster due to
  533. * the smaller number of triangle neighbours (3 per triangle) but can fail
  534. * for a point outside convex hall.
  535. *
  536. * We may wish to modify this procedure in future: first check if the point
  537. * is inside the convex hall, and depending on that use one of the two
  538. * search algorithms. It not 100% clear though whether this will lead to a
  539. * substantial speed gains because of the check on convex hall involved.
  540. */
  541. void delaunay_circles_find(delaunay* d, point* p, int* n, int** out)
  542. {
  543. int i;
  544. if (d->t_in == NULL) {
  545. d->t_in = istack_create();
  546. d->t_out = istack_create();
  547. }
  548. /*
  549. * It is important to have a reasonable seed here. If the last search
  550. * was successful -- start with the last found tricircle, otherwhile (i)
  551. * try to find a triangle containing (x,y); if fails then (ii) check
  552. * tricircles from the last search; if fails then (iii) make linear
  553. * search through all tricircles
  554. */
  555. if (d->first_id < 0 || !circle_contains(&d->circles[d->first_id], p)) {
  556. /*
  557. * if any triangle contains (x,y) -- start with this triangle
  558. */
  559. d->first_id = delaunay_xytoi(d, p, d->first_id);
  560. /*
  561. * if no triangle contains (x,y), there still is a chance that it is
  562. * inside some of circumcircles
  563. */
  564. if (d->first_id < 0) {
  565. int nn = d->t_out->n;
  566. int tid = -1;
  567. /*
  568. * first check results of the last search
  569. */
  570. for (i = 0; i < nn; ++i) {
  571. tid = d->t_out->v[i];
  572. if (circle_contains(&d->circles[tid], p))
  573. break;
  574. }
  575. /*
  576. * if unsuccessful, search through all circles
  577. */
  578. if (tid < 0 || tid == nn) {
  579. double nt = d->ntriangles;
  580. for (tid = 0; tid < nt; ++tid) {
  581. if (circle_contains(&d->circles[tid], p))
  582. break;
  583. }
  584. if (tid == nt) {
  585. istack_reset(d->t_out);
  586. *n = 0;
  587. *out = NULL;
  588. return; /* failed */
  589. }
  590. }
  591. d->first_id = tid;
  592. }
  593. }
  594. istack_reset(d->t_in);
  595. istack_reset(d->t_out);
  596. istack_push(d->t_in, d->first_id);
  597. d->flags[d->first_id] = 1;
  598. /*
  599. * main cycle
  600. */
  601. while (d->t_in->n > 0) {
  602. int tid = istack_pop(d->t_in);
  603. triangle* t = &d->triangles[tid];
  604. if (circle_contains(&d->circles[tid], p)) {
  605. istack_push(d->t_out, tid);
  606. for (i = 0; i < 3; ++i) {
  607. int vid = t->vids[i];
  608. int nt = d->n_point_triangles[vid];
  609. int j;
  610. for (j = 0; j < nt; ++j) {
  611. int ntid = d->point_triangles[vid][j];
  612. if (d->flags[ntid] == 0) {
  613. istack_push(d->t_in, ntid);
  614. d->flags[ntid] = 1;
  615. }
  616. }
  617. }
  618. }
  619. }
  620. *n = d->t_out->n;
  621. *out = d->t_out->v;
  622. }