vector.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. #define _ISOC99_SOURCE /* to get isfinite() */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <math.h>
  6. #include <grass/gis.h>
  7. #include "list.h"
  8. #include "mapcalc.h"
  9. #include "vector.h"
  10. typedef struct Vecfunc
  11. {
  12. char *name;
  13. void *func;
  14. char *proto;
  15. } VECFUNC;
  16. static VECFUNC vf[] = {
  17. {"v_copy", v_copy, "p=rp"},
  18. {"v_add", v_add, "p=rpp"},
  19. {"pnt_op_func_+", v_add, "p=rpp"},
  20. {"v_sub", v_sub, "p=rpp"},
  21. {"pnt_op_func_-", v_sub, "p=rpp"},
  22. {"v_abs", v_abs, "p=rp"},
  23. {"v_neg", v_neg, "p=rp"},
  24. {"pnt_op_func__", v_neg, "p=rp"},
  25. {"v_mul", v_mul, "p=rpd"},
  26. {"pnt_op_func_*", v_mul, "p=rpd"},
  27. {"v_div", v_div, "p=rpd"},
  28. {"pnt_op_func_/", v_div, "p=rpd"},
  29. {"v_unit", v_unit, "p=rp"},
  30. {"v_cross", v_cross, "p=rpp"},
  31. {"pnt_op_func_^", v_cross, "p=rpp"},
  32. {"v_val", v_val, "d=p"},
  33. {"v_dot", v_dot, "d=pp"},
  34. {"pnt_op_func_%", v_dot, "d=pp"},
  35. {"v_area", v_area, "d=pp"},
  36. {"v_eq", v_eq, "d=pp"},
  37. {"v_eq_epsilon", v_eq_epsilon, "d=ppp"},
  38. {"v_isortho", v_isortho, "d=pp"},
  39. {"v_ispara", v_ispara, "d=pp"},
  40. {"v_isacute", v_isacute, "d=pp"},
  41. {NULL, NULL, NULL}
  42. };
  43. typedef VECTOR *(*p_func) (void);
  44. typedef VECTOR *(*p_func_p) (void *p0);
  45. typedef VECTOR *(*p_func_pp) (void *p0, void *p1);
  46. typedef VECTOR *(*p_func_ppp) (void *p0, void *p1, void *p2);
  47. typedef VECTOR *(*p_func_ppd) (void *p0, void *p1, double d);
  48. double nanval;
  49. static VECTOR pnt_o = { NULL, 0, 0, 0, 1 };
  50. static VECTOR pnt_i = { NULL, 1, 0, 0, 1 };
  51. static VECTOR pnt_j = { NULL, 0, 1, 0, 1 };
  52. static VECTOR pnt_k = { NULL, 0, 0, 1, 1 };
  53. void init_vec(void);
  54. void printvec(SYMBOL * sym);
  55. void showvec(SYMBOL * sym);
  56. void setpnt(SYMBOL * var, SYMBOL * pnt);
  57. SYMBOL *mkpnt(double x, double y, double z);
  58. SYMBOL *mkpntvar(SYMBOL * var, SYMBOL * pnt);
  59. SYMBOL *pntfunc(SYMBOL * func, SYMBOL * arglist);
  60. SYMBOL *pntop(int op, SYMBOL * pnt1, SYMBOL * pnt2);
  61. SYMBOL *pntapp(SYMBOL * head, SYMBOL * elt);
  62. VECTOR *v_copy(VECTOR * p, VECTOR * p1);
  63. VECTOR *v_add(VECTOR * p, VECTOR * p1, VECTOR * p2);
  64. VECTOR *v_sub(VECTOR * p, VECTOR * p1, VECTOR * p2);
  65. VECTOR *v_abs(VECTOR * p, VECTOR * p1);
  66. VECTOR *v_neg(VECTOR * p, VECTOR * p1);
  67. static inline int _is_zero(double r);
  68. double v_eq(VECTOR * p1, VECTOR * p2);
  69. double v_eq_epsilon(VECTOR * p1, VECTOR * p2, VECTOR * e);
  70. VECTOR *v_mul(VECTOR * p, VECTOR * p1, double d);
  71. VECTOR *v_div(VECTOR * p, VECTOR * p1, double d);
  72. double v_val(VECTOR * p);
  73. VECTOR *v_unit(VECTOR * p, VECTOR * p1);
  74. double v_dot(VECTOR * p1, VECTOR * p2);
  75. VECTOR *v_cross(VECTOR * p, VECTOR * p1, VECTOR * p2);
  76. double v_isortho(VECTOR * p1, VECTOR * p2);
  77. double v_ispara(VECTOR * p1, VECTOR * p2);
  78. double v_isacute(VECTOR * p1, VECTOR * p2);
  79. double v_area(VECTOR * p1, VECTOR * p2);
  80. void init_vec(void)
  81. {
  82. SYMBOL *sym;
  83. int i;
  84. for (i = 0; vf[i].name; i++) {
  85. sym = putsym(vf[i].name);
  86. switch (vf[i].proto[0]) {
  87. case 'p':
  88. sym->type = st_pfunc;
  89. sym->rettype = st_pnt;
  90. break;
  91. case 'd':
  92. sym->type = st_nfunc;
  93. sym->rettype = st_num;
  94. break;
  95. }
  96. sym->itype = sym->type;
  97. sym->v.p = vf[i].func;
  98. sym->proto = vf[i].proto + 2;
  99. }
  100. /* add some handy constants */
  101. sym = putsym("pnt_o");
  102. sym->type = sym->itype = st_pnt;
  103. sym->v.p = &pnt_o;
  104. sym = putsym("pnt_i");
  105. sym->type = sym->itype = st_pnt;
  106. sym->v.p = &pnt_i;
  107. sym = putsym("pnt_j");
  108. sym->type = sym->itype = st_pnt;
  109. sym->v.p = &pnt_j;
  110. sym = putsym("pnt_k");
  111. sym->type = sym->itype = st_pnt;
  112. sym->v.p = &pnt_k;
  113. /* initialize NaN */
  114. nanval = sqrt(-1);
  115. }
  116. void printvec(SYMBOL * sym)
  117. {
  118. VECTOR *v;
  119. v = (VECTOR *) sym->v.p;
  120. fprintf(stdout, "\t(");
  121. if (!isfinite(v->x))
  122. fprintf(stdout, "??.??");
  123. else if (v->x == (int)v->x)
  124. fprintf(stdout, "%d", (int)v->x);
  125. else
  126. fprintf(stdout, "%g", v->x);
  127. fprintf(stdout, ", ");
  128. if (!isfinite(v->y))
  129. fprintf(stdout, "??.??");
  130. else if (v->y == (int)v->y)
  131. fprintf(stdout, "%d", (int)v->y);
  132. else
  133. fprintf(stdout, "%g", v->y);
  134. if (isfinite(v->z)) {
  135. fprintf(stdout, ", ");
  136. if (v->z == (int)v->z)
  137. fprintf(stdout, "%d", (int)v->z);
  138. else
  139. fprintf(stdout, "%g", v->z);
  140. }
  141. fprintf(stdout, ")\n");
  142. }
  143. void showvec(SYMBOL * sym)
  144. {
  145. VECTOR *v;
  146. v = (VECTOR *) sym->v.p;
  147. printvec(sym);
  148. if (v && --v->refcnt > 0)
  149. sym->v.p = NULL;
  150. freesym(sym);
  151. }
  152. void setpnt(SYMBOL * var, SYMBOL * pnt)
  153. {
  154. SYMBOL *sym;
  155. if (var->name) {
  156. sym = getsym(var->name);
  157. if (sym) {
  158. if (--((VECTOR *) sym->v.p)->refcnt < 1)
  159. G_free(sym->v.p);
  160. /*
  161. * If refcnt(pnt) == 1, this was anonymous, else it's used
  162. * somewhere else. Must we dup then?
  163. */
  164. sym->v.p = pnt->v.p;
  165. }
  166. }
  167. if (--((VECTOR *) var->v.p)->refcnt < 1)
  168. G_free(var->v.p);
  169. var->v.p = NULL;
  170. freesym(var);
  171. printvec(pnt);
  172. pnt->v.p = NULL;
  173. freesym(pnt);
  174. }
  175. SYMBOL *mkpnt(double x, double y, double z)
  176. {
  177. SYMBOL *pnt;
  178. VECTOR *vec;
  179. vec = (VECTOR *) listitem(sizeof(VECTOR));
  180. vec->x = x;
  181. vec->y = y;
  182. vec->z = z;
  183. vec->refcnt = 1;
  184. pnt = (SYMBOL *) listitem(sizeof(SYMBOL));
  185. pnt->type = pnt->itype = st_pnt;
  186. pnt->v.p = vec;
  187. return pnt;
  188. }
  189. SYMBOL *mkpntvar(SYMBOL * var, SYMBOL * pnt)
  190. {
  191. var->type = var->itype = st_pnt;
  192. var->name = var->v.p;
  193. var->v.p = pnt->v.p;
  194. pnt->v.p = NULL;
  195. freesym(pnt);
  196. symtab = (SYMBOL *) listadd((LIST *) symtab, (LIST *) var, cmpsymsym);
  197. printvec(var);
  198. return var;
  199. }
  200. SYMBOL *pntfunc(SYMBOL * func, SYMBOL * arglist)
  201. {
  202. SYMBOL *sym, *sptr;
  203. VECTOR *res = NULL;
  204. int argc = -1, i;
  205. sym = (SYMBOL *) listitem(sizeof(SYMBOL));
  206. sym->type = sym->itype = st_pnt;
  207. if (!func || !func->v.p || func->type != st_pfunc) {
  208. parseerror = 1;
  209. G_warning(_("Can't call bad function"));
  210. }
  211. else
  212. argc = listcnt((LIST *) arglist);
  213. for (i = 0, sptr = arglist; sptr; sptr = sptr->next, i++) {
  214. if (func->proto[i] == 'r')
  215. i++;
  216. if (func->proto[i] == 'p') {
  217. if (sptr->itype != st_pnt || !sptr->v.p)
  218. argc = -1;
  219. }
  220. else if (func->proto[i] == 'd' && sptr->itype != st_num)
  221. argc = -1;
  222. }
  223. res = (VECTOR *) listitem(sizeof(VECTOR));
  224. if (argc == 0 && (!func->proto || !*func->proto))
  225. res = (*(p_func) func->v.p) ();
  226. else if (argc == 1 && !strcmp(func->proto, "p"))
  227. res = (*(p_func_p) func->v.p) (arglist->v.p);
  228. else if (argc == 1 && !strcmp(func->proto, "rp"))
  229. res = (*(p_func_pp) func->v.p) (res, arglist->v.p);
  230. else if (argc == 2 && !strcmp(func->proto, "rpd"))
  231. res = (*(p_func_ppd) func->v.p) (res, arglist->v.p,
  232. arglist->next->v.d);
  233. else if (argc == 2 && !strcmp(func->proto, "pp"))
  234. res = (*(p_func_pp) func->v.p) (arglist->v.p, arglist->next->v.p);
  235. else if (argc == 2 && !strcmp(func->proto, "rpp"))
  236. res = (*(p_func_ppp) func->v.p) (res, arglist->v.p,
  237. arglist->next->v.p);
  238. else if (argc == 3 && !strcmp(func->proto, "ppp"))
  239. res = (*(p_func_ppp) func->v.p) (arglist->v.p,
  240. arglist->next->v.p,
  241. arglist->next->next->v.p);
  242. else {
  243. G_warning(_("Bad arguments to pointfunc %s"), func->name);
  244. parseerror = 1;
  245. sym = (SYMBOL *) listdelall((LIST *) sym, freesym);
  246. if (res)
  247. G_free(res);
  248. return NULL;
  249. }
  250. sym->v.p = res;
  251. listdelall((LIST *) arglist, freesym);
  252. return sym;
  253. }
  254. SYMBOL *pntop(int op, SYMBOL * pnt1, SYMBOL * pnt2)
  255. {
  256. SYMBOL *func, *arglist, *res = NULL;
  257. char buf[32];
  258. sprintf(buf, "pnt_op_func_%c", op);
  259. func = getsym(buf);
  260. if (!func) {
  261. G_warning(_("No function defined to perform ``point %c point''"), op);
  262. parseerror = 1;
  263. }
  264. else if (func->rettype == st_pnt) {
  265. res = (SYMBOL *) listitem(sizeof(SYMBOL));
  266. symcpy(res, func);
  267. res->next = NULL;
  268. func = res;
  269. arglist = (SYMBOL *) listapp(NULL, (LIST *) pnt1);
  270. arglist = (SYMBOL *) listapp((LIST *) arglist, (LIST *) pnt2);
  271. res = pntfunc(func, arglist);
  272. }
  273. return res;
  274. }
  275. SYMBOL *pntapp(SYMBOL * head, SYMBOL * elt)
  276. {
  277. return (SYMBOL *) listapp((LIST *) head, (LIST *) elt);
  278. }
  279. /*
  280. * Utility function to copy a point: p = p1;
  281. * The dimension (2D/3D) depends on p1. Note, that copying a constant
  282. * will always yield 3D.
  283. */
  284. VECTOR *v_copy(VECTOR * p, VECTOR * p1)
  285. {
  286. p->x = p1->x;
  287. p->y = p1->y;
  288. p->z = p1->z;
  289. return p;
  290. }
  291. /*
  292. * Vector addition
  293. * Result is 2D if at least one of p1 or p2 is 2D.
  294. */
  295. VECTOR *v_add(VECTOR * p, VECTOR * p1, VECTOR * p2)
  296. {
  297. p->x = p1->x + p2->x;
  298. p->y = p1->y + p2->y;
  299. /*
  300. * resist the tentation setting p->z to nanval and then testing for
  301. * dimension, as p might be the same as p1 or p2
  302. */
  303. if (!isnan(p1->z) && !isnan(p2->z))
  304. p->z = p1->z + p2->z;
  305. else
  306. p->z = nanval;
  307. return p;
  308. }
  309. /*
  310. * Vector substraction
  311. * Result is 2D if at least one of p1 or p2 is 2D.
  312. */
  313. VECTOR *v_sub(VECTOR * p, VECTOR * p1, VECTOR * p2)
  314. {
  315. p->x = p1->x - p2->x;
  316. p->y = p1->y - p2->y;
  317. if (!isnan(p1->z) && !isnan(p2->z))
  318. p->z = p1->z + p2->z;
  319. else
  320. p->z = nanval;
  321. return p;
  322. }
  323. /*
  324. * Utility function to make all coordinates positive
  325. */
  326. VECTOR *v_abs(VECTOR * p, VECTOR * p1)
  327. {
  328. p->x = fabs(p1->x);
  329. p->y = fabs(p1->y);
  330. if (!isnan(p1->z))
  331. p->z = fabs(p1->z);
  332. else
  333. p->z = nanval;
  334. return p;
  335. }
  336. /*
  337. * Utility function to negate all coordinates
  338. */
  339. VECTOR *v_neg(VECTOR * p, VECTOR * p1)
  340. {
  341. p->x = -p1->x;
  342. p->y = -p1->y;
  343. if (!isnan(p1->z))
  344. p->z = -p1->z;
  345. else
  346. p->z = nanval;
  347. return p;
  348. }
  349. /*
  350. * Utility function to compare two doubles for equality without epsilon
  351. * This is not really true, as we consider NaN to be zero.
  352. */
  353. static inline int _is_zero(double r)
  354. {
  355. if ((isfinite(r) && r == 0.0) || isnan(r))
  356. return 1;
  357. return 0;
  358. }
  359. /*
  360. * Test for equality of two points. No epsion applied
  361. */
  362. double v_eq(VECTOR * p1, VECTOR * p2)
  363. {
  364. VECTOR p;
  365. int dim = 2;
  366. if (!isnan(p1->z) && !isnan(p2->z))
  367. dim = 3;
  368. v_sub(&p, p1, p2);
  369. v_abs(&p, &p);
  370. if (_is_zero(p.x) && _is_zero(p.y) && (dim == 2 || _is_zero(p.z)))
  371. return 1;
  372. return 0;
  373. }
  374. /*
  375. * Test for equality of two points by a given epsilon
  376. * epsilon is supposed to have positive values only.
  377. */
  378. double v_eq_epsilon(VECTOR * p1, VECTOR * p2, VECTOR * e)
  379. {
  380. VECTOR p;
  381. int dim = 2;
  382. if (!isnan(p1->z) && !isnan(p2->z))
  383. dim = 3;
  384. v_sub(&p, p1, p2);
  385. v_abs(&p, &p);
  386. if (p.x < e->x && p.y < e->y && (dim == 2 || (p.z < e->z)))
  387. return 1;
  388. return 0;
  389. }
  390. /*
  391. * Multiply a vector by a scalar
  392. */
  393. VECTOR *v_mul(VECTOR * p, VECTOR * p1, double d)
  394. {
  395. p->x = d * p1->x;
  396. p->y = d * p1->y;
  397. if (!isnan(p1->z))
  398. p->z = d * p1->z;
  399. else
  400. p->z = nanval;
  401. return p;
  402. }
  403. /*
  404. * Divide a vector by a scalar
  405. */
  406. VECTOR *v_div(VECTOR * p, VECTOR * p1, double d)
  407. {
  408. if (!isfinite(d) || d == 0.0) {
  409. parseerror = 1;
  410. return p;
  411. }
  412. p->x = p1->x / d;
  413. p->y = p1->y / d;
  414. if (!isnan(p1->z))
  415. p->z = p1->z / d;
  416. else
  417. p->z = nanval;
  418. return p;
  419. }
  420. /*
  421. * Compute the value of a vector
  422. */
  423. double v_val(VECTOR * p)
  424. {
  425. return sqrt(p->x * p->x + p->y * p->y +
  426. ((isnan(p->z)) ? 0 : p->z * p->z));
  427. }
  428. /*
  429. * The only way to get a value of zero is that P1 is the origin.
  430. * The unit vector of the origin doesn't exist, but we return the
  431. * origin.
  432. */
  433. VECTOR *v_unit(VECTOR * p, VECTOR * p1)
  434. {
  435. double val = v_val(p1);
  436. if (_is_zero(val))
  437. return v_copy(p, &pnt_o);
  438. p->x = p1->x / val;
  439. p->y = p1->y / val;
  440. if (!isnan(p1->z))
  441. p->z = p1->z / val;
  442. else
  443. p->z = nanval;
  444. return p;
  445. }
  446. /*
  447. * Compute the dot product of P1 and P2
  448. */
  449. double v_dot(VECTOR * p1, VECTOR * p2)
  450. {
  451. int dim = 2;
  452. if (!isnan(p1->z) && !isnan(p2->z))
  453. dim = 3;
  454. return p1->x * p2->x + p1->y * p2->y + ((dim == 2) ? 0 : p1->z * p2->z);
  455. }
  456. /*
  457. * Compute the cross product of P1 and P2
  458. * Return (0,0) for 2D
  459. */
  460. VECTOR *v_cross(VECTOR * p, VECTOR * p1, VECTOR * p2)
  461. {
  462. VECTOR p0;
  463. if (!isnan(p1->z) && !isnan(p2->z)) {
  464. p0.x = p1->y * p2->z + p1->z * p2->y;
  465. p0.y = p1->z * p2->x + p1->x * p2->z;
  466. p0.z = p1->x * p2->y + p1->y * p2->x;
  467. v_copy(p, &p0);
  468. }
  469. else {
  470. p->x = p->y = 0;
  471. p->z = nanval;
  472. }
  473. return p;
  474. }
  475. /*
  476. * Decide if vector P1 is ortogonal to vector P2
  477. * Should test if either P1 or P2 are (0,0,0);
  478. */
  479. double v_isortho(VECTOR * p1, VECTOR * p2)
  480. {
  481. return v_dot(p1, p2) == 0;
  482. }
  483. /*
  484. * Decide if P1 and P2 are parallel. If they are but have a diferent
  485. * direction, -1 is returned.
  486. */
  487. double v_ispara(VECTOR * p1, VECTOR * p2)
  488. {
  489. double dot, val, dif;
  490. dot = v_dot(p1, p2);
  491. val = v_val(p1);
  492. val *= v_val(p2);
  493. dif = fabs(dot - val);
  494. if (_is_zero(dif))
  495. return 1;
  496. dif = fabs(dot + val);
  497. if (_is_zero(dif))
  498. return -1;
  499. return 0;
  500. }
  501. /*
  502. * Decide if P1 and P2 have and angle alpha which: 0 < alpha < 90.0
  503. */
  504. double v_isacute(VECTOR * p1, VECTOR * p2)
  505. {
  506. return v_dot(p1, p2) > 0;
  507. }
  508. /*
  509. * Return the area spanned by the two vectors P1 and P2
  510. * Works only in 3D.
  511. */
  512. double v_area(VECTOR * p1, VECTOR * p2)
  513. {
  514. VECTOR p;
  515. return 0.5 * v_val(v_cross(&p, p1, p2));
  516. }