intersect2.c 39 KB

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