cindex.c 7.6 KB

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