route.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #include <assert.h>
  11. #include <limits.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <math.h>
  15. #include <pathplan/pathutil.h>
  16. #include <pathplan/solvers.h>
  17. #define EPSILON1 1E-3
  18. #define EPSILON2 1E-6
  19. typedef struct tna_t {
  20. double t;
  21. Ppoint_t a[2];
  22. } tna_t;
  23. #define DISTSQ(a, b) ( \
  24. (((a).x - (b).x) * ((a).x - (b).x)) + (((a).y - (b).y) * ((a).y - (b).y)) \
  25. )
  26. #define POINTSIZE sizeof (Ppoint_t)
  27. static Ppoint_t *ops;
  28. static size_t opn, opl;
  29. static int reallyroutespline(Pedge_t *, size_t,
  30. Ppoint_t *, int, Ppoint_t, Ppoint_t);
  31. static int mkspline(Ppoint_t *, int, tna_t *, Ppoint_t, Ppoint_t,
  32. Ppoint_t *, Ppoint_t *, Ppoint_t *, Ppoint_t *);
  33. static int splinefits(Pedge_t *, size_t, Ppoint_t, Pvector_t, Ppoint_t,
  34. Pvector_t, Ppoint_t *, int);
  35. static int splineisinside(Pedge_t *, size_t, Ppoint_t *);
  36. static int splineintersectsline(Ppoint_t *, Ppoint_t *, double *);
  37. static void points2coeff(double, double, double, double, double *);
  38. static void addroot(double, double *, int *);
  39. static Pvector_t normv(Pvector_t);
  40. static int growops(size_t);
  41. static Ppoint_t add(Ppoint_t, Ppoint_t);
  42. static Ppoint_t sub(Ppoint_t, Ppoint_t);
  43. static double dist(Ppoint_t, Ppoint_t);
  44. static Ppoint_t scale(Ppoint_t, double);
  45. static double dot(Ppoint_t, Ppoint_t);
  46. static double B0(double t);
  47. static double B1(double t);
  48. static double B2(double t);
  49. static double B3(double t);
  50. static double B01(double t);
  51. static double B23(double t);
  52. /* Proutespline:
  53. * Given a set of barrier line segments edges as obstacles, a template
  54. * path input_route, and endpoint vectors endpoint_slopes, construct a spline
  55. * fitting the input and endpoint vectors, and return in output_route.
  56. * Return 0 on success and -1 on failure, including no memory.
  57. */
  58. int Proutespline(Pedge_t *barriers, size_t n_barriers, Ppolyline_t input_route,
  59. Ppoint_t endpoint_slopes[2], Ppolyline_t *output_route) {
  60. Ppoint_t *inps;
  61. int inpn;
  62. /* unpack into previous format rather than modify legacy code */
  63. inps = input_route.ps;
  64. assert(input_route.pn <= INT_MAX);
  65. inpn = (int)input_route.pn;
  66. /* generate the splines */
  67. endpoint_slopes[0] = normv(endpoint_slopes[0]);
  68. endpoint_slopes[1] = normv(endpoint_slopes[1]);
  69. opl = 0;
  70. if (growops(4) < 0) {
  71. return -1;
  72. }
  73. ops[opl++] = inps[0];
  74. if (reallyroutespline(barriers, n_barriers, inps, inpn, endpoint_slopes[0],
  75. endpoint_slopes[1]) == -1)
  76. return -1;
  77. output_route->pn = opl;
  78. output_route->ps = ops;
  79. return 0;
  80. }
  81. static int reallyroutespline(Pedge_t *edges, size_t edgen, Ppoint_t *inps,
  82. int inpn, Ppoint_t ev0, Ppoint_t ev1) {
  83. Ppoint_t p1, p2, cp1, cp2, p;
  84. Pvector_t v1, v2, splitv, splitv1, splitv2;
  85. double maxd, d, t;
  86. int maxi, i, spliti;
  87. static tna_t *tnas;
  88. static int tnan;
  89. if (tnan < inpn) {
  90. tna_t *new_tnas = realloc(tnas, sizeof(tna_t) * (size_t)inpn);
  91. if (new_tnas == NULL)
  92. return -1;
  93. tnas = new_tnas;
  94. tnan = inpn;
  95. }
  96. tnas[0].t = 0;
  97. for (i = 1; i < inpn; i++)
  98. tnas[i].t = tnas[i - 1].t + dist(inps[i], inps[i - 1]);
  99. for (i = 1; i < inpn; i++)
  100. tnas[i].t /= tnas[inpn - 1].t;
  101. for (i = 0; i < inpn; i++) {
  102. tnas[i].a[0] = scale(ev0, B1(tnas[i].t));
  103. tnas[i].a[1] = scale(ev1, B2(tnas[i].t));
  104. }
  105. if (mkspline(inps, inpn, tnas, ev0, ev1, &p1, &v1, &p2, &v2) == -1)
  106. return -1;
  107. int fit = splinefits(edges, edgen, p1, v1, p2, v2, inps, inpn);
  108. if (fit > 0) {
  109. return 0;
  110. }
  111. if (fit < 0) {
  112. return -1;
  113. }
  114. cp1 = add(p1, scale(v1, 1 / 3.0));
  115. cp2 = sub(p2, scale(v2, 1 / 3.0));
  116. for (maxd = -1, maxi = -1, i = 1; i < inpn - 1; i++) {
  117. t = tnas[i].t;
  118. p.x = B0(t) * p1.x + B1(t) * cp1.x + B2(t) * cp2.x + B3(t) * p2.x;
  119. p.y = B0(t) * p1.y + B1(t) * cp1.y + B2(t) * cp2.y + B3(t) * p2.y;
  120. if ((d = dist(p, inps[i])) > maxd)
  121. maxd = d, maxi = i;
  122. }
  123. spliti = maxi;
  124. splitv1 = normv(sub(inps[spliti], inps[spliti - 1]));
  125. splitv2 = normv(sub(inps[spliti + 1], inps[spliti]));
  126. splitv = normv(add(splitv1, splitv2));
  127. if (reallyroutespline(edges, edgen, inps, spliti + 1, ev0, splitv) < 0) {
  128. return -1;
  129. }
  130. if (reallyroutespline(edges, edgen, &inps[spliti], inpn - spliti, splitv,
  131. ev1) < 0) {
  132. return -1;
  133. }
  134. return 0;
  135. }
  136. static int mkspline(Ppoint_t * inps, int inpn, tna_t * tnas, Ppoint_t ev0,
  137. Ppoint_t ev1, Ppoint_t * sp0, Ppoint_t * sv0,
  138. Ppoint_t * sp1, Ppoint_t * sv1)
  139. {
  140. Ppoint_t tmp;
  141. double c[2][2], x[2], det01, det0X, detX1;
  142. double d01, scale0, scale3;
  143. int i;
  144. scale0 = scale3 = 0.0;
  145. c[0][0] = c[0][1] = c[1][0] = c[1][1] = 0.0;
  146. x[0] = x[1] = 0.0;
  147. for (i = 0; i < inpn; i++) {
  148. c[0][0] += dot(tnas[i].a[0], tnas[i].a[0]);
  149. c[0][1] += dot(tnas[i].a[0], tnas[i].a[1]);
  150. c[1][0] = c[0][1];
  151. c[1][1] += dot(tnas[i].a[1], tnas[i].a[1]);
  152. tmp = sub(inps[i], add(scale(inps[0], B01(tnas[i].t)),
  153. scale(inps[inpn - 1], B23(tnas[i].t))));
  154. x[0] += dot(tnas[i].a[0], tmp);
  155. x[1] += dot(tnas[i].a[1], tmp);
  156. }
  157. det01 = c[0][0] * c[1][1] - c[1][0] * c[0][1];
  158. det0X = c[0][0] * x[1] - c[0][1] * x[0];
  159. detX1 = x[0] * c[1][1] - x[1] * c[0][1];
  160. if (fabs(det01) >= 1e-6) {
  161. scale0 = detX1 / det01;
  162. scale3 = det0X / det01;
  163. }
  164. if (fabs(det01) < 1e-6 || scale0 <= 0.0 || scale3 <= 0.0) {
  165. d01 = dist(inps[0], inps[inpn - 1]) / 3.0;
  166. scale0 = d01;
  167. scale3 = d01;
  168. }
  169. *sp0 = inps[0];
  170. *sv0 = scale(ev0, scale0);
  171. *sp1 = inps[inpn - 1];
  172. *sv1 = scale(ev1, scale3);
  173. return 0;
  174. }
  175. static double dist_n(Ppoint_t * p, int n)
  176. {
  177. int i;
  178. double rv;
  179. rv = 0.0;
  180. for (i = 1; i < n; i++) {
  181. rv += hypot(p[i].x - p[i - 1].x, p[i].y - p[i - 1].y);
  182. }
  183. return rv;
  184. }
  185. static int splinefits(Pedge_t *edges, size_t edgen, Ppoint_t pa, Pvector_t va,
  186. Ppoint_t pb, Pvector_t vb, Ppoint_t *inps, int inpn) {
  187. Ppoint_t sps[4];
  188. double a;
  189. int pi;
  190. int forceflag;
  191. int first = 1;
  192. forceflag = (inpn == 2 ? 1 : 0);
  193. a = 4;
  194. for (;;) {
  195. sps[0].x = pa.x;
  196. sps[0].y = pa.y;
  197. sps[1].x = pa.x + a * va.x / 3.0;
  198. sps[1].y = pa.y + a * va.y / 3.0;
  199. sps[2].x = pb.x - a * vb.x / 3.0;
  200. sps[2].y = pb.y - a * vb.y / 3.0;
  201. sps[3].x = pb.x;
  202. sps[3].y = pb.y;
  203. /* shortcuts (paths shorter than the shortest path) not allowed -
  204. * they must be outside the constraint polygon. this can happen
  205. * if the candidate spline intersects the constraint polygon exactly
  206. * on sides or vertices. maybe this could be more elegant, but
  207. * it solves the immediate problem. we could also try jittering the
  208. * constraint polygon, or computing the candidate spline more carefully,
  209. * for example using the path. SCN */
  210. if (first && (dist_n(sps, 4) < (dist_n(inps, inpn) - EPSILON1)))
  211. return 0;
  212. first = 0;
  213. if (splineisinside(edges, edgen, &sps[0])) {
  214. if (growops(opl + 4) < 0) {
  215. return -1;
  216. }
  217. for (pi = 1; pi < 4; pi++)
  218. ops[opl].x = sps[pi].x, ops[opl++].y = sps[pi].y;
  219. #if defined(DEBUG) && DEBUG >= 1
  220. fprintf(stderr, "success: %f %f\n", a, a);
  221. #endif
  222. return 1;
  223. }
  224. // is `a` 0, accounting for the precision with which it was computed (on the
  225. // last loop iteration) below?
  226. if (a < 0.005) {
  227. if (forceflag) {
  228. if (growops(opl + 4) < 0) {
  229. return -1;
  230. }
  231. for (pi = 1; pi < 4; pi++)
  232. ops[opl].x = sps[pi].x, ops[opl++].y = sps[pi].y;
  233. #if defined(DEBUG) && DEBUG >= 1
  234. fprintf(stderr, "forced straight line: %f %f\n", a, a);
  235. #endif
  236. return 1;
  237. }
  238. break;
  239. }
  240. if (a > .01)
  241. a /= 2;
  242. else
  243. a = 0;
  244. }
  245. #if defined(DEBUG) && DEBUG >= 1
  246. fprintf(stderr, "failure\n");
  247. #endif
  248. return 0;
  249. }
  250. static int splineisinside(Pedge_t *edges, size_t edgen, Ppoint_t *sps) {
  251. double roots[4];
  252. int rooti, rootn;
  253. Ppoint_t lps[2], ip;
  254. double t, ta, tb, tc, td;
  255. for (size_t ei = 0; ei < edgen; ei++) {
  256. lps[0] = edges[ei].a, lps[1] = edges[ei].b;
  257. if ((rootn = splineintersectsline(sps, lps, roots)) == 4)
  258. continue;
  259. for (rooti = 0; rooti < rootn; rooti++) {
  260. if (roots[rooti] < EPSILON2 || roots[rooti] > 1 - EPSILON2)
  261. continue;
  262. t = roots[rooti];
  263. td = t * t * t;
  264. tc = 3 * t * t * (1 - t);
  265. tb = 3 * t * (1 - t) * (1 - t);
  266. ta = (1 - t) * (1 - t) * (1 - t);
  267. ip.x = ta * sps[0].x + tb * sps[1].x +
  268. tc * sps[2].x + td * sps[3].x;
  269. ip.y = ta * sps[0].y + tb * sps[1].y +
  270. tc * sps[2].y + td * sps[3].y;
  271. if (DISTSQ(ip, lps[0]) < EPSILON1 ||
  272. DISTSQ(ip, lps[1]) < EPSILON1)
  273. continue;
  274. return 0;
  275. }
  276. }
  277. return 1;
  278. }
  279. static int splineintersectsline(Ppoint_t * sps, Ppoint_t * lps,
  280. double *roots)
  281. {
  282. double scoeff[4], xcoeff[2], ycoeff[2];
  283. double xroots[3], yroots[3], tv, sv, rat;
  284. int rootn, xrootn, yrootn, i, j;
  285. xcoeff[0] = lps[0].x;
  286. xcoeff[1] = lps[1].x - lps[0].x;
  287. ycoeff[0] = lps[0].y;
  288. ycoeff[1] = lps[1].y - lps[0].y;
  289. rootn = 0;
  290. if (xcoeff[1] == 0) {
  291. if (ycoeff[1] == 0) {
  292. points2coeff(sps[0].x, sps[1].x, sps[2].x, sps[3].x, scoeff);
  293. scoeff[0] -= xcoeff[0];
  294. xrootn = solve3(scoeff, xroots);
  295. points2coeff(sps[0].y, sps[1].y, sps[2].y, sps[3].y, scoeff);
  296. scoeff[0] -= ycoeff[0];
  297. yrootn = solve3(scoeff, yroots);
  298. if (xrootn == 4)
  299. if (yrootn == 4)
  300. return 4;
  301. else
  302. for (j = 0; j < yrootn; j++)
  303. addroot(yroots[j], roots, &rootn);
  304. else if (yrootn == 4)
  305. for (i = 0; i < xrootn; i++)
  306. addroot(xroots[i], roots, &rootn);
  307. else
  308. for (i = 0; i < xrootn; i++)
  309. for (j = 0; j < yrootn; j++)
  310. if (xroots[i] == yroots[j])
  311. addroot(xroots[i], roots, &rootn);
  312. return rootn;
  313. } else {
  314. points2coeff(sps[0].x, sps[1].x, sps[2].x, sps[3].x, scoeff);
  315. scoeff[0] -= xcoeff[0];
  316. xrootn = solve3(scoeff, xroots);
  317. if (xrootn == 4)
  318. return 4;
  319. for (i = 0; i < xrootn; i++) {
  320. tv = xroots[i];
  321. if (tv >= 0 && tv <= 1) {
  322. points2coeff(sps[0].y, sps[1].y, sps[2].y, sps[3].y,
  323. scoeff);
  324. sv = scoeff[0] + tv * (scoeff[1] + tv *
  325. (scoeff[2] + tv * scoeff[3]));
  326. sv = (sv - ycoeff[0]) / ycoeff[1];
  327. if ((0 <= sv) && (sv <= 1))
  328. addroot(tv, roots, &rootn);
  329. }
  330. }
  331. return rootn;
  332. }
  333. } else {
  334. rat = ycoeff[1] / xcoeff[1];
  335. points2coeff(sps[0].y - rat * sps[0].x, sps[1].y - rat * sps[1].x,
  336. sps[2].y - rat * sps[2].x, sps[3].y - rat * sps[3].x,
  337. scoeff);
  338. scoeff[0] += rat * xcoeff[0] - ycoeff[0];
  339. xrootn = solve3(scoeff, xroots);
  340. if (xrootn == 4)
  341. return 4;
  342. for (i = 0; i < xrootn; i++) {
  343. tv = xroots[i];
  344. if (tv >= 0 && tv <= 1) {
  345. points2coeff(sps[0].x, sps[1].x, sps[2].x, sps[3].x,
  346. scoeff);
  347. sv = scoeff[0] + tv * (scoeff[1] +
  348. tv * (scoeff[2] + tv * scoeff[3]));
  349. sv = (sv - xcoeff[0]) / xcoeff[1];
  350. if ((0 <= sv) && (sv <= 1))
  351. addroot(tv, roots, &rootn);
  352. }
  353. }
  354. return rootn;
  355. }
  356. }
  357. static void points2coeff(double v0, double v1, double v2, double v3,
  358. double *coeff)
  359. {
  360. coeff[3] = v3 + 3 * v1 - (v0 + 3 * v2);
  361. coeff[2] = 3 * v0 + 3 * v2 - 6 * v1;
  362. coeff[1] = 3 * (v1 - v0);
  363. coeff[0] = v0;
  364. }
  365. static void addroot(double root, double *roots, int *rootnp)
  366. {
  367. if (root >= 0 && root <= 1)
  368. roots[*rootnp] = root, (*rootnp)++;
  369. }
  370. static Pvector_t normv(Pvector_t v)
  371. {
  372. double d;
  373. d = v.x * v.x + v.y * v.y;
  374. if (d > 1e-6) {
  375. d = sqrt(d);
  376. v.x /= d, v.y /= d;
  377. }
  378. return v;
  379. }
  380. static int growops(size_t newopn) {
  381. if (newopn <= opn)
  382. return 0;
  383. if (!(ops = realloc(ops, POINTSIZE * newopn))) {
  384. return -1;
  385. }
  386. opn = newopn;
  387. return 0;
  388. }
  389. static Ppoint_t add(Ppoint_t p1, Ppoint_t p2)
  390. {
  391. p1.x += p2.x, p1.y += p2.y;
  392. return p1;
  393. }
  394. static Ppoint_t sub(Ppoint_t p1, Ppoint_t p2)
  395. {
  396. p1.x -= p2.x, p1.y -= p2.y;
  397. return p1;
  398. }
  399. static double dist(Ppoint_t p1, Ppoint_t p2)
  400. {
  401. double dx, dy;
  402. dx = p2.x - p1.x, dy = p2.y - p1.y;
  403. return hypot(dx, dy);
  404. }
  405. static Ppoint_t scale(Ppoint_t p, double c)
  406. {
  407. p.x *= c, p.y *= c;
  408. return p;
  409. }
  410. static double dot(Ppoint_t p1, Ppoint_t p2)
  411. {
  412. return p1.x * p2.x + p1.y * p2.y;
  413. }
  414. static double B0(double t)
  415. {
  416. double tmp = 1.0 - t;
  417. return tmp * tmp * tmp;
  418. }
  419. static double B1(double t)
  420. {
  421. double tmp = 1.0 - t;
  422. return 3 * t * tmp * tmp;
  423. }
  424. static double B2(double t)
  425. {
  426. double tmp = 1.0 - t;
  427. return 3 * t * t * tmp;
  428. }
  429. static double B3(double t)
  430. {
  431. return t * t * t;
  432. }
  433. static double B01(double t)
  434. {
  435. double tmp = 1.0 - t;
  436. return tmp * tmp * (tmp + 3 * t);
  437. }
  438. static double B23(double t)
  439. {
  440. double tmp = 1.0 - t;
  441. return t * t * (3 * tmp + t);
  442. }