cindex.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. /*****************************************************************************
  2. *
  3. * MODULE: Vector library
  4. *
  5. * AUTHOR(S): Radim Blazek
  6. *
  7. * PURPOSE: Lower level functions for reading/writing/manipulating vectors.
  8. *
  9. * COPYRIGHT: (C) 2001 by the GRASS Development Team
  10. *
  11. * This program is free software under the GNU General Public
  12. * License (>=v2). Read the file COPYING that comes with GRASS
  13. * for details.
  14. *
  15. *****************************************************************************/
  16. #include <grass/config.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <grass/gis.h>
  20. #include <grass/Vect.h>
  21. /*
  22. * dig_cidx_init ()
  23. * initit cat index
  24. *
  25. * returns 1 OK
  26. * 0 on error
  27. */
  28. int dig_cidx_init(struct Plus_head *Plus)
  29. {
  30. G_debug(3, "dig_cidx_init()");
  31. Plus->n_cidx = 0;
  32. Plus->a_cidx = 5;
  33. Plus->cidx =
  34. (struct Cat_index *)G_malloc(Plus->a_cidx * sizeof(struct Cat_index));
  35. if (!Plus->cidx)
  36. return 0;
  37. Plus->cidx_up_to_date = 0;
  38. return 1;
  39. }
  40. /* Free category index */
  41. void dig_cidx_free(struct Plus_head *Plus)
  42. {
  43. int i;
  44. struct Cat_index *ci;
  45. G_debug(2, "dig_cidx_free()");
  46. for (i = 0; i < Plus->n_cidx; i++) {
  47. ci = &(Plus->cidx[0]);
  48. G_free(ci->cat);
  49. ci->cat = NULL;
  50. ci->field = ci->n_cats = ci->a_cats = ci->n_types = 0;
  51. }
  52. Plus->n_cidx = 0;
  53. Plus->cidx_up_to_date = 0;
  54. }
  55. /*
  56. * dig_cidx_add_cat ()
  57. * add new field - cat - line record, space is allocated if necessary
  58. *
  59. * returns 1 OK
  60. * 0 on error
  61. */
  62. int
  63. dig_cidx_add_cat(struct Plus_head *Plus, int field, int cat, int line,
  64. int type)
  65. {
  66. int i, si, found;
  67. struct Cat_index *ci;
  68. G_debug(3, "dig_cidx_add_cat(): field = %d cat = %d line = %d type = %d",
  69. field, cat, line, type);
  70. /* Find field or add new */
  71. si = -1;
  72. for (i = 0; i < Plus->n_cidx; i++) {
  73. if (Plus->cidx[i].field == field) {
  74. si = i;
  75. }
  76. }
  77. if (si == -1) { /* not found add new */
  78. if (Plus->n_cidx == Plus->a_cidx) {
  79. Plus->a_cidx += 10;
  80. Plus->cidx =
  81. (struct Cat_index *)G_realloc(Plus->cidx,
  82. Plus->a_cidx *
  83. sizeof(struct Cat_index));
  84. if (!Plus->cidx)
  85. return 0;
  86. }
  87. si = Plus->n_cidx;
  88. ci = &(Plus->cidx[si]);
  89. ci->field = field;
  90. ci->n_cats = ci->a_cats = 0;
  91. ci->cat = NULL;
  92. ci->n_types = 0;
  93. ci->offset = 0;
  94. Plus->n_cidx++;
  95. }
  96. /* Add new cat - line record */
  97. ci = &(Plus->cidx[si]);
  98. if (ci->n_cats == ci->a_cats) {
  99. ci->a_cats += 5000;
  100. ci->cat = G_realloc(ci->cat, ci->a_cats * 3 * sizeof(int));
  101. }
  102. ci->cat[ci->n_cats][0] = cat;
  103. ci->cat[ci->n_cats][1] = type;
  104. ci->cat[ci->n_cats][2] = line;
  105. ci->n_cats++;
  106. /* Add type */
  107. found = 0;
  108. for (i = 0; i < ci->n_types; i++) {
  109. if (ci->type[i][0] == type) {
  110. ci->type[i][1]++;
  111. found = 1;
  112. }
  113. }
  114. if (!found) {
  115. ci->type[ci->n_types][0] = type;
  116. ci->type[ci->n_types][1] = 1;
  117. ci->n_types++;
  118. }
  119. return 1;
  120. }
  121. /* Compare by cat */
  122. static int cmp_cat(const void *pa, const void *pb)
  123. {
  124. int *p1 = (int *)pa;
  125. int *p2 = (int *)pb;
  126. if (p1[0] < p2[0])
  127. return -1;
  128. if (p1[0] > p2[0])
  129. return 1;
  130. return 0;
  131. }
  132. /* Compare by field */
  133. static int cmp_field(const void *pa, const void *pb)
  134. {
  135. struct Cat_index *p1 = (struct Cat_index *)pa;
  136. struct Cat_index *p2 = (struct Cat_index *)pb;
  137. if (p1->field < p2->field)
  138. return -1;
  139. if (p1->field > p2->field)
  140. return 1;
  141. return 0;
  142. }
  143. /*
  144. * dig_cidx_add_cat_sorted ()
  145. * add new field - cat - line record to sorted category index, space is allocated if necessary
  146. *
  147. * returns 1 OK
  148. * 0 on error
  149. */
  150. int
  151. dig_cidx_add_cat_sorted(struct Plus_head *Plus, int field, int cat, int line,
  152. int type)
  153. {
  154. int i, si, found, position;
  155. struct Cat_index *ci;
  156. G_debug(3,
  157. "dig_cidx_add_cat_sorted(): field = %d cat = %d line = %d type = %d",
  158. field, cat, line, type);
  159. /* Find field or add new */
  160. si = -1;
  161. for (i = 0; i < Plus->n_cidx; i++) {
  162. if (Plus->cidx[i].field == field) {
  163. si = i;
  164. }
  165. }
  166. if (si == -1) { /* not found add new */
  167. if (Plus->n_cidx == Plus->a_cidx) {
  168. Plus->a_cidx += 10;
  169. Plus->cidx =
  170. (struct Cat_index *)G_realloc(Plus->cidx,
  171. Plus->a_cidx *
  172. sizeof(struct Cat_index));
  173. if (!Plus->cidx)
  174. return 0;
  175. }
  176. si = Plus->n_cidx;
  177. ci = &(Plus->cidx[si]);
  178. ci->field = field;
  179. ci->n_cats = ci->a_cats = 0;
  180. ci->cat = NULL;
  181. ci->n_types = 0;
  182. ci->offset = 0;
  183. Plus->n_cidx++;
  184. }
  185. /* Add new cat - line record */
  186. ci = &(Plus->cidx[si]);
  187. if (ci->n_cats == ci->a_cats) {
  188. ci->a_cats += 5000;
  189. ci->cat = G_realloc(ci->cat, ci->a_cats * 3 * sizeof(int));
  190. }
  191. /* Find position */
  192. for (position = 0; position < ci->n_cats; position++) {
  193. if (ci->cat[position][0] >= cat) {
  194. break;
  195. }
  196. }
  197. G_debug(4, "position = %d", position);
  198. /* Move */
  199. for (i = ci->n_cats; i > position; i--) {
  200. ci->cat[i][0] = ci->cat[i - 1][0];
  201. ci->cat[i][1] = ci->cat[i - 1][1];
  202. ci->cat[i][2] = ci->cat[i - 1][2];
  203. }
  204. ci->cat[position][0] = cat;
  205. ci->cat[position][1] = type;
  206. ci->cat[position][2] = line;
  207. ci->n_cats++;
  208. /* Add type */
  209. found = 0;
  210. for (i = 0; i < ci->n_types; i++) {
  211. if (ci->type[i][0] == type) {
  212. ci->type[i][1]++;
  213. found = 1;
  214. }
  215. }
  216. if (!found) {
  217. ci->type[ci->n_types][0] = type;
  218. ci->type[ci->n_types][1] = 1;
  219. ci->n_types++;
  220. }
  221. /* Sort by field */
  222. qsort(Plus->cidx, Plus->n_cidx, sizeof(struct Cat_index), cmp_field);
  223. G_debug(3, "Added new category to index");
  224. return 1;
  225. }
  226. /*
  227. * dig_cidx_del_cat ()
  228. * delete old field - cat - line record from _sorted_ category index
  229. *
  230. * returns 1 OK
  231. * 0 on error
  232. */
  233. int
  234. dig_cidx_del_cat(struct Plus_head *Plus, int field, int cat, int line,
  235. int type)
  236. {
  237. int i, position;
  238. struct Cat_index *ci;
  239. G_debug(3, "dig_cidx_del_cat(): field = %d cat = %d line = %d", field,
  240. cat, line);
  241. /* Find field or add new */
  242. ci = NULL;
  243. for (i = 0; i < Plus->n_cidx; i++) {
  244. if (Plus->cidx[i].field == field) {
  245. ci = &(Plus->cidx[i]);
  246. }
  247. }
  248. if (ci == NULL) { /* should not happen */
  249. G_warning("BUG: Category index not found for field %d.", field);
  250. return 0;
  251. }
  252. /* Find position */
  253. G_debug(3, "n_cats = %d", ci->n_cats);
  254. for (position = 0; position < ci->n_cats; position++) {
  255. if (ci->cat[position][0] == cat && ci->cat[position][1] == type &&
  256. ci->cat[position][2] == line) {
  257. break;
  258. }
  259. }
  260. G_debug(4, "position = %d", position);
  261. if (position == ci->n_cats) {
  262. G_warning("BUG: Category not found in category index.");
  263. return 0;
  264. }
  265. /* Delete */
  266. for (i = position; i < ci->n_cats - 1; i++) {
  267. ci->cat[i][0] = ci->cat[i + 1][0];
  268. ci->cat[i][1] = ci->cat[i + 1][1];
  269. ci->cat[i][2] = ci->cat[i + 1][2];
  270. }
  271. ci->n_cats--;
  272. for (i = 0; i < ci->n_types; i++) {
  273. if (ci->type[i][0] == type) {
  274. ci->type[i][1]--;
  275. }
  276. }
  277. G_debug(3, "Deleted from category index");
  278. return 1;
  279. }
  280. /*
  281. * dig_cidx_sort ()
  282. * sort all records in cat index
  283. *
  284. */
  285. void dig_cidx_sort(struct Plus_head *Plus)
  286. {
  287. int f;
  288. struct Cat_index *ci;
  289. G_debug(2, "dig_cidx_sort()");
  290. for (f = 0; f < Plus->n_cidx; f++) {
  291. int c, nucats = 0;
  292. ci = &(Plus->cidx[f]);
  293. /* Sort by category */
  294. qsort(ci->cat, ci->n_cats, 3 * sizeof(int), cmp_cat);
  295. /* Calculate number of unique cats */
  296. if (ci->n_cats > 0)
  297. nucats++;
  298. for (c = 1; c < ci->n_cats; c++) {
  299. if (ci->cat[c][0] != ci->cat[c - 1][0])
  300. nucats++;
  301. }
  302. ci->n_ucats = nucats;
  303. }
  304. /* Sort by field */
  305. qsort(Plus->cidx, Plus->n_cidx, sizeof(struct Cat_index), cmp_field);
  306. }