partition.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #include "config.h"
  11. #include <common/boxes.h>
  12. #include <ortho/partition.h>
  13. #include <ortho/trap.h>
  14. #include <math.h>
  15. #include <stdbool.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <util/alloc.h>
  19. #include <util/bitarray.h>
  20. #include <util/prisize_t.h>
  21. #ifndef DEBUG
  22. #define DEBUG 0
  23. #endif
  24. #define NPOINTS 4 /* only rectangles */
  25. #define TR_FROM_UP 1 /* for traverse-direction */
  26. #define TR_FROM_DN 2
  27. #define SP_SIMPLE_LRUP 1 /* for splitting trapezoids */
  28. #define SP_SIMPLE_LRDN 2
  29. #define SP_2UP_2DN 3
  30. #define SP_2UP_LEFT 4
  31. #define SP_2UP_RIGHT 5
  32. #define SP_2DN_LEFT 6
  33. #define SP_2DN_RIGHT 7
  34. #define SP_NOSPLIT -1
  35. #define DOT(v0, v1) ((v0).x * (v1).x + (v0).y * (v1).y)
  36. #define CROSS_SINE(v0, v1) ((v0).x * (v1).y - (v1).x * (v0).y)
  37. #define LENGTH(v0) hypot((v0).x, (v0).y)
  38. #ifndef HAVE_SRAND48
  39. #define srand48 srand
  40. #endif
  41. #ifdef _WIN32
  42. extern double drand48(void);
  43. #endif
  44. typedef struct {
  45. int vnum;
  46. int next; /* Circularly linked list */
  47. int prev; /* describing the monotone */
  48. int marked; /* polygon */
  49. } monchain_t;
  50. typedef struct {
  51. pointf pt;
  52. int vnext[4]; /* next vertices for the 4 chains */
  53. int vpos[4]; /* position of v in the 4 chains */
  54. int nextfree;
  55. } vertexchain_t;
  56. static int chain_idx, mon_idx;
  57. /* Table to hold all the monotone */
  58. /* polygons . Each monotone polygon */
  59. /* is a circularly linked list */
  60. static monchain_t* mchain;
  61. /* chain init. information. This */
  62. /* is used to decide which */
  63. /* monotone polygon to split if */
  64. /* there are several other */
  65. /* polygons touching at the same */
  66. /* vertex */
  67. static vertexchain_t* vert;
  68. /* contains position of any vertex in */
  69. /* the monotone chain for the polygon */
  70. static int* mon;
  71. /* return a new mon structure from the table */
  72. #define newmon() (++mon_idx)
  73. /* return a new chain element from the table */
  74. #define new_chain_element() (++chain_idx)
  75. static void
  76. convert (boxf bb, int flip, int ccw, pointf* pts)
  77. {
  78. pts[0] = bb.LL;
  79. pts[2] = bb.UR;
  80. if (ccw) {
  81. pts[1].x = bb.UR.x;
  82. pts[1].y = bb.LL.y;
  83. pts[3].x = bb.LL.x;
  84. pts[3].y = bb.UR.y;
  85. }
  86. else {
  87. pts[1].x = bb.LL.x;
  88. pts[1].y = bb.UR.y;
  89. pts[3].x = bb.UR.x;
  90. pts[3].y = bb.LL.y;
  91. }
  92. if (flip) {
  93. int i;
  94. for (i = 0; i < NPOINTS; i++) {
  95. double tmp = pts[i].y;
  96. pts[i].y = pts[i].x;
  97. pts[i].x = -tmp;
  98. }
  99. }
  100. }
  101. static int
  102. store (segment_t* seg, int first, pointf* pts)
  103. {
  104. int i, last = first + NPOINTS - 1;
  105. int j = 0;
  106. for (i = first; i <= last; i++, j++) {
  107. if (i == first) {
  108. seg[i].next = first+1;
  109. seg[i].prev = last;
  110. }
  111. else if (i == last) {
  112. seg[i].next = first;
  113. seg[i].prev = last-1;
  114. }
  115. else {
  116. seg[i].next = i+1;
  117. seg[i].prev = i-1;
  118. }
  119. seg[i].is_inserted = false;
  120. seg[seg[i].prev].v1 = seg[i].v0 = pts[j];
  121. }
  122. return (last+1);
  123. }
  124. static void
  125. genSegments (cell* cells, int ncells, boxf bb, segment_t* seg, int flip)
  126. {
  127. int j = 0, i = 1;
  128. pointf pts[4];
  129. convert (bb, flip, 1, pts);
  130. i = store (seg, i, pts);
  131. for (j = 0; j < ncells; j++) {
  132. convert (cells[j].bb, flip, 0, pts);
  133. i = store (seg, i, pts);
  134. }
  135. }
  136. /* Generate a random permutation of the segments 1..n */
  137. static void
  138. generateRandomOrdering(int n, int* permute)
  139. {
  140. int i, j, tmp;
  141. for (i = 0; i <= n; i++) permute[i] = i;
  142. for (i = 1; i <= n; i++) {
  143. j = i + drand48() * (n + 1 - i);
  144. if (j != i) {
  145. tmp = permute[i];
  146. permute [i] = permute[j];
  147. permute [j] = tmp;
  148. }
  149. }
  150. }
  151. /* Function returns true if the trapezoid lies inside the polygon */
  152. static bool
  153. inside_polygon (trap_t *t, segment_t* seg)
  154. {
  155. int rseg = t->rseg;
  156. if (t->state == ST_INVALID)
  157. return false;
  158. if (t->lseg <= 0 || t->rseg <= 0)
  159. return false;
  160. if ((t->u0 <= 0 && t->u1 <= 0) || (t->d0 <= 0 && t->d1 <= 0)) /* triangle */
  161. return _greater_than(&seg[rseg].v1, &seg[rseg].v0);
  162. return false;
  163. }
  164. static double
  165. get_angle (pointf *vp0, pointf *vpnext, pointf *vp1)
  166. {
  167. pointf v0, v1;
  168. v0.x = vpnext->x - vp0->x;
  169. v0.y = vpnext->y - vp0->y;
  170. v1.x = vp1->x - vp0->x;
  171. v1.y = vp1->y - vp0->y;
  172. if (CROSS_SINE(v0, v1) >= 0) /* sine is positive */
  173. return DOT(v0, v1)/LENGTH(v0)/LENGTH(v1);
  174. else
  175. return -1.0 * DOT(v0, v1)/LENGTH(v0)/LENGTH(v1) - 2;
  176. }
  177. /* (v0, v1) is the new diagonal to be added to the polygon. Find which */
  178. /* chain to use and return the positions of v0 and v1 in p and q */
  179. static void
  180. get_vertex_positions (int v0, int v1, int *ip, int *iq)
  181. {
  182. vertexchain_t *vp0, *vp1;
  183. int i;
  184. double angle, temp;
  185. int tp = 0, tq = 0;
  186. vp0 = &vert[v0];
  187. vp1 = &vert[v1];
  188. /* p is identified as follows. Scan from (v0, v1) rightwards till */
  189. /* you hit the first segment starting from v0. That chain is the */
  190. /* chain of our interest */
  191. angle = -4.0;
  192. for (i = 0; i < 4; i++)
  193. {
  194. if (vp0->vnext[i] <= 0)
  195. continue;
  196. if ((temp = get_angle(&vp0->pt, &(vert[vp0->vnext[i]].pt),
  197. &vp1->pt)) > angle)
  198. {
  199. angle = temp;
  200. tp = i;
  201. }
  202. }
  203. *ip = tp;
  204. /* Do similar actions for q */
  205. angle = -4.0;
  206. for (i = 0; i < 4; i++)
  207. {
  208. if (vp1->vnext[i] <= 0)
  209. continue;
  210. if ((temp = get_angle(&vp1->pt, &(vert[vp1->vnext[i]].pt),
  211. &vp0->pt)) > angle)
  212. {
  213. angle = temp;
  214. tq = i;
  215. }
  216. }
  217. *iq = tq;
  218. }
  219. /* v0 and v1 are specified in anti-clockwise order with respect to
  220. * the current monotone polygon mcur. Split the current polygon into
  221. * two polygons using the diagonal (v0, v1)
  222. */
  223. static int
  224. make_new_monotone_poly (int mcur, int v0, int v1)
  225. {
  226. int p, q, ip, iq;
  227. int mnew = newmon();
  228. int i, j, nf0, nf1;
  229. vertexchain_t *vp0, *vp1;
  230. vp0 = &vert[v0];
  231. vp1 = &vert[v1];
  232. get_vertex_positions(v0, v1, &ip, &iq);
  233. p = vp0->vpos[ip];
  234. q = vp1->vpos[iq];
  235. /* At this stage, we have got the positions of v0 and v1 in the */
  236. /* desired chain. Now modify the linked lists */
  237. i = new_chain_element(); /* for the new list */
  238. j = new_chain_element();
  239. mchain[i].vnum = v0;
  240. mchain[j].vnum = v1;
  241. mchain[i].next = mchain[p].next;
  242. mchain[mchain[p].next].prev = i;
  243. mchain[i].prev = j;
  244. mchain[j].next = i;
  245. mchain[j].prev = mchain[q].prev;
  246. mchain[mchain[q].prev].next = j;
  247. mchain[p].next = q;
  248. mchain[q].prev = p;
  249. nf0 = vp0->nextfree;
  250. nf1 = vp1->nextfree;
  251. vp0->vnext[ip] = v1;
  252. vp0->vpos[nf0] = i;
  253. vp0->vnext[nf0] = mchain[mchain[i].next].vnum;
  254. vp1->vpos[nf1] = j;
  255. vp1->vnext[nf1] = v0;
  256. vp0->nextfree++;
  257. vp1->nextfree++;
  258. #if DEBUG > 0
  259. fprintf(stderr, "make_poly: mcur = %d, (v0, v1) = (%d, %d)\n", mcur, v0, v1);
  260. fprintf(stderr, "next posns = (p, q) = (%d, %d)\n", p, q);
  261. #endif
  262. mon[mcur] = p;
  263. mon[mnew] = i;
  264. return mnew;
  265. }
  266. /* recursively visit all the trapezoids */
  267. static void traverse_polygon(bitarray_t *visited, boxes_t *decomp,
  268. segment_t *seg, traps_t *tr, int mcur, int trnum,
  269. int from, int flip, int dir) {
  270. trap_t *t;
  271. int mnew;
  272. int v0, v1;
  273. if (trnum <= 0 || bitarray_get(*visited, (size_t)trnum))
  274. return;
  275. t = &tr->data[trnum];
  276. bitarray_set(visited, (size_t)trnum, true);
  277. if (t->hi.y > t->lo.y + C_EPS && FP_EQUAL(seg[t->lseg].v0.x, seg[t->lseg].v1.x) &&
  278. FP_EQUAL(seg[t->rseg].v0.x, seg[t->rseg].v1.x)) {
  279. boxf newbox = {0};
  280. if (flip) {
  281. newbox.LL.x = t->lo.y;
  282. newbox.LL.y = -seg[t->rseg].v0.x;
  283. newbox.UR.x = t->hi.y;
  284. newbox.UR.y = -seg[t->lseg].v0.x;
  285. } else {
  286. newbox.LL.x = seg[t->lseg].v0.x;
  287. newbox.LL.y = t->lo.y;
  288. newbox.UR.x = seg[t->rseg].v0.x;
  289. newbox.UR.y = t->hi.y;
  290. }
  291. boxes_append(decomp, newbox);
  292. }
  293. /* We have much more information available here. */
  294. /* rseg: goes upwards */
  295. /* lseg: goes downwards */
  296. /* Initially assume that dir = TR_FROM_DN (from the left) */
  297. /* Switch v0 and v1 if necessary afterwards */
  298. /* special cases for triangles with cusps at the opposite ends. */
  299. /* take care of this first */
  300. if (t->u0 <= 0 && t->u1 <= 0)
  301. {
  302. if (t->d0 > 0 && t->d1 > 0) /* downward opening triangle */
  303. {
  304. v0 = tr->data[t->d1].lseg;
  305. v1 = t->lseg;
  306. if (from == t->d1)
  307. {
  308. mnew = make_new_monotone_poly(mcur, v1, v0);
  309. traverse_polygon(visited, decomp, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP);
  310. traverse_polygon(visited, decomp, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP);
  311. }
  312. else
  313. {
  314. mnew = make_new_monotone_poly(mcur, v0, v1);
  315. traverse_polygon (visited, decomp, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP);
  316. traverse_polygon (visited, decomp, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP);
  317. }
  318. }
  319. else
  320. {
  321. /* Just traverse all neighbours */
  322. traverse_polygon(visited, decomp, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN);
  323. traverse_polygon(visited, decomp, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN);
  324. traverse_polygon(visited, decomp, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP);
  325. traverse_polygon(visited, decomp, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP);
  326. }
  327. }
  328. else if (t->d0 <= 0 && t->d1 <= 0)
  329. {
  330. if (t->u0 > 0 && t->u1 > 0) /* upward opening triangle */
  331. {
  332. v0 = t->rseg;
  333. v1 = tr->data[t->u0].rseg;
  334. if (from == t->u1)
  335. {
  336. mnew = make_new_monotone_poly(mcur, v1, v0);
  337. traverse_polygon(visited, decomp, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN);
  338. traverse_polygon(visited, decomp, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN);
  339. }
  340. else
  341. {
  342. mnew = make_new_monotone_poly(mcur, v0, v1);
  343. traverse_polygon(visited, decomp, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN);
  344. traverse_polygon(visited, decomp, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN);
  345. }
  346. }
  347. else
  348. {
  349. /* Just traverse all neighbours */
  350. traverse_polygon(visited, decomp, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN);
  351. traverse_polygon(visited, decomp, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN);
  352. traverse_polygon(visited, decomp, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP);
  353. traverse_polygon(visited, decomp, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP);
  354. }
  355. }
  356. else if (t->u0 > 0 && t->u1 > 0)
  357. {
  358. if (t->d0 > 0 && t->d1 > 0) /* downward + upward cusps */
  359. {
  360. v0 = tr->data[t->d1].lseg;
  361. v1 = tr->data[t->u0].rseg;
  362. if ((dir == TR_FROM_DN && t->d1 == from) ||
  363. (dir == TR_FROM_UP && t->u1 == from))
  364. {
  365. mnew = make_new_monotone_poly(mcur, v1, v0);
  366. traverse_polygon(visited, decomp, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN);
  367. traverse_polygon(visited, decomp, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP);
  368. traverse_polygon(visited, decomp, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN);
  369. traverse_polygon(visited, decomp, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP);
  370. }
  371. else
  372. {
  373. mnew = make_new_monotone_poly(mcur, v0, v1);
  374. traverse_polygon(visited, decomp, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN);
  375. traverse_polygon(visited, decomp, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP);
  376. traverse_polygon(visited, decomp, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN);
  377. traverse_polygon(visited, decomp, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP);
  378. }
  379. }
  380. else /* only downward cusp */
  381. {
  382. if (_equal_to(&t->lo, &seg[t->lseg].v1))
  383. {
  384. v0 = tr->data[t->u0].rseg;
  385. v1 = seg[t->lseg].next;
  386. if (dir == TR_FROM_UP && t->u0 == from)
  387. {
  388. mnew = make_new_monotone_poly(mcur, v1, v0);
  389. traverse_polygon(visited, decomp, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN);
  390. traverse_polygon(visited, decomp, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP);
  391. traverse_polygon(visited, decomp, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN);
  392. traverse_polygon(visited, decomp, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP);
  393. }
  394. else
  395. {
  396. mnew = make_new_monotone_poly(mcur, v0, v1);
  397. traverse_polygon(visited, decomp, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN);
  398. traverse_polygon(visited, decomp, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP);
  399. traverse_polygon(visited, decomp, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP);
  400. traverse_polygon(visited, decomp, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN);
  401. }
  402. }
  403. else
  404. {
  405. v0 = t->rseg;
  406. v1 = tr->data[t->u0].rseg;
  407. if (dir == TR_FROM_UP && t->u1 == from)
  408. {
  409. mnew = make_new_monotone_poly(mcur, v1, v0);
  410. traverse_polygon(visited, decomp, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN);
  411. traverse_polygon(visited, decomp, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP);
  412. traverse_polygon(visited, decomp, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP);
  413. traverse_polygon(visited, decomp, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN);
  414. }
  415. else
  416. {
  417. mnew = make_new_monotone_poly(mcur, v0, v1);
  418. traverse_polygon(visited, decomp, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN);
  419. traverse_polygon(visited, decomp, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP);
  420. traverse_polygon(visited, decomp, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP);
  421. traverse_polygon(visited, decomp, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN);
  422. }
  423. }
  424. }
  425. }
  426. else if (t->u0 > 0 || t->u1 > 0) /* no downward cusp */
  427. {
  428. if (t->d0 > 0 && t->d1 > 0) /* only upward cusp */
  429. {
  430. if (_equal_to(&t->hi, &seg[t->lseg].v0))
  431. {
  432. v0 = tr->data[t->d1].lseg;
  433. v1 = t->lseg;
  434. if (!(dir == TR_FROM_DN && t->d0 == from))
  435. {
  436. mnew = make_new_monotone_poly(mcur, v1, v0);
  437. traverse_polygon(visited, decomp, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN);
  438. traverse_polygon(visited, decomp, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP);
  439. traverse_polygon(visited, decomp, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN);
  440. traverse_polygon(visited, decomp, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP);
  441. }
  442. else
  443. {
  444. mnew = make_new_monotone_poly(mcur, v0, v1);
  445. traverse_polygon(visited, decomp, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP);
  446. traverse_polygon(visited, decomp, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN);
  447. traverse_polygon(visited, decomp, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN);
  448. traverse_polygon(visited, decomp, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP);
  449. }
  450. }
  451. else
  452. {
  453. v0 = tr->data[t->d1].lseg;
  454. v1 = seg[t->rseg].next;
  455. if (dir == TR_FROM_DN && t->d1 == from)
  456. {
  457. mnew = make_new_monotone_poly(mcur, v1, v0);
  458. traverse_polygon(visited, decomp, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP);
  459. traverse_polygon(visited, decomp, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN);
  460. traverse_polygon(visited, decomp, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN);
  461. traverse_polygon(visited, decomp, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP);
  462. }
  463. else
  464. {
  465. mnew = make_new_monotone_poly(mcur, v0, v1);
  466. traverse_polygon(visited, decomp, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN);
  467. traverse_polygon(visited, decomp, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP);
  468. traverse_polygon(visited, decomp, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN);
  469. traverse_polygon(visited, decomp, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP);
  470. }
  471. }
  472. }
  473. else /* no cusp */
  474. {
  475. if (_equal_to(&t->hi, &seg[t->lseg].v0) &&
  476. _equal_to(&t->lo, &seg[t->rseg].v0))
  477. {
  478. v0 = t->rseg;
  479. v1 = t->lseg;
  480. if (dir == TR_FROM_UP)
  481. {
  482. mnew = make_new_monotone_poly(mcur, v1, v0);
  483. traverse_polygon(visited, decomp, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN);
  484. traverse_polygon(visited, decomp, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN);
  485. traverse_polygon(visited, decomp, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP);
  486. traverse_polygon(visited, decomp, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP);
  487. }
  488. else
  489. {
  490. mnew = make_new_monotone_poly(mcur, v0, v1);
  491. traverse_polygon(visited, decomp, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP);
  492. traverse_polygon(visited, decomp, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP);
  493. traverse_polygon(visited, decomp, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN);
  494. traverse_polygon(visited, decomp, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN);
  495. }
  496. }
  497. else if (_equal_to(&t->hi, &seg[t->rseg].v1) &&
  498. _equal_to(&t->lo, &seg[t->lseg].v1))
  499. {
  500. v0 = seg[t->rseg].next;
  501. v1 = seg[t->lseg].next;
  502. if (dir == TR_FROM_UP)
  503. {
  504. mnew = make_new_monotone_poly(mcur, v1, v0);
  505. traverse_polygon(visited, decomp, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN);
  506. traverse_polygon(visited, decomp, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN);
  507. traverse_polygon(visited, decomp, seg, tr, mnew, t->d1, trnum, flip, TR_FROM_UP);
  508. traverse_polygon(visited, decomp, seg, tr, mnew, t->d0, trnum, flip, TR_FROM_UP);
  509. }
  510. else
  511. {
  512. mnew = make_new_monotone_poly(mcur, v0, v1);
  513. traverse_polygon(visited, decomp, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP);
  514. traverse_polygon(visited, decomp, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP);
  515. traverse_polygon(visited, decomp, seg, tr, mnew, t->u0, trnum, flip, TR_FROM_DN);
  516. traverse_polygon(visited, decomp, seg, tr, mnew, t->u1, trnum, flip, TR_FROM_DN);
  517. }
  518. }
  519. else /* no split possible */
  520. {
  521. traverse_polygon(visited, decomp, seg, tr, mcur, t->u0, trnum, flip, TR_FROM_DN);
  522. traverse_polygon(visited, decomp, seg, tr, mcur, t->d0, trnum, flip, TR_FROM_UP);
  523. traverse_polygon(visited, decomp, seg, tr, mcur, t->u1, trnum, flip, TR_FROM_DN);
  524. traverse_polygon(visited, decomp, seg, tr, mcur, t->d1, trnum, flip, TR_FROM_UP);
  525. }
  526. }
  527. }
  528. }
  529. static void
  530. monotonate_trapezoids(int nsegs, segment_t *seg, traps_t *tr,
  531. int flip, boxes_t *decomp) {
  532. int i;
  533. int tr_start;
  534. bitarray_t visited = bitarray_new(tr->length);
  535. mchain = gv_calloc(tr->length, sizeof(monchain_t));
  536. vert = gv_calloc(nsegs + 1, sizeof(vertexchain_t));
  537. mon = gv_calloc(nsegs, sizeof(int));
  538. /* First locate a trapezoid which lies inside the polygon */
  539. /* and which is triangular */
  540. for (i = 0; i < tr->length; i++)
  541. if (inside_polygon(&tr->data[i], seg)) break;
  542. tr_start = i;
  543. /* Initialise the mon data-structure and start spanning all the */
  544. /* trapezoids within the polygon */
  545. for (i = 1; i <= nsegs; i++) {
  546. mchain[i].prev = seg[i].prev;
  547. mchain[i].next = seg[i].next;
  548. mchain[i].vnum = i;
  549. vert[i].pt = seg[i].v0;
  550. vert[i].vnext[0] = seg[i].next; /* next vertex */
  551. vert[i].vpos[0] = i; /* locn. of next vertex */
  552. vert[i].nextfree = 1;
  553. }
  554. chain_idx = nsegs;
  555. mon_idx = 0;
  556. mon[0] = 1; /* position of any vertex in the first */
  557. /* chain */
  558. /* traverse the polygon */
  559. if (tr->data[tr_start].u0 > 0)
  560. traverse_polygon(&visited, decomp, seg, tr, 0, tr_start,
  561. tr->data[tr_start].u0, flip, TR_FROM_UP);
  562. else if (tr->data[tr_start].d0 > 0)
  563. traverse_polygon(&visited, decomp, seg, tr, 0, tr_start,
  564. tr->data[tr_start].d0, flip, TR_FROM_DN);
  565. bitarray_reset(&visited);
  566. free (mchain);
  567. free (vert);
  568. free (mon);
  569. }
  570. static bool rectIntersect(boxf *d, const boxf r0, const boxf r1) {
  571. double t = fmax(r0.LL.x, r1.LL.x);
  572. d->UR.x = fmin(r0.UR.x, r1.UR.x);
  573. d->LL.x = t;
  574. t = fmax(r0.LL.y, r1.LL.y);
  575. d->UR.y = fmin(r0.UR.y, r1.UR.y);
  576. d->LL.y = t;
  577. return !(d->LL.x >= d->UR.x || d->LL.y >= d->UR.y);
  578. }
  579. #if DEBUG > 1
  580. static void
  581. dumpTrap (trap_t* tr, int n)
  582. {
  583. int i;
  584. for (i = 1; i <= n; i++) {
  585. tr++;
  586. fprintf (stderr, "%d : %d %d (%f,%f) (%f,%f) %d %d %d %d\n", i,
  587. tr->lseg, tr->rseg, tr->hi.x, tr->hi.y, tr->lo.x, tr->lo.y,
  588. tr->u0, tr->u1, tr->d0, tr->d1);
  589. fprintf (stderr, " %d %d %d %d\n", tr->sink, tr->usave,
  590. tr->uside, tr->state);
  591. }
  592. fprintf (stderr, "====\n");
  593. }
  594. static void
  595. dumpSegs (segment_t* sg, int n)
  596. {
  597. int i;
  598. for (i = 1; i <= n; i++) {
  599. sg++;
  600. fprintf (stderr, "%d : (%f,%f) (%f,%f) %d %d %d %d %d\n", i,
  601. sg->v0.x, sg->v0.y, sg->v1.x, sg->v1.y,
  602. (int)sg->is_inserted, sg->root0, sg->root1, sg->next, sg->prev);
  603. }
  604. fprintf (stderr, "====\n");
  605. }
  606. #endif
  607. boxf *partition(cell *cells, int ncells, size_t *nrects, boxf bb) {
  608. int nsegs = 4*(ncells+1);
  609. segment_t* segs = gv_calloc(nsegs + 1, sizeof(segment_t));
  610. int* permute = gv_calloc(nsegs + 1, sizeof(int));
  611. if (DEBUG) {
  612. fprintf (stderr, "cells = %d segs = %d traps = dynamic\n", ncells, nsegs);
  613. }
  614. genSegments (cells, ncells, bb, segs, 0);
  615. if (DEBUG) {
  616. fprintf (stderr, "%d\n\n", ncells+1);
  617. for (int i = 1; i <= nsegs; i++) {
  618. if (i%4 == 1) fprintf(stderr, "4\n");
  619. fprintf (stderr, "%f %f\n", segs[i].v0.x, segs[i].v0.y);
  620. if (i%4 == 0) fprintf(stderr, "\n");
  621. }
  622. }
  623. srand48(173);
  624. generateRandomOrdering (nsegs, permute);
  625. traps_t hor_traps = construct_trapezoids(nsegs, segs, permute);
  626. if (DEBUG) {
  627. fprintf (stderr, "hor traps = %" PRISIZE_T "\n", hor_traps.length);
  628. }
  629. boxes_t hor_decomp = {0};
  630. monotonate_trapezoids(nsegs, segs, &hor_traps, 0, &hor_decomp);
  631. free(hor_traps.data);
  632. genSegments (cells, ncells, bb, segs, 1);
  633. generateRandomOrdering (nsegs, permute);
  634. traps_t ver_traps = construct_trapezoids(nsegs, segs, permute);
  635. if (DEBUG) {
  636. fprintf (stderr, "ver traps = %" PRISIZE_T "\n", ver_traps.length);
  637. }
  638. boxes_t vert_decomp = {0};
  639. monotonate_trapezoids(nsegs, segs, &ver_traps, 1, &vert_decomp);
  640. free(ver_traps.data);
  641. boxes_t rs = {0};
  642. for (size_t i = 0; i < boxes_size(&vert_decomp); ++i)
  643. for (size_t j = 0; j < boxes_size(&hor_decomp); ++j) {
  644. boxf newbox = {0};
  645. if (rectIntersect(&newbox, boxes_get(&vert_decomp, i),
  646. boxes_get(&hor_decomp, j)))
  647. boxes_append(&rs, newbox);
  648. }
  649. free (segs);
  650. free (permute);
  651. boxes_free(&hor_decomp);
  652. boxes_free(&vert_decomp);
  653. *nrects = boxes_size(&rs);
  654. return boxes_detach(&rs);
  655. }