intersect2.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579
  1. /*!
  2. \file lib/vector/Vlib/intersect2.c
  3. \brief Vector library - intersection
  4. Higher level functions for reading/writing/manipulating vectors.
  5. Some parts of code taken from grass50 v.spag/linecros.c
  6. Based on the following:
  7. <code>
  8. (ax2-ax1)r1 - (bx2-bx1)r2 = ax2 - ax1
  9. (ay2-ay1)r1 - (by2-by1)r2 = ay2 - ay1
  10. </code>
  11. Solving for r1 and r2, if r1 and r2 are between 0 and 1, then line
  12. segments (ax1,ay1)(ax2,ay2) and (bx1,by1)(bx2,by2) intersect.
  13. Intersect 2 line segments.
  14. Returns: 0 - do not intersect
  15. 1 - intersect at one point
  16. <pre>
  17. \ / \ / \ /
  18. \/ \/ \/
  19. /\ \
  20. / \ \
  21. 2 - partial overlap ( \/ )
  22. ------ a ( distance < threshold )
  23. ------ b ( )
  24. 3 - a contains b ( /\ )
  25. ---------- a ----------- a
  26. ---- b ----- b
  27. 4 - b contains a
  28. ---- a ----- a
  29. ---------- b ----------- b
  30. 5 - identical
  31. ---------- a
  32. ---------- b
  33. </pre>
  34. Intersection points:
  35. <pre>
  36. return point1 breakes: point2 breaks: distance1 on: distance2 on:
  37. 0 - - - -
  38. 1 a,b - a b
  39. 2 a b a b
  40. 3 a a a a
  41. 4 b b b b
  42. 5 - - - -
  43. </pre>
  44. Sometimes (often) is important to get the same coordinates for a x
  45. b and b x a. To reach this, the segments a,b are 'sorted' at the
  46. beginning, so that for the same switched segments, results are
  47. identical. (reason is that double values are always rounded because
  48. of limited number of decimal places and for different order of
  49. coordinates, the results would be different)
  50. (C) 2001-2014 by the GRASS Development Team
  51. This program is free software under the GNU General Public License
  52. (>=v2). Read the file COPYING that comes with GRASS for details.
  53. \author Original author CERL, probably Dave Gerdes or Mike Higgins.
  54. \author Update to GRASS 5.7 Radim Blazek.
  55. \author Update to GRASS 7 Markus Metz.
  56. */
  57. #include <stdlib.h>
  58. #include <stdio.h>
  59. #include <unistd.h>
  60. #include <math.h>
  61. #include <grass/vector.h>
  62. #include <grass/rbtree.h>
  63. #include <grass/glocale.h>
  64. /* function prototypes */
  65. static int cmp_cross(const void *pa, const void *pb);
  66. static void add_cross(int asegment, double adistance, int bsegment,
  67. double bdistance, double x, double y);
  68. static double dist2(double x1, double y1, double x2, double y2);
  69. static int debug_level = -1;
  70. #if 0
  71. static int ident(double x1, double y1, double x2, double y2, double thresh);
  72. #endif
  73. static int snap_cross(int asegment, double *adistance, int bsegment,
  74. double *bdistance, double *xc, double *yc);
  75. static int cross_seg(int i, int j, int b);
  76. static int find_cross(int i, int j, int b);
  77. typedef struct
  78. { /* in arrays 0 - A line , 1 - B line */
  79. int segment[2]; /* segment number, start from 0 for first */
  80. double distance[2];
  81. double x, y, z;
  82. } CROSS;
  83. /* Current line in arrays is for some functions like cmp() set by: */
  84. static int current;
  85. static int second; /* line which is not current */
  86. static int a_cross = 0;
  87. static int n_cross;
  88. static CROSS *cross = NULL;
  89. static int *use_cross = NULL;
  90. /* static double rethresh = 0.000001; */ /* TODO */
  91. static double d_ulp(double a, double b)
  92. {
  93. double fa = fabs(a);
  94. double fb = fabs(b);
  95. double dmax, result;
  96. int exp;
  97. dmax = fa;
  98. if (dmax < fb)
  99. dmax = fb;
  100. /* unit in the last place (ULP):
  101. * smallest representable difference
  102. * shift of the exponent
  103. * float: 23, double: 52, middle: 37.5 */
  104. result = frexp(dmax, &exp);
  105. exp -= 38;
  106. result = ldexp(result, exp);
  107. return result;
  108. }
  109. static void add_cross(int asegment, double adistance, int bsegment,
  110. double bdistance, double x, double y)
  111. {
  112. if (n_cross == a_cross) {
  113. /* Must be space + 1, used later for last line point, do it better */
  114. cross =
  115. (CROSS *) G_realloc((void *)cross,
  116. (a_cross + 101) * sizeof(CROSS));
  117. use_cross =
  118. (int *)G_realloc((void *)use_cross,
  119. (a_cross + 101) * sizeof(int));
  120. a_cross += 100;
  121. }
  122. G_debug(5,
  123. " add new cross: aseg/dist = %d/%f bseg/dist = %d/%f, x = %f y = %f",
  124. asegment, adistance, bsegment, bdistance, x, y);
  125. cross[n_cross].segment[0] = asegment;
  126. cross[n_cross].distance[0] = adistance;
  127. cross[n_cross].segment[1] = bsegment;
  128. cross[n_cross].distance[1] = bdistance;
  129. cross[n_cross].x = x;
  130. cross[n_cross].y = y;
  131. n_cross++;
  132. }
  133. static int cmp_cross(const void *pa, const void *pb)
  134. {
  135. CROSS *p1 = (CROSS *) pa;
  136. CROSS *p2 = (CROSS *) pb;
  137. if (p1->segment[current] < p2->segment[current])
  138. return -1;
  139. if (p1->segment[current] > p2->segment[current])
  140. return 1;
  141. /* the same segment */
  142. if (p1->distance[current] < p2->distance[current])
  143. return -1;
  144. if (p1->distance[current] > p2->distance[current])
  145. return 1;
  146. return 0;
  147. }
  148. static double dist2(double x1, double y1, double x2, double y2)
  149. {
  150. double dx, dy;
  151. dx = x2 - x1;
  152. dy = y2 - y1;
  153. return (dx * dx + dy * dy);
  154. }
  155. #if 0
  156. /* returns 1 if points are identical */
  157. static int ident(double x1, double y1, double x2, double y2, double thresh)
  158. {
  159. double dx, dy;
  160. dx = x2 - x1;
  161. dy = y2 - y1;
  162. if ((dx * dx + dy * dy) <= thresh * thresh)
  163. return 1;
  164. return 0;
  165. }
  166. #endif
  167. /* shared by Vect_line_intersection, Vect_line_check_intersection, cross_seg, find_cross */
  168. static struct line_pnts *APnts, *BPnts, *ABPnts[2], *IPnts;
  169. /* Snap breaks to nearest vertices within RE threshold */
  170. /* Calculate distances along segments */
  171. static int snap_cross(int asegment, double *adistance, int bsegment,
  172. double *bdistance, double *xc, double *yc)
  173. {
  174. int seg;
  175. double x, y;
  176. double dist, curdist, dthresh;
  177. /* 1. of A seg */
  178. seg = asegment;
  179. curdist = dist2(*xc, *yc, APnts->x[seg], APnts->y[seg]);
  180. x = APnts->x[seg];
  181. y = APnts->y[seg];
  182. *adistance = curdist;
  183. /* 2. of A seg */
  184. dist = dist2(*xc, *yc, APnts->x[seg + 1], APnts->y[seg + 1]);
  185. if (dist < curdist) {
  186. curdist = dist;
  187. x = APnts->x[seg + 1];
  188. y = APnts->y[seg + 1];
  189. }
  190. /* 1. of B seg */
  191. seg = bsegment;
  192. dist = dist2(*xc, *yc, BPnts->x[seg], BPnts->y[seg]);
  193. *bdistance = dist;
  194. if (dist < curdist) {
  195. curdist = dist;
  196. x = BPnts->x[seg];
  197. y = BPnts->y[seg];
  198. }
  199. /* 2. of B seg */
  200. dist = dist2(*xc, *yc, BPnts->x[seg + 1], BPnts->y[seg + 1]);
  201. if (dist < curdist) {
  202. curdist = dist;
  203. x = BPnts->x[seg + 1];
  204. y = BPnts->y[seg + 1];
  205. }
  206. /* the threshold should not be too small, otherwise we get
  207. * too many tiny new segments
  208. * the threshold should not be too large, otherwise we might
  209. * introduce new crossings
  210. * the smallest difference representable with
  211. * single precision floating point works well with pathological input
  212. * regular input is not affected */
  213. dthresh = d_ulp(x, y);
  214. if (curdist < dthresh * dthresh) { /* was rethresh * rethresh */
  215. *xc = x;
  216. *yc = y;
  217. /* Update distances along segments */
  218. seg = asegment;
  219. *adistance = dist2(*xc, *yc, APnts->x[seg], APnts->y[seg]);
  220. seg = bsegment;
  221. *bdistance = dist2(*xc, *yc, BPnts->x[seg], BPnts->y[seg]);
  222. return 1;
  223. }
  224. return 0;
  225. }
  226. /* break segments */
  227. static int cross_seg(int i, int j, int b)
  228. {
  229. double x1, y1, z1, x2, y2, z2;
  230. double y1min, y1max, y2min, y2max;
  231. double adist, bdist;
  232. int ret;
  233. y1min = APnts->y[i];
  234. y1max = APnts->y[i + 1];
  235. if (APnts->y[i] > APnts->y[i + 1]) {
  236. y1min = APnts->y[i + 1];
  237. y1max = APnts->y[i];
  238. }
  239. y2min = BPnts->y[j];
  240. y2max = BPnts->y[j + 1];
  241. if (BPnts->y[j] > BPnts->y[j + 1]) {
  242. y2min = BPnts->y[j + 1];
  243. y2max = BPnts->y[j];
  244. }
  245. if (y1min > y2max || y1max < y2min)
  246. return 0;
  247. if (b) {
  248. ret = Vect_segment_intersection(APnts->x[i], APnts->y[i],
  249. APnts->z[i],
  250. APnts->x[i + 1], APnts->y[i + 1],
  251. APnts->z[i + 1],
  252. BPnts->x[j], BPnts->y[j],
  253. BPnts->z[j],
  254. BPnts->x[j + 1], BPnts->y[j + 1],
  255. BPnts->z[j + 1],
  256. &x1, &y1, &z1, &x2, &y2, &z2, 0);
  257. }
  258. else {
  259. ret = Vect_segment_intersection(BPnts->x[j], BPnts->y[j],
  260. BPnts->z[j],
  261. BPnts->x[j + 1], BPnts->y[j + 1],
  262. BPnts->z[j + 1],
  263. APnts->x[i], APnts->y[i],
  264. APnts->z[i],
  265. APnts->x[i + 1], APnts->y[i + 1],
  266. APnts->z[i + 1],
  267. &x1, &y1, &z1, &x2, &y2, &z2, 0);
  268. }
  269. /* add ALL (including end points and duplicates), clean later */
  270. if (ret > 0) {
  271. G_debug(2, " -> %d x %d: intersection type = %d", i, j, ret);
  272. if (ret == 1) { /* one intersection on segment A */
  273. G_debug(3, " in %f, %f ", x1, y1);
  274. /* snap intersection only once */
  275. snap_cross(i, &adist, j, &bdist, &x1, &y1);
  276. add_cross(i, adist, j, bdist, x1, y1);
  277. if (APnts == BPnts)
  278. add_cross(j, bdist, i, adist, x1, y1);
  279. }
  280. else if (ret == 2 || ret == 3 || ret == 4 || ret == 5) {
  281. /* partial overlap; a broken in one, b broken in one
  282. * or a contains b; a is broken in 2 points (but 1 may be end)
  283. * or b contains a; b is broken in 2 points (but 1 may be end)
  284. * or identical */
  285. G_debug(3, " in %f, %f; %f, %f", x1, y1, x2, y2);
  286. snap_cross(i, &adist, j, &bdist, &x1, &y1);
  287. add_cross(i, adist, j, bdist, x1, y1);
  288. if (APnts == BPnts)
  289. add_cross(j, bdist, i, adist, x1, y1);
  290. snap_cross(i, &adist, j, &bdist, &x2, &y2);
  291. add_cross(i, adist, j, bdist, x2, y2);
  292. if (APnts == BPnts)
  293. add_cross(j, bdist, i, adist, x2, y2);
  294. }
  295. }
  296. return 1; /* keep going */
  297. }
  298. /* event queue for Bentley-Ottmann */
  299. #define QEVT_IN 1
  300. #define QEVT_OUT 2
  301. #define QEVT_CRS 3
  302. #define GET_PARENT(p, c) ((p) = (int) (((c) - 2) / 3 + 1))
  303. #define GET_CHILD(c, p) ((c) = (int) (((p) * 3) - 1))
  304. struct qitem
  305. {
  306. int l; /* line 0 - A line , 1 - B line */
  307. int s; /* segment index */
  308. int p; /* point index */
  309. int e; /* event type */
  310. };
  311. struct boq
  312. {
  313. int count;
  314. int alloc;
  315. struct qitem *i;
  316. };
  317. /* compare two queue points */
  318. /* return 1 if a < b else 0 */
  319. static int cmp_q_x(struct qitem *a, struct qitem *b)
  320. {
  321. double x1, y1, z1, x2, y2, z2;
  322. x1 = ABPnts[a->l]->x[a->p];
  323. y1 = ABPnts[a->l]->y[a->p];
  324. z1 = ABPnts[a->l]->z[a->p];
  325. x2 = ABPnts[b->l]->x[b->p];
  326. y2 = ABPnts[b->l]->y[b->p];
  327. z2 = ABPnts[b->l]->z[b->p];
  328. if (x1 < x2)
  329. return 1;
  330. if (x1 > x2)
  331. return 0;
  332. if (y1 < y2)
  333. return 1;
  334. if (y1 > y2)
  335. return 0;
  336. if (z1 < z2)
  337. return 1;
  338. if (z1 > z2)
  339. return 0;
  340. if (a->e < b->e)
  341. return 1;
  342. if (a->l < b->l)
  343. return 1;
  344. if (a->s < b->s)
  345. return 1;
  346. return 0;
  347. }
  348. /* sift up routine for min heap */
  349. static int sift_up(struct boq *q, int start)
  350. {
  351. register int parent, child;
  352. struct qitem a, *b;
  353. child = start;
  354. a = q->i[child];
  355. while (child > 1) {
  356. GET_PARENT(parent, child);
  357. b = &q->i[parent];
  358. /* child smaller */
  359. if (cmp_q_x(&a, b)) {
  360. /* push parent point down */
  361. q->i[child] = q->i[parent];
  362. child = parent;
  363. }
  364. else
  365. /* no more sifting up, found new slot for child */
  366. break;
  367. }
  368. /* put point in new slot */
  369. if (child < start) {
  370. q->i[child] = a;
  371. }
  372. return child;
  373. }
  374. static int boq_add(struct boq *q, struct qitem *i)
  375. {
  376. if (q->count + 2 >= q->alloc) {
  377. q->alloc = q->count + 100;
  378. q->i = G_realloc(q->i, q->alloc * sizeof(struct qitem));
  379. }
  380. q->i[q->count + 1] = *i;
  381. sift_up(q, q->count + 1);
  382. q->count++;
  383. return 1;
  384. }
  385. /* drop point routine for min heap */
  386. static int boq_drop(struct boq *q, struct qitem *qi)
  387. {
  388. register int child, childr, parent;
  389. register int i;
  390. struct qitem *a, *b;
  391. if (q->count == 0)
  392. return 0;
  393. *qi = q->i[1];
  394. if (q->count == 1) {
  395. q->count = 0;
  396. return 1;
  397. }
  398. /* start with root */
  399. parent = 1;
  400. /* sift down: move hole back towards bottom of heap */
  401. while (GET_CHILD(child, parent) <= q->count) {
  402. a = &q->i[child];
  403. i = child + 3;
  404. for (childr = child + 1; childr <= q->count && childr < i; childr++) {
  405. b = &q->i[childr];
  406. if (cmp_q_x(b, a)) {
  407. child = childr;
  408. a = &q->i[child];
  409. }
  410. }
  411. /* move hole down */
  412. q->i[parent] = q->i[child];
  413. parent = child;
  414. }
  415. /* hole is in lowest layer, move to heap end */
  416. if (parent < q->count) {
  417. q->i[parent] = q->i[q->count];
  418. /* sift up last swapped point, only necessary if hole moved to heap end */
  419. sift_up(q, parent);
  420. }
  421. /* the actual drop */
  422. q->count--;
  423. return 1;
  424. }
  425. /* compare two tree points */
  426. /* return -1 if a < b, 1 if a > b, 0 if a == b */
  427. static int cmp_t_y(const void *aa, const void *bb)
  428. {
  429. double x1, y1, z1, x2, y2, z2;
  430. struct qitem *a = (struct qitem *) aa;
  431. struct qitem *b = (struct qitem *) bb;
  432. x1 = ABPnts[a->l]->x[a->p];
  433. y1 = ABPnts[a->l]->y[a->p];
  434. z1 = ABPnts[a->l]->z[a->p];
  435. x2 = ABPnts[b->l]->x[b->p];
  436. y2 = ABPnts[b->l]->y[b->p];
  437. z2 = ABPnts[b->l]->z[b->p];
  438. if (y1 < y2)
  439. return -1;
  440. if (y1 > y2)
  441. return 1;
  442. if (x1 < x2)
  443. return -1;
  444. if (x1 > x2)
  445. return 1;
  446. if (z1 < z2)
  447. return -1;
  448. if (z1 > z2)
  449. return 1;
  450. if (a->s < b->s)
  451. return -1;
  452. if (a->s > b->s)
  453. return 1;
  454. return 0;
  455. }
  456. static int boq_load(struct boq *q, struct line_pnts *Pnts,
  457. struct bound_box *abbox, int l, int with_z)
  458. {
  459. int i, loaded;
  460. int vi, vo;
  461. double x1, y1, z1, x2, y2, z2;
  462. struct bound_box box;
  463. struct qitem qi;
  464. /* load Pnts to queue */
  465. qi.l = l;
  466. loaded = 0;
  467. for (i = 0; i < Pnts->n_points - 1; i++) {
  468. x1 = Pnts->x[i];
  469. y1 = Pnts->y[i];
  470. z1 = Pnts->z[i];
  471. x2 = Pnts->x[i + 1];
  472. y2 = Pnts->y[i + 1];
  473. z2 = Pnts->z[i + 1];
  474. if (x1 == x2 && y1 == y2 && (!with_z || z1 == z2))
  475. continue;
  476. if (x1 < x2) {
  477. box.W = x1;
  478. box.E = x2;
  479. }
  480. else {
  481. box.E = x1;
  482. box.W = x2;
  483. }
  484. if (y1 < y2) {
  485. box.S = y1;
  486. box.N = y2;
  487. }
  488. else {
  489. box.N = y1;
  490. box.S = y2;
  491. }
  492. if (z1 < z2) {
  493. box.B = z1;
  494. box.T = z2;
  495. }
  496. else {
  497. box.T = z1;
  498. box.B = z2;
  499. }
  500. box.W -= d_ulp(box.W, box.W);
  501. box.S -= d_ulp(box.S, box.S);
  502. box.B -= d_ulp(box.B, box.B);
  503. box.E += d_ulp(box.E, box.E);
  504. box.N += d_ulp(box.N, box.N);
  505. box.T += d_ulp(box.T, box.T);
  506. if (!Vect_box_overlap(abbox, &box))
  507. continue;
  508. vi = i;
  509. vo = i + 1;
  510. if (x1 < x2) {
  511. vi = i;
  512. vo = i + 1;
  513. }
  514. else if (x1 > x2) {
  515. vi = i + 1;
  516. vo = i;
  517. }
  518. else {
  519. if (y1 < y2) {
  520. vi = i;
  521. vo = i + 1;
  522. }
  523. else if (y1 > y2) {
  524. vi = i + 1;
  525. vo = i;
  526. }
  527. else {
  528. if (z1 < z2) {
  529. vi = i;
  530. vo = i + 1;
  531. }
  532. else if (z1 > z2) {
  533. vi = i + 1;
  534. vo = i;
  535. }
  536. else {
  537. G_fatal_error("Identical points");
  538. }
  539. }
  540. }
  541. qi.s = i;
  542. /* event in */
  543. qi.e = QEVT_IN;
  544. qi.p = vi;
  545. boq_add(q, &qi);
  546. /* event out */
  547. qi.e = QEVT_OUT;
  548. qi.p = vo;
  549. boq_add(q, &qi);
  550. loaded += 2;
  551. }
  552. return loaded;
  553. }
  554. /*!
  555. * \brief Intersect 2 lines.
  556. *
  557. * Creates array of new lines created from original A line, by
  558. * intersection with B line. Points (Points->n_points == 1) are not
  559. * supported. If B line is NULL, A line is intersected with itself.
  560. *
  561. * simplified Bentley–Ottmann Algorithm
  562. *
  563. * \param APoints first input line
  564. * \param BPoints second input line or NULL
  565. * \param[out] ALines array of new lines created from original A line
  566. * \param[out] BLines array of new lines created from original B line
  567. * \param[out] nalines number of new lines (ALines)
  568. * \param[out] nblines number of new lines (BLines)
  569. * \param with_z 3D, not supported!
  570. *
  571. * \return 0 no intersection
  572. * \return 1 intersection found
  573. */
  574. int
  575. Vect_line_intersection2(struct line_pnts *APoints,
  576. struct line_pnts *BPoints,
  577. struct bound_box *pABox,
  578. struct bound_box *pBBox,
  579. struct line_pnts ***ALines,
  580. struct line_pnts ***BLines,
  581. int *nalines, int *nblines, int with_z)
  582. {
  583. int i, j, k, l, nl, last_seg, seg, last;
  584. int n_alive_cross;
  585. double dist, last_x, last_y, last_z;
  586. struct line_pnts **XLines, *Points;
  587. struct line_pnts *Points1, *Points2; /* first, second points */
  588. int seg1, seg2, vert1, vert2;
  589. struct bound_box ABox, BBox, abbox;
  590. struct boq bo_queue;
  591. struct qitem qi, *found;
  592. struct RB_TREE *bo_ta, *bo_tb;
  593. struct RB_TRAV bo_t_trav;
  594. int same = 0;
  595. if (debug_level == -1) {
  596. const char *dstr = G_getenv_nofatal("DEBUG");
  597. if (dstr != NULL)
  598. debug_level = atoi(dstr);
  599. else
  600. debug_level = 0;
  601. }
  602. n_cross = 0;
  603. APnts = APoints;
  604. BPnts = BPoints;
  605. same = 0;
  606. if (!BPoints) {
  607. BPnts = APoints;
  608. same = 1;
  609. }
  610. ABPnts[0] = APnts;
  611. ABPnts[1] = BPnts;
  612. *nalines = 0;
  613. *nblines = 0;
  614. /* RE (representation error).
  615. * RE thresh above is nonsense of course, the RE threshold should be based on
  616. * number of significant digits for double (IEEE-754) which is 15 or 16 and exponent.
  617. * The number above is in fact not required threshold, and will not work
  618. * for example: equator length is 40.075,695 km (8 digits), units are m (+3)
  619. * and we want precision in mm (+ 3) = 14 -> minimum rethresh may be around 0.001
  620. * ?Maybe all nonsense?
  621. * Use rounding error of the unit in the last place ?
  622. * max of fabs(x), fabs(y)
  623. * rethresh = pow(2, log2(max) - 53) */
  624. /* Warning: This function is also used to intersect the line by itself i.e. APoints and
  625. * BPoints are identical. I am not sure if it is clever, but it seems to work, but
  626. * we have to keep this in mind and handle some special cases (maybe) */
  627. /* TODO: 3D, RE threshold, GV_POINTS (line x point) */
  628. /* Take each segment from A and intersect by each segment from B.
  629. *
  630. * All intersections are found first and saved to array, then sorted by a distance along the line,
  631. * and then the line is split to pieces.
  632. *
  633. * Note: If segments are collinear, check if previous/next segments are also collinear,
  634. * in that case do not break:
  635. * +----------+
  636. * +----+-----+ etc.
  637. * doesn't need to be broken
  638. *
  639. * Note: If 2 adjacent segments of line B have common vertex exactly (or within thresh) on line A,
  640. * intersection points for these B segments may differ due to RE:
  641. * ------------ a ----+--+---- ----+--+----
  642. * /\ => / \ or maybe \/
  643. * b0 / \ b1 / \ even: /\
  644. *
  645. * -> solution: snap all breaks to nearest vertices first within RE threshold
  646. *
  647. * Question: Snap all breaks to each other within RE threshold?
  648. *
  649. * Note: If a break is snapped to end point or two breaks are snapped to the same vertex
  650. * resulting new line is degenerated => before line is added to array, it must be checked
  651. * if line is not degenerated
  652. *
  653. * Note: to snap to vertices is important for cases where line A is broken by B and C line
  654. * at the same point:
  655. * \ / b no snap \ /
  656. * \/ could ----+--+----
  657. * ------ a result
  658. * /\ in ?: /\
  659. * / \ c / \
  660. *
  661. * Note: once we snap breaks to vertices, we have to do that for both lines A and B in the same way
  662. * and because we cannot be sure that A childrens will not change a bit by break(s)
  663. * we have to break both A and B at once i.e. in one Vect_line_intersection () call.
  664. */
  665. /* don't modify original bboxes: make a copy of the bboxes */
  666. ABox = *pABox;
  667. BBox = *pBBox;
  668. if (!with_z) {
  669. ABox.T = BBox.T = PORT_DOUBLE_MAX;
  670. ABox.B = BBox.B = -PORT_DOUBLE_MAX;
  671. }
  672. if (!same && !Vect_box_overlap(&ABox, &BBox)) {
  673. return 0;
  674. }
  675. /* overlap box of A line and B line */
  676. abbox = BBox;
  677. if (!same) {
  678. if (abbox.N > ABox.N)
  679. abbox.N = ABox.N;
  680. if (abbox.S < ABox.S)
  681. abbox.S = ABox.S;
  682. if (abbox.E > ABox.E)
  683. abbox.E = ABox.E;
  684. if (abbox.W < ABox.W)
  685. abbox.W = ABox.W;
  686. if (with_z) {
  687. if (abbox.T > BBox.T)
  688. abbox.T = BBox.T;
  689. if (abbox.B < BBox.B)
  690. abbox.B = BBox.B;
  691. }
  692. }
  693. abbox.N += d_ulp(abbox.N, abbox.N);
  694. abbox.S -= d_ulp(abbox.S, abbox.S);
  695. abbox.E += d_ulp(abbox.E, abbox.E);
  696. abbox.W -= d_ulp(abbox.W, abbox.W);
  697. if (with_z) {
  698. abbox.T += d_ulp(abbox.T, abbox.T);
  699. abbox.B -= d_ulp(abbox.B, abbox.B);
  700. }
  701. if (APnts->n_points < 2 || BPnts->n_points < 2) {
  702. G_fatal_error("Intersection with points is not yet supported");
  703. return 0;
  704. }
  705. /* initialize queue */
  706. bo_queue.count = 0;
  707. bo_queue.alloc = 2 * (APnts->n_points + BPnts->n_points);
  708. bo_queue.i = G_malloc(bo_queue.alloc * sizeof(struct qitem));
  709. /* load APnts to queue */
  710. boq_load(&bo_queue, APnts, &abbox, 0, with_z);
  711. if (!same) {
  712. /* load BPnts to queue */
  713. boq_load(&bo_queue, BPnts, &abbox, 1, with_z);
  714. }
  715. /* initialize search tree */
  716. bo_ta = rbtree_create(cmp_t_y, sizeof(struct qitem));
  717. if (same)
  718. bo_tb = bo_ta;
  719. else
  720. bo_tb = rbtree_create(cmp_t_y, sizeof(struct qitem));
  721. /* find intersections */
  722. while (boq_drop(&bo_queue, &qi)) {
  723. if (qi.e == QEVT_IN) {
  724. /* not the original Bentley-Ottmann algorithm */
  725. if (qi.l == 0) {
  726. /* test for intersection of s with all segments in T */
  727. rbtree_init_trav(&bo_t_trav, bo_tb);
  728. while ((found = rbtree_traverse(&bo_t_trav))) {
  729. cross_seg(qi.s, found->s, 0);
  730. }
  731. /* insert s in T */
  732. rbtree_insert(bo_ta, &qi);
  733. }
  734. else {
  735. /* test for intersection of s with all segments in T */
  736. rbtree_init_trav(&bo_t_trav, bo_ta);
  737. while ((found = rbtree_traverse(&bo_t_trav))) {
  738. cross_seg(found->s, qi.s, 1);
  739. }
  740. /* insert s in T */
  741. rbtree_insert(bo_tb, &qi);
  742. }
  743. }
  744. else if (qi.e == QEVT_OUT) {
  745. /* remove from T */
  746. /* adjust p */
  747. if (qi.p == qi.s)
  748. qi.p++;
  749. else
  750. qi.p--;
  751. if (qi.l == 0) {
  752. if (!rbtree_remove(bo_ta, &qi))
  753. G_fatal_error("RB tree error!");
  754. }
  755. else {
  756. if (!rbtree_remove(bo_tb, &qi))
  757. G_fatal_error("RB tree error!");
  758. }
  759. }
  760. }
  761. G_free(bo_queue.i);
  762. rbtree_destroy(bo_ta);
  763. if (!same)
  764. rbtree_destroy(bo_tb);
  765. G_debug(2, "n_cross = %d", n_cross);
  766. /* Lines do not cross each other */
  767. if (n_cross == 0) {
  768. return 0;
  769. }
  770. /* l = 1 ~ line A, l = 2 ~ line B */
  771. nl = 3;
  772. if (same)
  773. nl = 2;
  774. for (l = 1; l < nl; l++) {
  775. for (i = 0; i < n_cross; i++)
  776. use_cross[i] = 1;
  777. /* Create array of lines */
  778. XLines = G_malloc((n_cross + 1) * sizeof(struct line_pnts *));
  779. if (l == 1) {
  780. G_debug(2, "Clean and create array for line A");
  781. Points = APnts;
  782. Points1 = APnts;
  783. Points2 = BPnts;
  784. current = 0;
  785. second = 1;
  786. }
  787. else {
  788. G_debug(2, "Clean and create array for line B");
  789. Points = BPnts;
  790. Points1 = BPnts;
  791. Points2 = APnts;
  792. current = 1;
  793. second = 0;
  794. }
  795. /* Sort points along lines */
  796. qsort((void *)cross, sizeof(char) * n_cross, sizeof(CROSS),
  797. cmp_cross);
  798. /* Print all (raw) breaks */
  799. /* avoid loop when not debugging */
  800. if (debug_level > 2) {
  801. for (i = 0; i < n_cross; i++) {
  802. G_debug(3,
  803. " cross = %d seg1/dist1 = %d/%f seg2/dist2 = %d/%f x = %f y = %f",
  804. i, cross[i].segment[current],
  805. sqrt(cross[i].distance[current]),
  806. cross[i].segment[second], sqrt(cross[i].distance[second]),
  807. cross[i].x, cross[i].y);
  808. }
  809. }
  810. /* Remove breaks on first/last line vertices */
  811. for (i = 0; i < n_cross; i++) {
  812. if (use_cross[i] == 1) {
  813. j = Points1->n_points - 1;
  814. /* Note: */
  815. if ((cross[i].segment[current] == 0 &&
  816. cross[i].x == Points1->x[0] &&
  817. cross[i].y == Points1->y[0]) ||
  818. (cross[i].segment[current] == j - 1 &&
  819. cross[i].x == Points1->x[j] &&
  820. cross[i].y == Points1->y[j])) {
  821. use_cross[i] = 0; /* first/last */
  822. G_debug(3, "cross %d deleted (first/last point)", i);
  823. }
  824. }
  825. }
  826. /* Remove breaks with collinear previous and next segments on 1 and 2 */
  827. /* Note: breaks with collinear previous and nex must be remove duplicates,
  828. * otherwise some cross may be lost. Example (+ is vertex):
  829. * B first cross intersections: A/B segment:
  830. * | 0/0, 0/1, 1/0, 1/1 - collinear previous and next
  831. * AB -----+----+--- A 0/4, 0/5, 1/4, 1/5 - OK
  832. * \___|
  833. * B
  834. * This should not inluence that break is always on first segment, see below (I hope)
  835. */
  836. /* TODO: this doesn't find identical with breaks on revious/next */
  837. for (i = 0; i < n_cross; i++) {
  838. if (use_cross[i] == 0)
  839. continue;
  840. G_debug(3, " is %d between colinear?", i);
  841. seg1 = cross[i].segment[current];
  842. seg2 = cross[i].segment[second];
  843. /* Is it vertex on 1, which? */
  844. if (cross[i].x == Points1->x[seg1] &&
  845. cross[i].y == Points1->y[seg1]) {
  846. vert1 = seg1;
  847. }
  848. else if (cross[i].x == Points1->x[seg1 + 1] &&
  849. cross[i].y == Points1->y[seg1 + 1]) {
  850. vert1 = seg1 + 1;
  851. }
  852. else {
  853. G_debug(3, " -> is not vertex on 1. line");
  854. continue;
  855. }
  856. /* Is it vertex on 2, which? */
  857. /* For 1. line it is easy, because breaks on vertex are always at end vertex
  858. * for 2. line we need to find which vertex is on break if any (vert2 starts from 0) */
  859. if (cross[i].x == Points2->x[seg2] &&
  860. cross[i].y == Points2->y[seg2]) {
  861. vert2 = seg2;
  862. }
  863. else if (cross[i].x == Points2->x[seg2 + 1] &&
  864. cross[i].y == Points2->y[seg2 + 1]) {
  865. vert2 = seg2 + 1;
  866. }
  867. else {
  868. G_debug(3, " -> is not vertex on 2. line");
  869. continue;
  870. }
  871. G_debug(3, " seg1/vert1 = %d/%d seg2/ver2 = %d/%d", seg1,
  872. vert1, seg2, vert2);
  873. /* Check if the second vertex is not first/last */
  874. if (vert2 == 0 || vert2 == Points2->n_points - 1) {
  875. G_debug(3, " -> vertex 2 (%d) is first/last", vert2);
  876. continue;
  877. }
  878. /* Are there first vertices of this segment identical */
  879. if (!((Points1->x[vert1 - 1] == Points2->x[vert2 - 1] &&
  880. Points1->y[vert1 - 1] == Points2->y[vert2 - 1] &&
  881. Points1->x[vert1 + 1] == Points2->x[vert2 + 1] &&
  882. Points1->y[vert1 + 1] == Points2->y[vert2 + 1]) ||
  883. (Points1->x[vert1 - 1] == Points2->x[vert2 + 1] &&
  884. Points1->y[vert1 - 1] == Points2->y[vert2 + 1] &&
  885. Points1->x[vert1 + 1] == Points2->x[vert2 - 1] &&
  886. Points1->y[vert1 + 1] == Points2->y[vert2 - 1])
  887. )
  888. ) {
  889. G_debug(3, " -> previous/next are not identical");
  890. continue;
  891. }
  892. use_cross[i] = 0;
  893. G_debug(3, " -> collinear -> remove");
  894. }
  895. /* Remove duplicates, i.e. merge all identical breaks to one.
  896. * We must be careful because two points with identical coordinates may be distant if measured along
  897. * the line:
  898. * | Segments b0 and b1 overlap, b0 runs up, b1 down.
  899. * | Two inersections may be merged for a, because they are identical,
  900. * -----+---- a but cannot be merged for b, because both b0 and b1 must be broken.
  901. * | I.e. Breaks on b have identical coordinates, but there are not identical
  902. * b0 | b1 if measured along line b.
  903. *
  904. * -> Breaks may be merged as identical if lay on the same segment, or on vertex connecting
  905. * 2 adjacent segments the points lay on
  906. *
  907. * Note: if duplicate is on a vertex, the break is removed from next segment =>
  908. * break on vertex is always on first segment of this vertex (used below)
  909. */
  910. last = -1;
  911. for (i = 0; i < n_cross; i++) {
  912. if (use_cross[i] == 0)
  913. continue;
  914. if (last == -1) { /* set first alive */
  915. last = i;
  916. continue;
  917. }
  918. seg = cross[i].segment[current];
  919. /* compare with last */
  920. G_debug(3, " duplicate ?: cross = %d seg = %d dist = %f", i,
  921. cross[i].segment[current], cross[i].distance[current]);
  922. if ((cross[i].segment[current] == cross[last].segment[current] &&
  923. cross[i].distance[current] == cross[last].distance[current])
  924. || (cross[i].segment[current] ==
  925. cross[last].segment[current] + 1 &&
  926. cross[i].distance[current] == 0 &&
  927. cross[i].x == cross[last].x &&
  928. cross[i].y == cross[last].y)) {
  929. G_debug(3, " cross %d identical to last -> removed", i);
  930. use_cross[i] = 0; /* identical */
  931. }
  932. else {
  933. last = i;
  934. }
  935. }
  936. /* Create array of new lines */
  937. /* Count alive crosses */
  938. n_alive_cross = 0;
  939. G_debug(3, " alive crosses:");
  940. for (i = 0; i < n_cross; i++) {
  941. if (use_cross[i] == 1) {
  942. G_debug(3, " %d", i);
  943. n_alive_cross++;
  944. }
  945. }
  946. k = 0;
  947. if (n_alive_cross > 0) {
  948. /* Add last line point at the end of cross array (cross alley) */
  949. use_cross[n_cross] = 1;
  950. j = Points->n_points - 1;
  951. cross[n_cross].x = Points->x[j];
  952. cross[n_cross].y = Points->y[j];
  953. cross[n_cross].segment[current] = Points->n_points - 2;
  954. last_seg = 0;
  955. last_x = Points->x[0];
  956. last_y = Points->y[0];
  957. last_z = Points->z[0];
  958. /* Go through all cross (+last line point) and create for each new line
  959. * starting at last_* and ending at cross (last point) */
  960. for (i = 0; i <= n_cross; i++) { /* i.e. n_cross + 1 new lines */
  961. seg = cross[i].segment[current];
  962. G_debug(2, "%d seg = %d dist = %f", i, seg,
  963. cross[i].distance[current]);
  964. if (use_cross[i] == 0) {
  965. G_debug(3, " removed -> next");
  966. continue;
  967. }
  968. G_debug(2, " New line:");
  969. XLines[k] = Vect_new_line_struct();
  970. /* add last intersection or first point first */
  971. Vect_append_point(XLines[k], last_x, last_y, last_z);
  972. G_debug(2, " append last vert: %f %f", last_x, last_y);
  973. /* add first points of segments between last and current seg */
  974. for (j = last_seg + 1; j <= seg; j++) {
  975. G_debug(2, " segment j = %d", j);
  976. /* skipp vertex identical to last break */
  977. if ((j == last_seg + 1) && Points->x[j] == last_x &&
  978. Points->y[j] == last_y) {
  979. G_debug(2, " -> skip (identical to last break)");
  980. continue;
  981. }
  982. Vect_append_point(XLines[k], Points->x[j], Points->y[j],
  983. Points->z[j]);
  984. G_debug(2, " append first of seg: %f %f", Points->x[j],
  985. Points->y[j]);
  986. }
  987. last_seg = seg;
  988. last_x = cross[i].x;
  989. last_y = cross[i].y;
  990. last_z = 0;
  991. /* calculate last_z */
  992. if (Points->z[last_seg] == Points->z[last_seg + 1]) {
  993. last_z = Points->z[last_seg + 1];
  994. }
  995. else if (last_x == Points->x[last_seg] &&
  996. last_y == Points->y[last_seg]) {
  997. last_z = Points->z[last_seg];
  998. }
  999. else if (last_x == Points->x[last_seg + 1] &&
  1000. last_y == Points->y[last_seg + 1]) {
  1001. last_z = Points->z[last_seg + 1];
  1002. }
  1003. else {
  1004. dist = dist2(Points->x[last_seg],
  1005. Points->x[last_seg + 1],
  1006. Points->y[last_seg],
  1007. Points->y[last_seg + 1]);
  1008. if (with_z) {
  1009. last_z = (Points->z[last_seg] * sqrt(cross[i].distance[current]) +
  1010. Points->z[last_seg + 1] *
  1011. (sqrt(dist) - sqrt(cross[i].distance[current]))) /
  1012. sqrt(dist);
  1013. }
  1014. }
  1015. /* add current cross or end point */
  1016. Vect_append_point(XLines[k], cross[i].x, cross[i].y, last_z);
  1017. G_debug(2, " append cross / last point: %f %f", cross[i].x,
  1018. cross[i].y);
  1019. /* Check if line is degenerate */
  1020. if (dig_line_degenerate(XLines[k]) > 0) {
  1021. G_debug(2, " line is degenerate -> skipped");
  1022. Vect_destroy_line_struct(XLines[k]);
  1023. }
  1024. else {
  1025. k++;
  1026. }
  1027. }
  1028. }
  1029. if (l == 1) {
  1030. *nalines = k;
  1031. *ALines = XLines;
  1032. }
  1033. else {
  1034. *nblines = k;
  1035. *BLines = XLines;
  1036. }
  1037. }
  1038. return 1;
  1039. }
  1040. /* static int cross_found; */ /* set by find_cross() */
  1041. /* find segment intersection, used by Vect_line_check_intersection2 */
  1042. static int find_cross(int i, int j, int b)
  1043. {
  1044. double x1, y1, z1, x2, y2, z2;
  1045. double y1min, y1max, y2min, y2max;
  1046. int ret;
  1047. y1min = APnts->y[i];
  1048. y1max = APnts->y[i + 1];
  1049. if (APnts->y[i] > APnts->y[i + 1]) {
  1050. y1min = APnts->y[i + 1];
  1051. y1max = APnts->y[i];
  1052. }
  1053. y2min = BPnts->y[j];
  1054. y2max = BPnts->y[j + 1];
  1055. if (BPnts->y[j] > BPnts->y[j + 1]) {
  1056. y2min = BPnts->y[j + 1];
  1057. y2max = BPnts->y[j];
  1058. }
  1059. if (y1min > y2max || y1max < y2min)
  1060. return 0;
  1061. if (b) {
  1062. ret = Vect_segment_intersection(APnts->x[i], APnts->y[i],
  1063. APnts->z[i],
  1064. APnts->x[i + 1], APnts->y[i + 1],
  1065. APnts->z[i + 1],
  1066. BPnts->x[j], BPnts->y[j],
  1067. BPnts->z[j],
  1068. BPnts->x[j + 1], BPnts->y[j + 1],
  1069. BPnts->z[j + 1],
  1070. &x1, &y1, &z1, &x2, &y2, &z2, 0);
  1071. }
  1072. else {
  1073. ret = Vect_segment_intersection(BPnts->x[j], BPnts->y[j],
  1074. BPnts->z[j],
  1075. BPnts->x[j + 1], BPnts->y[j + 1],
  1076. BPnts->z[j + 1],
  1077. APnts->x[i], APnts->y[i],
  1078. APnts->z[i],
  1079. APnts->x[i + 1], APnts->y[i + 1],
  1080. APnts->z[i + 1],
  1081. &x1, &y1, &z1, &x2, &y2, &z2, 0);
  1082. }
  1083. if (!IPnts)
  1084. IPnts = Vect_new_line_struct();
  1085. /* add ALL (including end points and duplicates), clean later */
  1086. switch (ret) {
  1087. case 0:
  1088. case 5:
  1089. break;
  1090. case 1:
  1091. if (0 > Vect_copy_xyz_to_pnts(IPnts, &x1, &y1, &z1, 1))
  1092. G_warning(_("Error while adding point to array. Out of memory"));
  1093. break;
  1094. case 2:
  1095. case 3:
  1096. case 4:
  1097. if (0 > Vect_copy_xyz_to_pnts(IPnts, &x1, &y1, &z1, 1))
  1098. G_warning(_("Error while adding point to array. Out of memory"));
  1099. if (0 > Vect_copy_xyz_to_pnts(IPnts, &x2, &y2, &z2, 1))
  1100. G_warning(_("Error while adding point to array. Out of memory"));
  1101. break;
  1102. }
  1103. return ret;
  1104. }
  1105. /*!
  1106. * \brief Check if 2 lines intersect.
  1107. *
  1108. * Points (Points->n_points == 1) are also supported.
  1109. *
  1110. * \param APoints first input line
  1111. * \param BPoints second input line
  1112. * \param with_z 3D, not supported (only if one or both are points)!
  1113. *
  1114. * \return 0 no intersection
  1115. * \return 1 intersection
  1116. * \return 2 end points only
  1117. */
  1118. int
  1119. Vect_line_check_intersection2(struct line_pnts *APoints,
  1120. struct line_pnts *BPoints, int with_z)
  1121. {
  1122. double dist;
  1123. struct bound_box ABox, BBox, abbox;
  1124. struct boq bo_queue;
  1125. struct qitem qi, *found;
  1126. struct RB_TREE *bo_ta, *bo_tb;
  1127. struct RB_TRAV bo_t_trav;
  1128. int ret, intersect;
  1129. double xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2, xi, yi;
  1130. APnts = APoints;
  1131. BPnts = BPoints;
  1132. ABPnts[0] = APnts;
  1133. ABPnts[1] = BPnts;
  1134. /* TODO: 3D, RE (representation error) threshold, GV_POINTS (line x point) */
  1135. if (!IPnts)
  1136. IPnts = Vect_new_line_struct();
  1137. Vect_reset_line(IPnts);
  1138. /* If one or both are point (Points->n_points == 1) */
  1139. if (APoints->n_points == 1 && BPoints->n_points == 1) {
  1140. if (APoints->x[0] == BPoints->x[0] && APoints->y[0] == BPoints->y[0]) {
  1141. if (!with_z) {
  1142. if (0 >
  1143. Vect_copy_xyz_to_pnts(IPnts, &APoints->x[0],
  1144. &APoints->y[0], NULL, 1))
  1145. G_warning(_("Error while adding point to array. Out of memory"));
  1146. return 1;
  1147. }
  1148. else {
  1149. if (APoints->z[0] == BPoints->z[0]) {
  1150. if (0 >
  1151. Vect_copy_xyz_to_pnts(IPnts, &APoints->x[0],
  1152. &APoints->y[0], &APoints->z[0],
  1153. 1))
  1154. G_warning(_("Error while adding point to array. Out of memory"));
  1155. return 1;
  1156. }
  1157. else
  1158. return 0;
  1159. }
  1160. }
  1161. else {
  1162. return 0;
  1163. }
  1164. }
  1165. if (APoints->n_points == 1) {
  1166. Vect_line_distance(BPoints, APoints->x[0], APoints->y[0],
  1167. APoints->z[0], with_z, NULL, NULL, NULL, &dist,
  1168. NULL, NULL);
  1169. if (dist <= d_ulp(APoints->x[0], APoints->y[0])) {
  1170. if (0 >
  1171. Vect_copy_xyz_to_pnts(IPnts, &APoints->x[0], &APoints->y[0],
  1172. &APoints->z[0], 1))
  1173. G_warning(_("Error while adding point to array. Out of memory"));
  1174. return 1;
  1175. }
  1176. else {
  1177. return 0;
  1178. }
  1179. }
  1180. if (BPoints->n_points == 1) {
  1181. Vect_line_distance(APoints, BPoints->x[0], BPoints->y[0],
  1182. BPoints->z[0], with_z, NULL, NULL, NULL, &dist,
  1183. NULL, NULL);
  1184. if (dist <= d_ulp(BPoints->x[0], BPoints->y[0])) {
  1185. if (0 >
  1186. Vect_copy_xyz_to_pnts(IPnts, &BPoints->x[0], &BPoints->y[0],
  1187. &BPoints->z[0], 1))
  1188. G_warning(_("Error while adding point to array. Out of memory"));
  1189. return 1;
  1190. }
  1191. else
  1192. return 0;
  1193. }
  1194. /* Take each segment from A and find if intersects any segment from B. */
  1195. dig_line_box(APoints, &ABox);
  1196. dig_line_box(BPoints, &BBox);
  1197. if (!with_z) {
  1198. ABox.T = BBox.T = PORT_DOUBLE_MAX;
  1199. ABox.B = BBox.B = -PORT_DOUBLE_MAX;
  1200. }
  1201. if (!Vect_box_overlap(&ABox, &BBox)) {
  1202. return 0;
  1203. }
  1204. /* overlap box */
  1205. abbox = BBox;
  1206. if (abbox.N > ABox.N)
  1207. abbox.N = ABox.N;
  1208. if (abbox.S < ABox.S)
  1209. abbox.S = ABox.S;
  1210. if (abbox.E > ABox.E)
  1211. abbox.E = ABox.E;
  1212. if (abbox.W < ABox.W)
  1213. abbox.W = ABox.W;
  1214. abbox.N += d_ulp(abbox.N, abbox.N);
  1215. abbox.S -= d_ulp(abbox.S, abbox.S);
  1216. abbox.E += d_ulp(abbox.E, abbox.E);
  1217. abbox.W -= d_ulp(abbox.W, abbox.W);
  1218. if (with_z) {
  1219. if (abbox.T > ABox.T)
  1220. abbox.T = ABox.T;
  1221. if (abbox.B < ABox.B)
  1222. abbox.B = ABox.B;
  1223. abbox.T += d_ulp(abbox.T, abbox.T);
  1224. abbox.B -= d_ulp(abbox.B, abbox.B);
  1225. }
  1226. /* initialize queue */
  1227. bo_queue.count = 0;
  1228. bo_queue.alloc = 2 * (APnts->n_points + BPnts->n_points);
  1229. bo_queue.i = G_malloc(bo_queue.alloc * sizeof(struct qitem));
  1230. /* load APnts to queue */
  1231. if (!boq_load(&bo_queue, APnts, &abbox, 0, with_z)) {
  1232. G_free(bo_queue.i);
  1233. return 0;
  1234. }
  1235. /* load BPnts to queue */
  1236. if (!boq_load(&bo_queue, BPnts, &abbox, 1, with_z)) {
  1237. G_free(bo_queue.i);
  1238. return 0;
  1239. }
  1240. /* initialize search tree */
  1241. bo_ta = rbtree_create(cmp_t_y, sizeof(struct qitem));
  1242. bo_tb = rbtree_create(cmp_t_y, sizeof(struct qitem));
  1243. /* find intersection */
  1244. xa1 = APnts->x[0];
  1245. ya1 = APnts->y[0];
  1246. xa2 = APnts->x[APnts->n_points - 1];
  1247. ya2 = APnts->y[APnts->n_points - 1];
  1248. xb1 = BPnts->x[0];
  1249. yb1 = BPnts->y[0];
  1250. xb2 = BPnts->x[BPnts->n_points - 1];
  1251. yb2 = BPnts->y[BPnts->n_points - 1];
  1252. intersect = 0;
  1253. while (boq_drop(&bo_queue, &qi)) {
  1254. if (qi.e == QEVT_IN) {
  1255. /* not the original Bentley-Ottmann algorithm */
  1256. if (qi.l == 0) {
  1257. /* test for intersection of s with all segments in T */
  1258. rbtree_init_trav(&bo_t_trav, bo_tb);
  1259. while ((found = rbtree_traverse(&bo_t_trav))) {
  1260. ret = find_cross(qi.s, found->s, 0);
  1261. if (ret > 0) {
  1262. if (ret != 1) {
  1263. intersect = 1;
  1264. }
  1265. /* intersect at one point */
  1266. else if (intersect != 1) {
  1267. intersect = 1;
  1268. xi = IPnts->x[IPnts->n_points - 1];
  1269. yi = IPnts->y[IPnts->n_points - 1];
  1270. if (xi == xa1 && yi == ya1) {
  1271. if ((xi == xb1 && yi == yb1) ||
  1272. (xi == xb2 && yi == yb2)) {
  1273. intersect = 2;
  1274. }
  1275. }
  1276. else if (xi == xa2 && yi == ya2) {
  1277. if ((xi == xb1 && yi == yb1) ||
  1278. (xi == xb2 && yi == yb2)) {
  1279. intersect = 2;
  1280. }
  1281. }
  1282. }
  1283. }
  1284. if (intersect == 1) {
  1285. break;
  1286. }
  1287. }
  1288. /* insert s in T */
  1289. rbtree_insert(bo_ta, &qi);
  1290. }
  1291. else {
  1292. /* test for intersection of s with all segments in T */
  1293. rbtree_init_trav(&bo_t_trav, bo_ta);
  1294. while ((found = rbtree_traverse(&bo_t_trav))) {
  1295. ret = find_cross(found->s, qi.s, 1);
  1296. if (ret > 0) {
  1297. if (ret != 1) {
  1298. intersect = 1;
  1299. }
  1300. /* intersect at one point */
  1301. else if (intersect != 1) {
  1302. intersect = 1;
  1303. xi = IPnts->x[IPnts->n_points - 1];
  1304. yi = IPnts->y[IPnts->n_points - 1];
  1305. if (xi == xa1 && yi == ya1) {
  1306. if ((xi == xb1 && yi == yb1) ||
  1307. (xi == xb2 && yi == yb2)) {
  1308. intersect = 2;
  1309. }
  1310. }
  1311. else if (xi == xa2 && yi == ya2) {
  1312. if ((xi == xb1 && yi == yb1) ||
  1313. (xi == xb2 && yi == yb2)) {
  1314. intersect = 2;
  1315. }
  1316. }
  1317. }
  1318. }
  1319. if (intersect == 1) {
  1320. break;
  1321. }
  1322. }
  1323. /* insert s in T */
  1324. rbtree_insert(bo_tb, &qi);
  1325. }
  1326. }
  1327. else if (qi.e == QEVT_OUT) {
  1328. /* remove from T */
  1329. /* adjust p */
  1330. if (qi.p == qi.s)
  1331. qi.p++;
  1332. else
  1333. qi.p--;
  1334. if (qi.l == 0) {
  1335. if (!rbtree_remove(bo_ta, &qi))
  1336. G_fatal_error("RB tree error!");
  1337. }
  1338. else {
  1339. if (!rbtree_remove(bo_tb, &qi))
  1340. G_fatal_error("RB tree error!");
  1341. }
  1342. }
  1343. if (intersect == 1) {
  1344. break;
  1345. }
  1346. }
  1347. G_free(bo_queue.i);
  1348. rbtree_destroy(bo_ta);
  1349. rbtree_destroy(bo_tb);
  1350. return intersect;
  1351. }
  1352. /*!
  1353. * \brief Get 2 lines intersection points.
  1354. *
  1355. * A wrapper around Vect_line_check_intersection() function.
  1356. *
  1357. * \param APoints first input line
  1358. * \param BPoints second input line
  1359. * \param[out] IPoints output with intersection points
  1360. * \param with_z 3D, not supported (only if one or both are points)!
  1361. *
  1362. * \return 0 no intersection
  1363. * \return 1 intersection found
  1364. */
  1365. int
  1366. Vect_line_get_intersections2(struct line_pnts *APoints,
  1367. struct line_pnts *BPoints,
  1368. struct line_pnts *IPoints, int with_z)
  1369. {
  1370. int ret;
  1371. IPnts = IPoints;
  1372. ret = Vect_line_check_intersection2(APoints, BPoints, with_z);
  1373. return ret;
  1374. }