qtree.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*-
  2. * Written by H. Mitasova, I. Kosinovsky, D. Gerdes Fall 1993
  3. * University of Illinois
  4. * US Army Construction Engineering Research Lab
  5. * Copyright 1993, H. Mitasova (University of Illinois),
  6. * I. Kosinovsky, (USA-CERL), and D.Gerdes (USA-CERL)
  7. *
  8. * updated by Mitasova Nov. 96, no changes necessary
  9. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <math.h>
  13. #include <grass/dataquad.h>
  14. #include <grass/qtree.h>
  15. struct multfunc
  16. *MT_functions_new(int (*compare) (struct triple *, struct quaddata *),
  17. struct quaddata **(*divide_data) (struct quaddata *,
  18. int, double),
  19. int (*add_data) (struct triple *, struct quaddata *,
  20. double),
  21. int (*intersect) (struct quaddata *, struct quaddata *),
  22. int (*division_check) (struct quaddata *, int),
  23. int (*get_points) (struct quaddata *, struct quaddata *,
  24. int))
  25. /* Initializes FUNCTIONS structure with given arguments */
  26. {
  27. struct multfunc *functions;
  28. if (!(functions = (struct multfunc *)malloc(sizeof(struct multfunc)))) {
  29. return NULL;
  30. }
  31. functions->compare = compare;
  32. functions->divide_data = divide_data;
  33. functions->add_data = add_data;
  34. functions->intersect = intersect;
  35. functions->division_check = division_check;
  36. functions->get_points = get_points;
  37. return functions;
  38. }
  39. struct tree_info *MT_tree_info_new(struct multtree *root,
  40. struct multfunc *functions, double dmin,
  41. int kmax)
  42. /*Initializes TREE_INFO using given arguments */
  43. {
  44. struct tree_info *info;
  45. if (!(info = (struct tree_info *)malloc(sizeof(struct tree_info)))) {
  46. return NULL;
  47. }
  48. info->root = root;
  49. info->functions = functions;
  50. info->dmin = dmin;
  51. info->kmax = kmax;
  52. return info;
  53. }
  54. struct multtree *MT_tree_new(struct quaddata *data,
  55. struct multtree **leafs, struct multtree *parent,
  56. int multant)
  57. /*Initializes TREE using given arguments */
  58. {
  59. struct multtree *tree;
  60. if (!(tree = (struct multtree *)malloc(sizeof(struct multtree)))) {
  61. return NULL;
  62. }
  63. tree->data = data;
  64. tree->leafs = leafs;
  65. tree->parent = parent;
  66. tree->multant = multant;
  67. return tree;
  68. }
  69. int MT_insert(struct triple *point,
  70. struct tree_info *info, struct multtree *tree, int n_leafs)
  71. /*First checks for dividing cond. (if n_points>=KMAX) and TREE is a leaf
  72. by calling one of tree's functions (division_check()).
  73. If TREE is not a leaf (is a node) uses function compare to determine
  74. into which "son" we need to insert the point and calls MT_insert()
  75. with this son as a n argument.
  76. If TREE is a leaf but we don't need to divide it (n_points<KMAX) then
  77. calls function add_data(POINT) to add POINT to the data of TREE and
  78. returns the result of add_data() (which returns 1 if the point is
  79. inserted and 0 if its ignored (when its too dense)).
  80. If Division_check returns true, calls MT_divide(TREE) and then calls
  81. insert_quad() to insert the POINT into divided TREE and returns the
  82. result of MT_divide(). */
  83. {
  84. int j = 0, i, k, comp;
  85. if (tree == NULL) {
  86. fprintf(stderr, "insert: tree is NULL\n");
  87. return -5;
  88. }
  89. if (tree->data == NULL) {
  90. fprintf(stderr, "insert: tree->data is NULL\n");
  91. return -5;
  92. }
  93. i = info->functions->division_check(tree->data, info->kmax);
  94. if (i <= 0) {
  95. if (i == -1) {
  96. comp = info->functions->compare(point, tree->data);
  97. if ((comp < 1) || (comp > n_leafs))
  98. return -3;
  99. j = MT_insert(point, info, tree->leafs[comp - 1], n_leafs);
  100. }
  101. else {
  102. if (i == 0) {
  103. j = info->functions->add_data(point, tree->data, info->dmin);
  104. }
  105. }
  106. }
  107. else {
  108. k = MT_divide(info, tree, n_leafs);
  109. if (k == 1)
  110. j = MT_insert(point, info, tree, n_leafs);
  111. if (k == -3) {
  112. static int once = 0;
  113. if (!once) {
  114. fprintf(stderr, "Point out of range!\n");
  115. once = 1;
  116. }
  117. }
  118. if (k < 0)
  119. return k;
  120. }
  121. return j;
  122. }
  123. int MT_divide(struct tree_info *info, struct multtree *tree, int n_leafs)
  124. /* Divides the tree by calling one of tree's functions (divide_data())
  125. and returns the result of divide_data() */
  126. {
  127. int i;
  128. struct quaddata **datas;
  129. struct multtree *par;
  130. struct multtree **leafs;
  131. datas = info->functions->divide_data(tree->data, info->kmax, info->dmin);
  132. if (datas == NULL) {
  133. fprintf(stderr, "datas is NULL\n");
  134. return -7;
  135. }
  136. par = tree;
  137. leafs = (struct multtree **)malloc(sizeof(struct multtree *) * n_leafs);
  138. for (i = 1; i <= n_leafs; i++) {
  139. leafs[i - 1] = MT_tree_new(datas[i], NULL, par, i);
  140. }
  141. tree->leafs = leafs;
  142. return 1;
  143. }
  144. int MT_region_data(struct tree_info *info, struct multtree *tree, struct quaddata *data, int MAX, /* max number of points we can add (KMAX2) */
  145. int n_leafs)
  146. /* Gets points inside the region defined by DATA from TREE and
  147. adds them to DATA. If the number of eligible
  148. point is more than MAX returns MAX+1 othervise returns number of points added
  149. to DATA.
  150. Uses tree's functions intersect() to find leafs that intersect given region
  151. and get_points() to get points from such leafs. */
  152. {
  153. int n = 0, j;
  154. if (tree == NULL) {
  155. fprintf(stderr, "MT_region_data: tree is NULL\n");
  156. return n;
  157. }
  158. if (tree->data == NULL) {
  159. fprintf(stderr, "MT_region_data: data is NULL\n");
  160. return n;
  161. }
  162. if (info->functions->intersect(data, tree->data)) {
  163. if (tree->leafs != NULL) {
  164. for (j = 0; j < n_leafs; j++) {
  165. if ((n =
  166. n + MT_region_data(info, tree->leafs[j], data, MAX - n,
  167. n_leafs)) > MAX)
  168. return n;
  169. }
  170. }
  171. else {
  172. n = info->functions->get_points(data, tree->data, MAX);
  173. }
  174. return n;
  175. }
  176. return 0;
  177. }