cindex.c 7.9 KB

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