e_intersect.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078
  1. #include <stdlib.h>
  2. #include <math.h>
  3. #include <grass/gis.h>
  4. #include "e_intersect.h"
  5. #define SWAP(a,b) {t = a; a = b; b = t;}
  6. #ifndef MIN
  7. #define MIN(X,Y) ((X<Y)?X:Y)
  8. #endif
  9. #ifndef MAX
  10. #define MAX(X,Y) ((X>Y)?X:Y)
  11. #endif
  12. #define D (ax2-ax1)*(by1-by2) - (ay2-ay1)*(bx1-bx2)
  13. #define DA (bx1-ax1)*(by1-by2) - (by1-ay1)*(bx1-bx2)
  14. #define DB (ax2-ax1)*(by1-ay1) - (ay2-ay1)*(bx1-ax1)
  15. #ifdef ASDASDASFDSAFFDAS
  16. mpf_t p11, p12, p21, p22, t1, t2;
  17. mpf_t dd, dda, ddb, delta;
  18. mpf_t rra, rrb;
  19. int initialized = 0;
  20. void initialize_mpf_vars()
  21. {
  22. mpf_set_default_prec(2048);
  23. mpf_init(p11);
  24. mpf_init(p12);
  25. mpf_init(p21);
  26. mpf_init(p22);
  27. mpf_init(t1);
  28. mpf_init(t2);
  29. mpf_init(dd);
  30. mpf_init(dda);
  31. mpf_init(ddb);
  32. mpf_init(delta);
  33. mpf_init(rra);
  34. mpf_init(rrb);
  35. initialized = 1;
  36. }
  37. /*
  38. Caclulates:
  39. |a11-b11 a12-b12|
  40. |a21-b21 a22-b22|
  41. */
  42. void det22(mpf_t rop, double a11, double b11, double a12, double b12,
  43. double a21, double b21, double a22, double b22)
  44. {
  45. mpf_set_d(t1, a11);
  46. mpf_set_d(t2, b11);
  47. mpf_sub(p11, t1, t2);
  48. mpf_set_d(t1, a12);
  49. mpf_set_d(t2, b12);
  50. mpf_sub(p12, t1, t2);
  51. mpf_set_d(t1, a21);
  52. mpf_set_d(t2, b21);
  53. mpf_sub(p21, t1, t2);
  54. mpf_set_d(t1, a22);
  55. mpf_set_d(t2, b22);
  56. mpf_sub(p22, t1, t2);
  57. mpf_mul(t1, p11, p22);
  58. mpf_mul(t2, p12, p21);
  59. mpf_sub(rop, t1, t2);
  60. return;
  61. }
  62. void swap(double *a, double *b)
  63. {
  64. double t = *a;
  65. *a = *b;
  66. *b = t;
  67. return;
  68. }
  69. /* multi-precision version */
  70. int segment_intersection_2d_e(double ax1, double ay1, double ax2, double ay2,
  71. double bx1, double by1, double bx2, double by2,
  72. double *x1, double *y1, double *x2, double *y2)
  73. {
  74. double t;
  75. double max_ax, min_ax, max_ay, min_ay;
  76. double max_bx, min_bx, max_by, min_by;
  77. int sgn_d, sgn_da, sgn_db;
  78. int vertical;
  79. int f11, f12, f21, f22;
  80. mp_exp_t exp;
  81. char *s;
  82. if (!initialized)
  83. initialize_mpf_vars();
  84. /* TODO: Works for points ? */
  85. G_debug(3, "segment_intersection_2d_e()");
  86. G_debug(4, " ax1 = %.18f, ay1 = %.18f", ax1, ay1);
  87. G_debug(4, " ax2 = %.18f, ay2 = %.18f", ax2, ay2);
  88. G_debug(4, " bx1 = %.18f, by1 = %.18f", bx1, by1);
  89. G_debug(4, " bx2 = %.18f, by2 = %.18f", bx2, by2);
  90. f11 = ((ax1 == bx1) && (ay1 == by1));
  91. f12 = ((ax1 == bx2) && (ay1 == by2));
  92. f21 = ((ax2 == bx1) && (ay2 == by1));
  93. f22 = ((ax2 == bx2) && (ay2 == by2));
  94. /* Check for identical segments */
  95. if ((f11 && f22) || (f12 && f21)) {
  96. G_debug(3, " identical segments");
  97. *x1 = ax1;
  98. *y1 = ay1;
  99. *x2 = ax2;
  100. *y2 = ay2;
  101. return 5;
  102. }
  103. /* Check for identical endpoints */
  104. if (f11 || f12) {
  105. G_debug(3, " connected by endpoints");
  106. *x1 = ax1;
  107. *y1 = ay1;
  108. return 1;
  109. }
  110. if (f21 || f22) {
  111. G_debug(3, " connected by endpoints");
  112. *x1 = ax2;
  113. *y1 = ay2;
  114. return 1;
  115. }
  116. if ((MAX(ax1, ax2) < MIN(bx1, bx2)) || (MAX(bx1, bx2) < MIN(ax1, ax2))) {
  117. G_debug(3, " no intersection (disjoint bounding boxes)");
  118. return 0;
  119. }
  120. if ((MAX(ay1, ay2) < MIN(by1, by2)) || (MAX(by1, by2) < MIN(ay1, ay2))) {
  121. G_debug(3, " no intersection (disjoint bounding boxes)");
  122. return 0;
  123. }
  124. det22(dd, ax2, ax1, bx1, bx2, ay2, ay1, by1, by2);
  125. sgn_d = mpf_sgn(dd);
  126. if (sgn_d != 0) {
  127. G_debug(3, " general position");
  128. det22(dda, bx1, ax1, bx1, bx2, by1, ay1, by1, by2);
  129. sgn_da = mpf_sgn(dda);
  130. /*mpf_div(rra, dda, dd);
  131. mpf_div(rrb, ddb, dd);
  132. s = mpf_get_str(NULL, &exp, 10, 40, rra);
  133. G_debug(4, " ra = %sE%d", (s[0]==0)?"0":s, exp);
  134. s = mpf_get_str(NULL, &exp, 10, 24, rrb);
  135. G_debug(4, " rb = %sE%d", (s[0]==0)?"0":s, exp);
  136. */
  137. if (sgn_d > 0) {
  138. if ((sgn_da < 0) || (mpf_cmp(dda, dd) > 0)) {
  139. G_debug(3, " no intersection");
  140. return 0;
  141. }
  142. det22(ddb, ax2, ax1, bx1, ax1, ay2, ay1, by1, ay1);
  143. sgn_db = mpf_sgn(ddb);
  144. if ((sgn_db < 0) || (mpf_cmp(ddb, dd) > 0)) {
  145. G_debug(3, " no intersection");
  146. return 0;
  147. }
  148. }
  149. else { /* if sgn_d < 0 */
  150. if ((sgn_da > 0) || (mpf_cmp(dda, dd) < 0)) {
  151. G_debug(3, " no intersection");
  152. return 0;
  153. }
  154. det22(ddb, ax2, ax1, bx1, ax1, ay2, ay1, by1, ay1);
  155. sgn_db = mpf_sgn(ddb);
  156. if ((sgn_db > 0) || (mpf_cmp(ddb, dd) < 0)) {
  157. G_debug(3, " no intersection");
  158. return 0;
  159. }
  160. }
  161. /*G_debug(3, " ra=%.17g rb=%.17g", mpf_get_d(dda)/mpf_get_d(dd), mpf_get_d(ddb)/mpf_get_d(dd)); */
  162. /*G_debug(3, " sgn_d=%d sgn_da=%d sgn_db=%d cmp(dda,dd)=%d cmp(ddb,dd)=%d", sgn_d, sgn_da, sgn_db, mpf_cmp(dda, dd), mpf_cmp(ddb, dd)); */
  163. mpf_set_d(delta, ax2 - ax1);
  164. mpf_mul(t1, dda, delta);
  165. mpf_div(t2, t1, dd);
  166. *x1 = ax1 + mpf_get_d(t2);
  167. mpf_set_d(delta, ay2 - ay1);
  168. mpf_mul(t1, dda, delta);
  169. mpf_div(t2, t1, dd);
  170. *y1 = ay1 + mpf_get_d(t2);
  171. G_debug(3, " intersection %.16g, %.16g", *x1, *y1);
  172. return 1;
  173. }
  174. /* segments are parallel or collinear */
  175. det22(dda, bx1, ax1, bx1, bx2, by1, ay1, by1, by2);
  176. sgn_da = mpf_sgn(dda);
  177. if (sgn_da != 0) {
  178. /* segments are parallel */
  179. G_debug(3, " parallel segments");
  180. return 0;
  181. }
  182. /* segments are colinear. check for overlap */
  183. /* swap endpoints if needed */
  184. /* if segments are vertical, we swap x-coords with y-coords */
  185. vertical = 0;
  186. if (ax1 > ax2) {
  187. SWAP(ax1, ax2);
  188. SWAP(ay1, ay2);
  189. }
  190. else if (ax1 == ax2) {
  191. vertical = 1;
  192. if (ay1 > ay2)
  193. SWAP(ay1, ay2);
  194. SWAP(ax1, ay1);
  195. SWAP(ax2, ay2);
  196. }
  197. if (bx1 > bx2) {
  198. SWAP(bx1, bx2);
  199. SWAP(by1, by2);
  200. }
  201. else if (bx1 == bx2) {
  202. if (by1 > by2)
  203. SWAP(by1, by2);
  204. SWAP(bx1, by1);
  205. SWAP(bx2, by2);
  206. }
  207. G_debug(3, " collinear segments");
  208. if ((bx2 < ax1) || (bx1 > ax2)) {
  209. G_debug(3, " no intersection");
  210. return 0;
  211. }
  212. /* there is overlap or connected end points */
  213. G_debug(3, " overlap");
  214. /* a contains b */
  215. if ((ax1 < bx1) && (ax2 > bx2)) {
  216. G_debug(3, " a contains b");
  217. if (!vertical) {
  218. *x1 = bx1;
  219. *y1 = by1;
  220. *x2 = bx2;
  221. *y2 = by2;
  222. }
  223. else {
  224. *x1 = by1;
  225. *y1 = bx1;
  226. *x2 = by2;
  227. *y2 = bx2;
  228. }
  229. return 3;
  230. }
  231. /* b contains a */
  232. if ((ax1 > bx1) && (ax2 < bx2)) {
  233. G_debug(3, " b contains a");
  234. if (!vertical) {
  235. *x1 = bx1;
  236. *y1 = by1;
  237. *x2 = bx2;
  238. *y2 = by2;
  239. }
  240. else {
  241. *x1 = by1;
  242. *y1 = bx1;
  243. *x2 = by2;
  244. *y2 = bx2;
  245. }
  246. return 4;
  247. }
  248. /* general overlap, 2 intersection points */
  249. G_debug(3, " partial overlap");
  250. if ((bx1 > ax1) && (bx1 < ax2)) { /* b1 is in a */
  251. if (!vertical) {
  252. *x1 = bx1;
  253. *y1 = by1;
  254. *x2 = ax2;
  255. *y2 = ay2;
  256. }
  257. else {
  258. *x1 = by1;
  259. *y1 = bx1;
  260. *x2 = ay2;
  261. *y2 = ax2;
  262. }
  263. return 2;
  264. }
  265. if ((bx2 > ax1) && (bx2 < ax2)) { /* b2 is in a */
  266. if (!vertical) {
  267. *x1 = bx2;
  268. *y1 = by2;
  269. *x2 = ax1;
  270. *y2 = ay1;
  271. }
  272. else {
  273. *x1 = by2;
  274. *y1 = bx2;
  275. *x2 = ay1;
  276. *y2 = ax1;
  277. }
  278. return 2;
  279. }
  280. /* should not be reached */
  281. G_warning(("segment_intersection_2d() ERROR (should not be reached)"));
  282. G_warning("%.16g %.16g", ax1, ay1);
  283. G_warning("%.16g %.16g", ax2, ay2);
  284. G_warning("x");
  285. G_warning("%.16g %.16g", bx1, by1);
  286. G_warning("%.16g %.16g", bx2, by2);
  287. return 0;
  288. }
  289. #endif
  290. /* OLD */
  291. /* tollerance aware version */
  292. /* TODO: fix all ==s left */
  293. int segment_intersection_2d_tol(double ax1, double ay1, double ax2,
  294. double ay2, double bx1, double by1,
  295. double bx2, double by2, double *x1,
  296. double *y1, double *x2, double *y2,
  297. double tol)
  298. {
  299. double tola, tolb;
  300. double d, d1, d2, ra, rb, t;
  301. int switched = 0;
  302. /* TODO: Works for points ? */
  303. G_debug(4, "segment_intersection_2d()");
  304. G_debug(4, " ax1 = %.18f, ay1 = %.18f", ax1, ay1);
  305. G_debug(4, " ax2 = %.18f, ay2 = %.18f", ax2, ay2);
  306. G_debug(4, " bx1 = %.18f, by1 = %.18f", bx1, by1);
  307. G_debug(4, " bx2 = %.18f, by2 = %.18f", bx2, by2);
  308. /* Check identical lines */
  309. if ((FEQUAL(ax1, bx1, tol) && FEQUAL(ay1, by1, tol) &&
  310. FEQUAL(ax2, bx2, tol) && FEQUAL(ay2, by2, tol)) ||
  311. (FEQUAL(ax1, bx2, tol) && FEQUAL(ay1, by2, tol) &&
  312. FEQUAL(ax2, bx1, tol) && FEQUAL(ay2, by1, tol))) {
  313. G_debug(2, " -> identical segments");
  314. *x1 = ax1;
  315. *y1 = ay1;
  316. *x2 = ax2;
  317. *y2 = ay2;
  318. return 5;
  319. }
  320. /* 'Sort' lines by x1, x2, y1, y2 */
  321. if (bx1 < ax1)
  322. switched = 1;
  323. else if (bx1 == ax1) {
  324. if (bx2 < ax2)
  325. switched = 1;
  326. else if (bx2 == ax2) {
  327. if (by1 < ay1)
  328. switched = 1;
  329. else if (by1 == ay1) {
  330. if (by2 < ay2)
  331. switched = 1; /* by2 != ay2 (would be identical */
  332. }
  333. }
  334. }
  335. if (switched) {
  336. t = ax1;
  337. ax1 = bx1;
  338. bx1 = t;
  339. t = ay1;
  340. ay1 = by1;
  341. by1 = t;
  342. t = ax2;
  343. ax2 = bx2;
  344. bx2 = t;
  345. t = ay2;
  346. ay2 = by2;
  347. by2 = t;
  348. }
  349. d = (ax2 - ax1) * (by1 - by2) - (ay2 - ay1) * (bx1 - bx2);
  350. d1 = (bx1 - ax1) * (by1 - by2) - (by1 - ay1) * (bx1 - bx2);
  351. d2 = (ax2 - ax1) * (by1 - ay1) - (ay2 - ay1) * (bx1 - ax1);
  352. G_debug(2, " d = %.18g", d);
  353. G_debug(2, " d1 = %.18g", d1);
  354. G_debug(2, " d2 = %.18g", d2);
  355. tola = tol / MAX(fabs(ax2 - ax1), fabs(ay2 - ay1));
  356. tolb = tol / MAX(fabs(bx2 - bx1), fabs(by2 - by1));
  357. G_debug(2, " tol = %.18g", tol);
  358. G_debug(2, " tola = %.18g", tola);
  359. G_debug(2, " tolb = %.18g", tolb);
  360. if (!FZERO(d, tol)) {
  361. ra = d1 / d;
  362. rb = d2 / d;
  363. G_debug(2, " not parallel/collinear: ra = %.18g", ra);
  364. G_debug(2, " rb = %.18g", rb);
  365. if ((ra <= -tola) || (ra >= 1 + tola) || (rb <= -tolb) ||
  366. (rb >= 1 + tolb)) {
  367. G_debug(2, " no intersection");
  368. return 0;
  369. }
  370. ra = MIN(MAX(ra, 0), 1);
  371. *x1 = ax1 + ra * (ax2 - ax1);
  372. *y1 = ay1 + ra * (ay2 - ay1);
  373. G_debug(2, " intersection %.18f, %.18f", *x1, *y1);
  374. return 1;
  375. }
  376. /* segments are parallel or collinear */
  377. G_debug(3, " -> parallel/collinear");
  378. if ((!FZERO(d1, tol)) || (!FZERO(d2, tol))) { /* lines are parallel */
  379. G_debug(2, " -> parallel");
  380. return 0;
  381. }
  382. /* segments are colinear. check for overlap */
  383. /* aa = adx*adx + ady*ady;
  384. bb = bdx*bdx + bdy*bdy;
  385. t = (ax1-bx1)*bdx + (ay1-by1)*bdy; */
  386. /* Collinear vertical */
  387. /* original code assumed lines were not both vertical
  388. * so there is a special case if they are */
  389. if (FEQUAL(ax1, ax2, tol) && FEQUAL(bx1, bx2, tol) &&
  390. FEQUAL(ax1, bx1, tol)) {
  391. G_debug(2, " -> collinear vertical");
  392. if (ay1 > ay2) {
  393. t = ay1;
  394. ay1 = ay2;
  395. ay2 = t;
  396. } /* to be sure that ay1 < ay2 */
  397. if (by1 > by2) {
  398. t = by1;
  399. by1 = by2;
  400. by2 = t;
  401. } /* to be sure that by1 < by2 */
  402. if (ay1 > by2 || ay2 < by1) {
  403. G_debug(2, " -> no intersection");
  404. return 0;
  405. }
  406. /* end points */
  407. if (FEQUAL(ay1, by2, tol)) {
  408. *x1 = ax1;
  409. *y1 = ay1;
  410. G_debug(2, " -> connected by end points");
  411. return 1; /* endpoints only */
  412. }
  413. if (FEQUAL(ay2, by1, tol)) {
  414. *x1 = ax2;
  415. *y1 = ay2;
  416. G_debug(2, " -> connected by end points");
  417. return 1; /* endpoints only */
  418. }
  419. /* general overlap */
  420. G_debug(3, " -> vertical overlap");
  421. /* a contains b */
  422. if (ay1 <= by1 && ay2 >= by2) {
  423. G_debug(2, " -> a contains b");
  424. *x1 = bx1;
  425. *y1 = by1;
  426. *x2 = bx2;
  427. *y2 = by2;
  428. if (!switched)
  429. return 3;
  430. else
  431. return 4;
  432. }
  433. /* b contains a */
  434. if (ay1 >= by1 && ay2 <= by2) {
  435. G_debug(2, " -> b contains a");
  436. *x1 = ax1;
  437. *y1 = ay1;
  438. *x2 = ax2;
  439. *y2 = ay2;
  440. if (!switched)
  441. return 4;
  442. else
  443. return 3;
  444. }
  445. /* general overlap, 2 intersection points */
  446. G_debug(2, " -> partial overlap");
  447. if (by1 > ay1 && by1 < ay2) { /* b1 in a */
  448. if (!switched) {
  449. *x1 = bx1;
  450. *y1 = by1;
  451. *x2 = ax2;
  452. *y2 = ay2;
  453. }
  454. else {
  455. *x1 = ax2;
  456. *y1 = ay2;
  457. *x2 = bx1;
  458. *y2 = by1;
  459. }
  460. return 2;
  461. }
  462. if (by2 > ay1 && by2 < ay2) { /* b2 in a */
  463. if (!switched) {
  464. *x1 = bx2;
  465. *y1 = by2;
  466. *x2 = ax1;
  467. *y2 = ay1;
  468. }
  469. else {
  470. *x1 = ax1;
  471. *y1 = ay1;
  472. *x2 = bx2;
  473. *y2 = by2;
  474. }
  475. return 2;
  476. }
  477. /* should not be reached */
  478. G_warning(("Vect_segment_intersection() ERROR (collinear vertical segments)"));
  479. G_warning("%.15g %.15g", ax1, ay1);
  480. G_warning("%.15g %.15g", ax2, ay2);
  481. G_warning("x");
  482. G_warning("%.15g %.15g", bx1, by1);
  483. G_warning("%.15g %.15g", bx2, by2);
  484. return 0;
  485. }
  486. G_debug(2, " -> collinear non vertical");
  487. /* Collinear non vertical */
  488. if ((bx1 > ax1 && bx2 > ax1 && bx1 > ax2 && bx2 > ax2) ||
  489. (bx1 < ax1 && bx2 < ax1 && bx1 < ax2 && bx2 < ax2)) {
  490. G_debug(2, " -> no intersection");
  491. return 0;
  492. }
  493. /* there is overlap or connected end points */
  494. G_debug(2, " -> overlap/connected end points");
  495. /* end points */
  496. if ((ax1 == bx1 && ay1 == by1) || (ax1 == bx2 && ay1 == by2)) {
  497. *x1 = ax1;
  498. *y1 = ay1;
  499. G_debug(2, " -> connected by end points");
  500. return 1;
  501. }
  502. if ((ax2 == bx1 && ay2 == by1) || (ax2 == bx2 && ay2 == by2)) {
  503. *x1 = ax2;
  504. *y1 = ay2;
  505. G_debug(2, " -> connected by end points");
  506. return 1;
  507. }
  508. if (ax1 > ax2) {
  509. t = ax1;
  510. ax1 = ax2;
  511. ax2 = t;
  512. t = ay1;
  513. ay1 = ay2;
  514. ay2 = t;
  515. } /* to be sure that ax1 < ax2 */
  516. if (bx1 > bx2) {
  517. t = bx1;
  518. bx1 = bx2;
  519. bx2 = t;
  520. t = by1;
  521. by1 = by2;
  522. by2 = t;
  523. } /* to be sure that bx1 < bx2 */
  524. /* a contains b */
  525. if (ax1 <= bx1 && ax2 >= bx2) {
  526. G_debug(2, " -> a contains b");
  527. *x1 = bx1;
  528. *y1 = by1;
  529. *x2 = bx2;
  530. *y2 = by2;
  531. if (!switched)
  532. return 3;
  533. else
  534. return 4;
  535. }
  536. /* b contains a */
  537. if (ax1 >= bx1 && ax2 <= bx2) {
  538. G_debug(2, " -> b contains a");
  539. *x1 = ax1;
  540. *y1 = ay1;
  541. *x2 = ax2;
  542. *y2 = ay2;
  543. if (!switched)
  544. return 4;
  545. else
  546. return 3;
  547. }
  548. /* general overlap, 2 intersection points (lines are not vertical) */
  549. G_debug(2, " -> partial overlap");
  550. if (bx1 > ax1 && bx1 < ax2) { /* b1 is in a */
  551. if (!switched) {
  552. *x1 = bx1;
  553. *y1 = by1;
  554. *x2 = ax2;
  555. *y2 = ay2;
  556. }
  557. else {
  558. *x1 = ax2;
  559. *y1 = ay2;
  560. *x2 = bx1;
  561. *y2 = by1;
  562. }
  563. return 2;
  564. }
  565. if (bx2 > ax1 && bx2 < ax2) { /* b2 is in a */
  566. if (!switched) {
  567. *x1 = bx2;
  568. *y1 = by2;
  569. *x2 = ax1;
  570. *y2 = ay1;
  571. }
  572. else {
  573. *x1 = ax1;
  574. *y1 = ay1;
  575. *x2 = bx2;
  576. *y2 = by2;
  577. }
  578. return 2;
  579. }
  580. /* should not be reached */
  581. G_warning(("segment_intersection_2d() ERROR (collinear non vertical segments)"));
  582. G_warning("%.15g %.15g", ax1, ay1);
  583. G_warning("%.15g %.15g", ax2, ay2);
  584. G_warning("x");
  585. G_warning("%.15g %.15g", bx1, by1);
  586. G_warning("%.15g %.15g", bx2, by2);
  587. return 0;
  588. }
  589. int segment_intersection_2d(double ax1, double ay1, double ax2, double ay2,
  590. double bx1, double by1, double bx2, double by2,
  591. double *x1, double *y1, double *x2, double *y2)
  592. {
  593. const int DLEVEL = 4;
  594. double t;
  595. int vertical;
  596. int f11, f12, f21, f22;
  597. double d, da, db;
  598. /* TODO: Works for points ? */
  599. G_debug(DLEVEL, "segment_intersection_2d()");
  600. G_debug(4, " ax1 = %.18f, ay1 = %.18f", ax1, ay1);
  601. G_debug(4, " ax2 = %.18f, ay2 = %.18f", ax2, ay2);
  602. G_debug(4, " bx1 = %.18f, by1 = %.18f", bx1, by1);
  603. G_debug(4, " bx2 = %.18f, by2 = %.18f", bx2, by2);
  604. f11 = ((ax1 == bx1) && (ay1 == by1));
  605. f12 = ((ax1 == bx2) && (ay1 == by2));
  606. f21 = ((ax2 == bx1) && (ay2 == by1));
  607. f22 = ((ax2 == bx2) && (ay2 == by2));
  608. /* Check for identical segments */
  609. if ((f11 && f22) || (f12 && f21)) {
  610. G_debug(DLEVEL, " identical segments");
  611. *x1 = ax1;
  612. *y1 = ay1;
  613. *x2 = ax2;
  614. *y2 = ay2;
  615. return 5;
  616. }
  617. /* Check for identical endpoints */
  618. if (f11 || f12) {
  619. G_debug(DLEVEL, " connected by endpoints");
  620. *x1 = ax1;
  621. *y1 = ay1;
  622. return 1;
  623. }
  624. if (f21 || f22) {
  625. G_debug(DLEVEL, " connected by endpoints");
  626. *x1 = ax2;
  627. *y1 = ay2;
  628. return 1;
  629. }
  630. if ((MAX(ax1, ax2) < MIN(bx1, bx2)) || (MAX(bx1, bx2) < MIN(ax1, ax2))) {
  631. G_debug(DLEVEL, " no intersection (disjoint bounding boxes)");
  632. return 0;
  633. }
  634. if ((MAX(ay1, ay2) < MIN(by1, by2)) || (MAX(by1, by2) < MIN(ay1, ay2))) {
  635. G_debug(DLEVEL, " no intersection (disjoint bounding boxes)");
  636. return 0;
  637. }
  638. d = D;
  639. if (d != 0) {
  640. G_debug(DLEVEL, " general position");
  641. da = DA;
  642. /*mpf_div(rra, dda, dd);
  643. mpf_div(rrb, ddb, dd);
  644. s = mpf_get_str(NULL, &exp, 10, 40, rra);
  645. G_debug(4, " ra = %sE%d", (s[0]==0)?"0":s, exp);
  646. s = mpf_get_str(NULL, &exp, 10, 24, rrb);
  647. G_debug(4, " rb = %sE%d", (s[0]==0)?"0":s, exp);
  648. */
  649. if (d > 0) {
  650. if ((da < 0) || (da > d)) {
  651. G_debug(DLEVEL, " no intersection");
  652. return 0;
  653. }
  654. db = DB;
  655. if ((db < 0) || (db > d)) {
  656. G_debug(DLEVEL, " no intersection");
  657. return 0;
  658. }
  659. }
  660. else { /* if d < 0 */
  661. if ((da > 0) || (da < d)) {
  662. G_debug(DLEVEL, " no intersection");
  663. return 0;
  664. }
  665. db = DB;
  666. if ((db > 0) || (db < d)) {
  667. G_debug(DLEVEL, " no intersection");
  668. return 0;
  669. }
  670. }
  671. /*G_debug(DLEVEL, " ra=%.17g rb=%.17g", mpf_get_d(dda)/mpf_get_d(dd), mpf_get_d(ddb)/mpf_get_d(dd)); */
  672. /*G_debug(DLEVEL, " sgn_d=%d sgn_da=%d sgn_db=%d cmp(dda,dd)=%d cmp(ddb,dd)=%d", sgn_d, sgn_da, sgn_db, mpf_cmp(dda, dd), mpf_cmp(ddb, dd)); */
  673. *x1 = ax1 + (ax2 - ax1) * da / d;
  674. *y1 = ay1 + (ay2 - ay1) * da / d;
  675. G_debug(DLEVEL, " intersection %.16g, %.16g", *x1, *y1);
  676. return 1;
  677. }
  678. /* segments are parallel or collinear */
  679. da = DA;
  680. db = DB;
  681. if ((da != 0) || (db != 0)) {
  682. /* segments are parallel */
  683. G_debug(DLEVEL, " parallel segments");
  684. return 0;
  685. }
  686. /* segments are colinear. check for overlap */
  687. /* swap endpoints if needed */
  688. /* if segments are vertical, we swap x-coords with y-coords */
  689. vertical = 0;
  690. if (ax1 > ax2) {
  691. SWAP(ax1, ax2);
  692. SWAP(ay1, ay2);
  693. }
  694. else if (ax1 == ax2) {
  695. vertical = 1;
  696. if (ay1 > ay2)
  697. SWAP(ay1, ay2);
  698. SWAP(ax1, ay1);
  699. SWAP(ax2, ay2);
  700. }
  701. if (bx1 > bx2) {
  702. SWAP(bx1, bx2);
  703. SWAP(by1, by2);
  704. }
  705. else if (bx1 == bx2) {
  706. if (by1 > by2)
  707. SWAP(by1, by2);
  708. SWAP(bx1, by1);
  709. SWAP(bx2, by2);
  710. }
  711. G_debug(DLEVEL, " collinear segments");
  712. if ((bx2 < ax1) || (bx1 > ax2)) {
  713. G_debug(DLEVEL, " no intersection");
  714. return 0;
  715. }
  716. /* there is overlap or connected end points */
  717. G_debug(DLEVEL, " overlap");
  718. /* a contains b */
  719. if ((ax1 < bx1) && (ax2 > bx2)) {
  720. G_debug(DLEVEL, " a contains b");
  721. if (!vertical) {
  722. *x1 = bx1;
  723. *y1 = by1;
  724. *x2 = bx2;
  725. *y2 = by2;
  726. }
  727. else {
  728. *x1 = by1;
  729. *y1 = bx1;
  730. *x2 = by2;
  731. *y2 = bx2;
  732. }
  733. return 3;
  734. }
  735. /* b contains a */
  736. if ((ax1 > bx1) && (ax2 < bx2)) {
  737. G_debug(DLEVEL, " b contains a");
  738. if (!vertical) {
  739. *x1 = bx1;
  740. *y1 = by1;
  741. *x2 = bx2;
  742. *y2 = by2;
  743. }
  744. else {
  745. *x1 = by1;
  746. *y1 = bx1;
  747. *x2 = by2;
  748. *y2 = bx2;
  749. }
  750. return 4;
  751. }
  752. /* general overlap, 2 intersection points */
  753. G_debug(DLEVEL, " partial overlap");
  754. if ((bx1 > ax1) && (bx1 < ax2)) { /* b1 is in a */
  755. if (!vertical) {
  756. *x1 = bx1;
  757. *y1 = by1;
  758. *x2 = ax2;
  759. *y2 = ay2;
  760. }
  761. else {
  762. *x1 = by1;
  763. *y1 = bx1;
  764. *x2 = ay2;
  765. *y2 = ax2;
  766. }
  767. return 2;
  768. }
  769. if ((bx2 > ax1) && (bx2 < ax2)) { /* b2 is in a */
  770. if (!vertical) {
  771. *x1 = bx2;
  772. *y1 = by2;
  773. *x2 = ax1;
  774. *y2 = ay1;
  775. }
  776. else {
  777. *x1 = by2;
  778. *y1 = bx2;
  779. *x2 = ay1;
  780. *y2 = ax1;
  781. }
  782. return 2;
  783. }
  784. /* should not be reached */
  785. G_warning(("segment_intersection_2d() ERROR (should not be reached)"));
  786. G_warning("%.16g %.16g", ax1, ay1);
  787. G_warning("%.16g %.16g", ax2, ay2);
  788. G_warning("x");
  789. G_warning("%.16g %.16g", bx1, by1);
  790. G_warning("%.16g %.16g", bx2, by2);
  791. return 0;
  792. }
  793. #define N 52 /* double's mantisa size in bits */
  794. /* a and b are different in at most <bits> significant digits */
  795. int almost_equal(double a, double b, int bits)
  796. {
  797. int ea, eb, e;
  798. if (a == b)
  799. return 1;
  800. if (a == 0 || b == 0) {
  801. /* return (0 < -N+bits); */
  802. return (bits > N);
  803. }
  804. frexp(a, &ea);
  805. frexp(b, &eb);
  806. if (ea != eb)
  807. return (bits > N + abs(ea - eb));
  808. frexp(a - b, &e);
  809. return (e < ea - N + bits);
  810. }
  811. #ifdef ASDASDFASFEAS
  812. int segment_intersection_2d_test(double ax1, double ay1, double ax2,
  813. double ay2, double bx1, double by1,
  814. double bx2, double by2, double *x1,
  815. double *y1, double *x2, double *y2)
  816. {
  817. double t;
  818. double max_ax, min_ax, max_ay, min_ay;
  819. double max_bx, min_bx, max_by, min_by;
  820. int sgn_d, sgn_da, sgn_db;
  821. int vertical;
  822. int f11, f12, f21, f22;
  823. mp_exp_t exp;
  824. char *s;
  825. double d, da, db, ra, rb;
  826. if (!initialized)
  827. initialize_mpf_vars();
  828. /* TODO: Works for points ? */
  829. G_debug(3, "segment_intersection_2d_test()");
  830. G_debug(3, " ax1 = %.18e, ay1 = %.18e", ax1, ay1);
  831. G_debug(3, " ax2 = %.18e, ay2 = %.18e", ax2, ay2);
  832. G_debug(3, " bx1 = %.18e, by1 = %.18e", bx1, by1);
  833. G_debug(3, " bx2 = %.18e, by2 = %.18e", bx2, by2);
  834. f11 = ((ax1 == bx1) && (ay1 == by1));
  835. f12 = ((ax1 == bx2) && (ay1 == by2));
  836. f21 = ((ax2 == bx1) && (ay2 == by1));
  837. f22 = ((ax2 == bx2) && (ay2 == by2));
  838. /* Check for identical segments */
  839. if ((f11 && f22) || (f12 && f21)) {
  840. G_debug(4, " identical segments");
  841. *x1 = ax1;
  842. *y1 = ay1;
  843. *x2 = ax2;
  844. *y2 = ay2;
  845. return 5;
  846. }
  847. /* Check for identical endpoints */
  848. if (f11 || f12) {
  849. G_debug(4, " connected by endpoints");
  850. *x1 = ax1;
  851. *y1 = ay1;
  852. return 1;
  853. }
  854. if (f21 || f22) {
  855. G_debug(4, " connected by endpoints");
  856. *x1 = ax2;
  857. *y1 = ay2;
  858. return 1;
  859. }
  860. if ((MAX(ax1, ax2) < MIN(bx1, bx2)) || (MAX(bx1, bx2) < MIN(ax1, ax2))) {
  861. G_debug(4, " no intersection (disjoint bounding boxes)");
  862. return 0;
  863. }
  864. if ((MAX(ay1, ay2) < MIN(by1, by2)) || (MAX(by1, by2) < MIN(ay1, ay2))) {
  865. G_debug(4, " no intersection (disjoint bounding boxes)");
  866. return 0;
  867. }
  868. d = (ax2 - ax1) * (by1 - by2) - (ay2 - ay1) * (bx1 - bx2);
  869. da = (bx1 - ax1) * (by1 - by2) - (by1 - ay1) * (bx1 - bx2);
  870. db = (ax2 - ax1) * (by1 - ay1) - (ay2 - ay1) * (bx1 - ax1);
  871. det22(dd, ax2, ax1, bx1, bx2, ay2, ay1, by1, by2);
  872. sgn_d = mpf_sgn(dd);
  873. s = mpf_get_str(NULL, &exp, 10, 40, dd);
  874. G_debug(3, " dd = %sE%d", (s[0] == 0) ? "0" : s, exp);
  875. G_debug(3, " d = %.18E", d);
  876. if (sgn_d != 0) {
  877. G_debug(3, " general position");
  878. det22(dda, bx1, ax1, bx1, bx2, by1, ay1, by1, by2);
  879. det22(ddb, ax2, ax1, bx1, ax1, ay2, ay1, by1, ay1);
  880. sgn_da = mpf_sgn(dda);
  881. sgn_db = mpf_sgn(ddb);
  882. ra = da / d;
  883. rb = db / d;
  884. mpf_div(rra, dda, dd);
  885. mpf_div(rrb, ddb, dd);
  886. s = mpf_get_str(NULL, &exp, 10, 40, rra);
  887. G_debug(4, " rra = %sE%d", (s[0] == 0) ? "0" : s, exp);
  888. G_debug(4, " ra = %.18E", ra);
  889. s = mpf_get_str(NULL, &exp, 10, 40, rrb);
  890. G_debug(4, " rrb = %sE%d", (s[0] == 0) ? "0" : s, exp);
  891. G_debug(4, " rb = %.18E", rb);
  892. if (sgn_d > 0) {
  893. if ((sgn_da < 0) || (mpf_cmp(dda, dd) > 0)) {
  894. G_debug(DLEVEL, " no intersection");
  895. return 0;
  896. }
  897. if ((sgn_db < 0) || (mpf_cmp(ddb, dd) > 0)) {
  898. G_debug(DLEVEL, " no intersection");
  899. return 0;
  900. }
  901. }
  902. else { /* if sgn_d < 0 */
  903. if ((sgn_da > 0) || (mpf_cmp(dda, dd) < 0)) {
  904. G_debug(DLEVEL, " no intersection");
  905. return 0;
  906. }
  907. if ((sgn_db > 0) || (mpf_cmp(ddb, dd) < 0)) {
  908. G_debug(DLEVEL, " no intersection");
  909. return 0;
  910. }
  911. }
  912. mpf_set_d(delta, ax2 - ax1);
  913. mpf_mul(t1, dda, delta);
  914. mpf_div(t2, t1, dd);
  915. *x1 = ax1 + mpf_get_d(t2);
  916. mpf_set_d(delta, ay2 - ay1);
  917. mpf_mul(t1, dda, delta);
  918. mpf_div(t2, t1, dd);
  919. *y1 = ay1 + mpf_get_d(t2);
  920. G_debug(2, " intersection at:");
  921. G_debug(2, " xx = %.18e", *x1);
  922. G_debug(2, " x = %.18e", ax1 + ra * (ax2 - ax1));
  923. G_debug(2, " yy = %.18e", *y1);
  924. G_debug(2, " y = %.18e", ay1 + ra * (ay2 - ay1));
  925. return 1;
  926. }
  927. G_debug(3, " parallel/collinear...");
  928. return -1;
  929. }
  930. #endif