rect.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /****************************************************************************
  2. * MODULE: R-Tree library
  3. *
  4. * AUTHOR(S): Antonin Guttman - original code
  5. * Daniel Green (green@superliminal.com) - major clean-up
  6. * and implementation of bounding spheres
  7. * Markus Metz - R*-tree
  8. *
  9. * PURPOSE: Multidimensional index
  10. *
  11. * COPYRIGHT: (C) 2009 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General Public
  14. * License (>=v2). Read the file COPYING that comes with GRASS
  15. * for details.
  16. *****************************************************************************/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <assert.h>
  20. #include "index.h"
  21. #include <float.h>
  22. #include <math.h>
  23. #define BIG_NUM (FLT_MAX/4.0)
  24. #define Undefined(x) ((x)->boundary[0] > (x)->boundary[NUMDIMS])
  25. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  26. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  27. /*-----------------------------------------------------------------------------
  28. | Initialize a rectangle to have all 0 coordinates.
  29. -----------------------------------------------------------------------------*/
  30. void RTreeInitRect(struct Rect *R)
  31. {
  32. register struct Rect *r = R;
  33. register int i;
  34. for (i = 0; i < NUMSIDES; i++)
  35. r->boundary[i] = (RectReal) 0;
  36. }
  37. /*-----------------------------------------------------------------------------
  38. | Return a rect whose first low side is higher than its opposite side -
  39. | interpreted as an undefined rect.
  40. -----------------------------------------------------------------------------*/
  41. struct Rect RTreeNullRect(void)
  42. {
  43. struct Rect r;
  44. register int i;
  45. r.boundary[0] = (RectReal) 1;
  46. r.boundary[NUMDIMS] = (RectReal) - 1;
  47. for (i = 1; i < NUMDIMS; i++)
  48. r.boundary[i] = r.boundary[i + NUMDIMS] = (RectReal) 0;
  49. return r;
  50. }
  51. #if 0
  52. /*-----------------------------------------------------------------------------
  53. | Fills in random coordinates in a rectangle.
  54. | The low side is guaranteed to be less than the high side.
  55. -----------------------------------------------------------------------------*/
  56. void RTreeRandomRect(struct Rect *R)
  57. {
  58. register struct Rect *r = R;
  59. register int i;
  60. register RectReal width;
  61. for (i = 0; i < NUMDIMS; i++) {
  62. /* width from 1 to 1000 / 4, more small ones
  63. */
  64. width = drand48() * (1000 / 4) + 1;
  65. /* sprinkle a given size evenly but so they stay in [0,100]
  66. */
  67. r->boundary[i] = drand48() * (1000 - width); /* low side */
  68. r->boundary[i + NUMDIMS] = r->boundary[i] + width; /* high side */
  69. }
  70. }
  71. /*-----------------------------------------------------------------------------
  72. | Fill in the boundaries for a random search rectangle.
  73. | Pass in a pointer to a rect that contains all the data,
  74. | and a pointer to the rect to be filled in.
  75. | Generated rect is centered randomly anywhere in the data area,
  76. | and has size from 0 to the size of the data area in each dimension,
  77. | i.e. search rect can stick out beyond data area.
  78. -----------------------------------------------------------------------------*/
  79. void RTreeSearchRect(struct Rect *Search, struct Rect *Data)
  80. {
  81. register struct Rect *search = Search, *data = Data;
  82. register int i, j;
  83. register RectReal size, center;
  84. assert(search);
  85. assert(data);
  86. for (i = 0; i < NUMDIMS; i++) {
  87. j = i + NUMDIMS; /* index for high side boundary */
  88. if (data->boundary[i] > -BIG_NUM && data->boundary[j] < BIG_NUM) {
  89. size = (drand48() * (data->boundary[j] -
  90. data->boundary[i] + 1)) / 2;
  91. center = data->boundary[i] + drand48() *
  92. (data->boundary[j] - data->boundary[i] + 1);
  93. search->boundary[i] = center - size / 2;
  94. search->boundary[j] = center + size / 2;
  95. }
  96. else { /* some open boundary, search entire dimension */
  97. search->boundary[i] = -BIG_NUM;
  98. search->boundary[j] = BIG_NUM;
  99. }
  100. }
  101. }
  102. #endif
  103. /*-----------------------------------------------------------------------------
  104. | Print out the data for a rectangle.
  105. -----------------------------------------------------------------------------*/
  106. void RTreePrintRect(struct Rect *R, int depth)
  107. {
  108. register struct Rect *r = R;
  109. register int i;
  110. assert(r);
  111. RTreeTabIn(depth);
  112. fprintf(stdout, "rect:\n");
  113. for (i = 0; i < NUMDIMS; i++) {
  114. RTreeTabIn(depth + 1);
  115. fprintf(stdout, "%f\t%f\n", r->boundary[i], r->boundary[i + NUMDIMS]);
  116. }
  117. }
  118. /*-----------------------------------------------------------------------------
  119. | Calculate the n-dimensional volume of a rectangle
  120. -----------------------------------------------------------------------------*/
  121. RectReal RTreeRectVolume(struct Rect *R, struct RTree *t)
  122. {
  123. register struct Rect *r = R;
  124. register int i;
  125. register RectReal volume = (RectReal) 1;
  126. assert(r);
  127. if (Undefined(r))
  128. return (RectReal) 0;
  129. for (i = 0; i < t->ndims; i++)
  130. volume *= r->boundary[i + NUMDIMS] - r->boundary[i];
  131. assert(volume >= 0.0);
  132. return volume;
  133. }
  134. /*-----------------------------------------------------------------------------
  135. | Define the NUMDIMS-dimensional volume the unit sphere in that dimension into
  136. | the symbol "UnitSphereVolume"
  137. | Note that if the gamma function is available in the math library and if the
  138. | compiler supports static initialization using functions, this is
  139. | easily computed for any dimension. If not, the value can be precomputed and
  140. | taken from a table. The following code can do it either way.
  141. -----------------------------------------------------------------------------*/
  142. #ifdef gamma
  143. /* computes the volume of an N-dimensional sphere. */
  144. /* derived from formule in "Regular Polytopes" by H.S.M Coxeter */
  145. static double sphere_volume(double dimension)
  146. {
  147. double log_gamma, log_volume;
  148. log_gamma = gamma(dimension / 2.0 + 1);
  149. log_volume = dimension / 2.0 * log(M_PI) - log_gamma;
  150. return exp(log_volume);
  151. }
  152. static const double UnitSphereVolume = sphere_volume(NUMDIMS);
  153. #else
  154. /* Precomputed volumes of the unit spheres for the first few dimensions */
  155. const double UnitSphereVolumes[] = {
  156. 0.000000, /* dimension 0 */
  157. 2.000000, /* dimension 1 */
  158. 3.141593, /* dimension 2 */
  159. 4.188790, /* dimension 3 */
  160. 4.934802, /* dimension 4 */
  161. 5.263789, /* dimension 5 */
  162. 5.167713, /* dimension 6 */
  163. 4.724766, /* dimension 7 */
  164. 4.058712, /* dimension 8 */
  165. 3.298509, /* dimension 9 */
  166. 2.550164, /* dimension 10 */
  167. 1.884104, /* dimension 11 */
  168. 1.335263, /* dimension 12 */
  169. 0.910629, /* dimension 13 */
  170. 0.599265, /* dimension 14 */
  171. 0.381443, /* dimension 15 */
  172. 0.235331, /* dimension 16 */
  173. 0.140981, /* dimension 17 */
  174. 0.082146, /* dimension 18 */
  175. 0.046622, /* dimension 19 */
  176. 0.025807, /* dimension 20 */
  177. };
  178. #if NUMDIMS > 20
  179. # error "not enough precomputed sphere volumes"
  180. #endif
  181. #define UnitSphereVolume UnitSphereVolumes[NUMDIMS]
  182. #endif
  183. /*-----------------------------------------------------------------------------
  184. | Calculate the n-dimensional volume of the bounding sphere of a rectangle
  185. -----------------------------------------------------------------------------*/
  186. #if 0
  187. /*
  188. * A fast approximation to the volume of the bounding sphere for the
  189. * given Rect. By Paul B.
  190. */
  191. RectReal RTreeRectSphericalVolume(struct Rect *R, struct RTree *t)
  192. {
  193. register struct Rect *r = R;
  194. register int i;
  195. RectReal maxsize = (RectReal) 0, c_size;
  196. assert(r);
  197. if (Undefined(r))
  198. return (RectReal) 0;
  199. for (i = 0; i < t->ndims; i++) {
  200. c_size = r->boundary[i + NUMDIMS] - r->boundary[i];
  201. if (c_size > maxsize)
  202. maxsize = c_size;
  203. }
  204. return (RectReal) (pow(maxsize / 2, NUMDIMS) *
  205. UnitSphereVolumes[t->ndims]);
  206. }
  207. #endif
  208. /*
  209. * The exact volume of the bounding sphere for the given Rect.
  210. */
  211. RectReal RTreeRectSphericalVolume(struct Rect * r, struct RTree * t)
  212. {
  213. int i;
  214. double sum_of_squares = 0, radius, half_extent;
  215. assert(r);
  216. if (Undefined(r))
  217. return (RectReal) 0;
  218. for (i = 0; i < t->ndims; i++) {
  219. half_extent = (r->boundary[i + NUMDIMS] - r->boundary[i]) / 2;
  220. sum_of_squares += half_extent * half_extent;
  221. }
  222. radius = sqrt(sum_of_squares);
  223. return (RectReal) (pow(radius, t->ndims) * UnitSphereVolumes[t->ndims]);
  224. }
  225. /*-----------------------------------------------------------------------------
  226. | Calculate the n-dimensional surface area of a rectangle
  227. -----------------------------------------------------------------------------*/
  228. RectReal RTreeRectSurfaceArea(struct Rect * r, struct RTree * t)
  229. {
  230. int i, j;
  231. RectReal j_extent, sum = (RectReal) 0;
  232. assert(r);
  233. if (Undefined(r))
  234. return (RectReal) 0;
  235. for (i = 0; i < t->ndims; i++) {
  236. RectReal face_area = (RectReal) 1;
  237. for (j = 0; j < t->ndims; j++)
  238. /* exclude i extent from product in this dimension */
  239. if (i != j) {
  240. j_extent = r->boundary[j + NUMDIMS] - r->boundary[j];
  241. face_area *= j_extent;
  242. }
  243. sum += face_area;
  244. }
  245. return 2 * sum;
  246. }
  247. /*-----------------------------------------------------------------------------
  248. | Calculate the n-dimensional margin of a rectangle
  249. | the margin is the sum of the lengths of the edges
  250. -----------------------------------------------------------------------------*/
  251. RectReal RTreeRectMargin(struct Rect * r, struct RTree * t)
  252. {
  253. int i;
  254. RectReal margin = 0.0;
  255. assert(r);
  256. for (i = 0; i < t->ndims; i++) {
  257. margin += r->boundary[i + NUMDIMS] - r->boundary[i];
  258. }
  259. return margin;
  260. }
  261. /*-----------------------------------------------------------------------------
  262. | Combine two rectangles, make one that includes both.
  263. -----------------------------------------------------------------------------*/
  264. struct Rect RTreeCombineRect(struct Rect *r, struct Rect *rr, struct RTree *t)
  265. {
  266. int i, j;
  267. struct Rect new_rect;
  268. assert(r && rr);
  269. if (Undefined(r))
  270. return *rr;
  271. if (Undefined(rr))
  272. return *r;
  273. for (i = 0; i < t->ndims; i++) {
  274. new_rect.boundary[i] = MIN(r->boundary[i], rr->boundary[i]);
  275. j = i + NUMDIMS;
  276. new_rect.boundary[j] = MAX(r->boundary[j], rr->boundary[j]);
  277. }
  278. return new_rect;
  279. }
  280. /*-----------------------------------------------------------------------------
  281. | Decide whether two rectangles overlap.
  282. -----------------------------------------------------------------------------*/
  283. int RTreeOverlap(struct Rect *r, struct Rect *s, struct RTree *t)
  284. {
  285. register int i, j;
  286. assert(r && s);
  287. for (i = 0; i < t->ndims; i++) {
  288. j = i + NUMDIMS; /* index for high sides */
  289. if (r->boundary[i] > s->boundary[j] ||
  290. s->boundary[i] > r->boundary[j]) {
  291. return FALSE;
  292. }
  293. }
  294. return TRUE;
  295. }
  296. /*-----------------------------------------------------------------------------
  297. | Decide whether rectangle r is contained in rectangle s.
  298. -----------------------------------------------------------------------------*/
  299. int RTreeContained(struct Rect *r, struct Rect *s, struct RTree *t)
  300. {
  301. register int i, j, result;
  302. assert(r && s); /* same as in RTreeOverlap() */
  303. /* undefined rect is contained in any other */
  304. if (Undefined(r))
  305. return TRUE;
  306. /* no rect (except an undefined one) is contained in an undef rect */
  307. if (Undefined(s))
  308. return FALSE;
  309. result = TRUE;
  310. for (i = 0; i < t->ndims; i++) {
  311. j = i + NUMDIMS; /* index for high sides */
  312. result = result && r->boundary[i] >= s->boundary[i]
  313. && r->boundary[j] <= s->boundary[j];
  314. }
  315. return result;
  316. }