sw_geometry.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include <stdlib.h>
  2. #include <math.h>
  3. #include <grass/gis.h>
  4. #include "sw_defs.h"
  5. int geominit(void)
  6. {
  7. double sn;
  8. freeinit(&efl, sizeof(struct Edge));
  9. nvertices = 0;
  10. nedges = 0;
  11. sn = nsites + 4;
  12. sqrt_nsites = sqrt(sn);
  13. deltay = ymax - ymin;
  14. deltax = xmax - xmin;
  15. return 0;
  16. }
  17. struct Edge *bisect(struct Site *s1, struct Site *s2)
  18. {
  19. double dx, dy, adx, ady;
  20. struct Edge *newedge;
  21. newedge = (struct Edge *)getfree(&efl);
  22. newedge->reg[0] = s1;
  23. newedge->reg[1] = s2;
  24. ref(s1);
  25. ref(s2);
  26. newedge->ep[0] = (struct Site *)NULL;
  27. newedge->ep[1] = (struct Site *)NULL;
  28. if (s1->coord.x < s2->coord.x ||
  29. (s1->coord.x == s2->coord.x && s1->coord.y < s2->coord.y)) {
  30. dx = s2->coord.x - s1->coord.x;
  31. dy = s2->coord.y - s1->coord.y;
  32. newedge->c =
  33. s1->coord.x * dx + s1->coord.y * dy + (dx * dx + dy * dy) * 0.5;
  34. }
  35. else {
  36. dx = s1->coord.x - s2->coord.x;
  37. dy = s1->coord.y - s2->coord.y;
  38. newedge->c =
  39. s2->coord.x * dx + s2->coord.y * dy + (dx * dx + dy * dy) * 0.5;
  40. }
  41. adx = dx > 0 ? dx : -dx;
  42. ady = dy > 0 ? dy : -dy;
  43. if (adx > ady) {
  44. newedge->a = 1.0;
  45. newedge->b = dy / dx;
  46. newedge->c /= dx;
  47. }
  48. else {
  49. newedge->b = 1.0;
  50. newedge->a = dx / dy;
  51. newedge->c /= dy;
  52. }
  53. newedge->edgenbr = nedges;
  54. nedges++;
  55. return (newedge);
  56. }
  57. /* single precision ULP */
  58. double d_ulp(double d)
  59. {
  60. int exp;
  61. if (d == 0)
  62. return GRASS_EPSILON;
  63. if (d < 0)
  64. d = fabs(d);
  65. d = frexp(d, &exp);
  66. exp -= 22;
  67. d = ldexp(d, exp);
  68. return d;
  69. }
  70. struct Site *intersect(struct Halfedge *el1, struct Halfedge *el2)
  71. {
  72. struct Edge *e1, *e2, *e;
  73. struct Halfedge *el;
  74. double d, dt, xint, yint;
  75. int right_of_site;
  76. struct Site *v;
  77. e1 = el1->ELedge;
  78. e2 = el2->ELedge;
  79. if (e1 == (struct Edge *)NULL || e2 == (struct Edge *)NULL)
  80. return ((struct Site *)NULL);
  81. if (e1->reg[1] == e2->reg[1])
  82. return ((struct Site *)NULL);
  83. d = e1->a * e2->b - e1->b * e2->a;
  84. if (fabs(e1->a * e2->b) > fabs(e1->b * e2->a)) {
  85. dt = fabs(e1->a * e2->b);
  86. }
  87. else
  88. dt = fabs(e1->b * e2->a);
  89. if (dt != dt)
  90. return ((struct Site *)NULL);
  91. dt = d_ulp(dt);
  92. G_debug(4, "dt = %g", dt);
  93. if (-dt < d && d < dt)
  94. return ((struct Site *)NULL);
  95. xint = (e1->c * e2->b - e2->c * e1->b) / d;
  96. yint = (e2->c * e1->a - e1->c * e2->a) / d;
  97. if ((e1->reg[1]->coord.y < e2->reg[1]->coord.y) ||
  98. (e1->reg[1]->coord.y == e2->reg[1]->coord.y &&
  99. e1->reg[1]->coord.x < e2->reg[1]->coord.x)) {
  100. el = el1;
  101. e = e1;
  102. }
  103. else {
  104. el = el2;
  105. e = e2;
  106. }
  107. right_of_site = xint >= e->reg[1]->coord.x;
  108. if ((right_of_site && el->ELpm == le) ||
  109. (!right_of_site && el->ELpm == re))
  110. return ((struct Site *)NULL);
  111. v = (struct Site *)getfree(&sfl);
  112. v->refcnt = 0;
  113. v->coord.x = xint;
  114. v->coord.y = yint;
  115. return (v);
  116. }
  117. /* returns 1 if p is to right of halfedge e */
  118. int right_of(struct Halfedge *el, struct Point *p)
  119. {
  120. struct Edge *e;
  121. struct Site *topsite;
  122. int right_of_site, above, fast;
  123. double dxp, dyp, dxs, t1, t2, t3, yl;
  124. e = el->ELedge;
  125. topsite = e->reg[1];
  126. right_of_site = p->x > topsite->coord.x;
  127. if (right_of_site && el->ELpm == le)
  128. return (1);
  129. if (!right_of_site && el->ELpm == re)
  130. return (0);
  131. if (e->a == 1.0) {
  132. dyp = p->y - topsite->coord.y;
  133. dxp = p->x - topsite->coord.x;
  134. fast = 0;
  135. if ((!right_of_site & (e->b < 0.0)) | (right_of_site & (e->b >= 0.0))) {
  136. above = dyp >= e->b * dxp;
  137. fast = above;
  138. }
  139. else {
  140. above = p->x + p->y * e->b > e->c;
  141. if (e->b < 0.0)
  142. above = !above;
  143. if (!above)
  144. fast = 1;
  145. }
  146. if (!fast) {
  147. dxs = topsite->coord.x - (e->reg[0])->coord.x;
  148. above = e->b * (dxp * dxp - dyp * dyp) <
  149. dxs * dyp * (1.0 + 2.0 * dxp / dxs + e->b * e->b);
  150. if (e->b < 0.0)
  151. above = !above;
  152. }
  153. }
  154. else { /*e->b==1.0 */
  155. yl = e->c - e->a * p->x;
  156. t1 = p->y - yl;
  157. t2 = p->x - topsite->coord.x;
  158. t3 = yl - topsite->coord.y;
  159. above = t1 * t1 > t2 * t2 + t3 * t3;
  160. }
  161. return (el->ELpm == le ? above : !above);
  162. }
  163. int endpoint(struct Edge *e, int lr, struct Site *s)
  164. {
  165. e->ep[lr] = s;
  166. ref(s);
  167. if (e->ep[re - lr] == (struct Site *)NULL)
  168. return -1;
  169. write_ep(e);
  170. deref(e->reg[le]);
  171. deref(e->reg[re]);
  172. makefree((struct Freenode *)e, &efl);
  173. return 0;
  174. }
  175. double dist(struct Site *s, struct Site *t)
  176. {
  177. double dx, dy;
  178. dx = s->coord.x - t->coord.x;
  179. dy = s->coord.y - t->coord.y;
  180. return (sqrt(dx * dx + dy * dy));
  181. }
  182. int makevertex(struct Site *v)
  183. {
  184. v->sitenbr = -1;
  185. nvertices++;
  186. return 0;
  187. }
  188. int deref(struct Site *v)
  189. {
  190. v->refcnt--;
  191. if (v->refcnt == 0)
  192. makefree((struct Freenode *)v, &sfl);
  193. return 0;
  194. }
  195. int ref(struct Site *v)
  196. {
  197. v->refcnt++;
  198. return 0;
  199. }