cats.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /**
  2. \file cats.cpp
  3. \brief Category management
  4. This program is free software under the GNU General Public
  5. License (>=v2). Read the file COPYING that comes with GRASS
  6. for details.
  7. (C) 2008 by The GRASS development team
  8. \author Martin Landa <landa.martin gmail.com>
  9. \date 2008
  10. */
  11. #include "driver.h"
  12. #include "digit.h"
  13. /**
  14. \brief Initialize cats structure.
  15. \return 0 on success
  16. \return -1 on error
  17. */
  18. int Digit::InitCats()
  19. {
  20. int ndblinks, nfields, field, ncats;
  21. int cat, type, id;
  22. struct field_info *fi;
  23. if (!cats.empty()) {
  24. cats.clear();
  25. }
  26. if (!display->mapInfo) {
  27. return -1;
  28. }
  29. /* initialization */
  30. ndblinks = Vect_get_num_dblinks(display->mapInfo);
  31. for (int i = 0; i < ndblinks; i++) {
  32. fi = Vect_get_dblink(display->mapInfo, i);
  33. if (fi) {
  34. cats[fi->number] = PORT_INT_MIN;
  35. }
  36. }
  37. /* find max category */
  38. nfields = Vect_cidx_get_num_fields (display->mapInfo);
  39. G_debug(2, "wxDigit.InitCats(): nfields=%d", nfields);
  40. for (int i = 0; i < nfields; i++ ) {
  41. field = Vect_cidx_get_field_number(display->mapInfo, i);
  42. ncats = Vect_cidx_get_num_cats_by_index(display->mapInfo, i);
  43. if (field <= 0) {
  44. continue;
  45. }
  46. for (int j = 0; j < ncats; j++) {
  47. Vect_cidx_get_cat_by_index (display->mapInfo, i, j, &cat, &type, &id);
  48. if (cat > cats[field])
  49. cats[field] = cat;
  50. }
  51. G_debug(3, "wxDigit.InitCats(): layer=%d, cat=%d", field, cats[field]);
  52. }
  53. /* set default values */
  54. for(std::map<int, int>::const_iterator b = cats.begin(), e = cats.end();
  55. b != e; ++b ) {
  56. if (b->second == PORT_INT_MIN) {
  57. cats[b->first] = 0;
  58. G_debug(3, "wxDigit.InitCats(): layer=%d, cat=%d", b->first, cats[b->first]);
  59. }
  60. }
  61. return 0;
  62. }
  63. /**
  64. \brief Get max category number for layer
  65. \param layer layer number
  66. \return category number (1 if no category found)
  67. \return -1 on error
  68. */
  69. int Digit::GetCategory(int layer)
  70. {
  71. if (cats.find(layer) != cats.end()) {
  72. G_debug(3, "v.digit.GetCategory(): layer=%d, cat=%d", layer, cats[layer]);
  73. return cats[layer];
  74. }
  75. return -1;
  76. }
  77. /**
  78. \brief Set max category number for layer
  79. \param layer layer number
  80. \param cats category number to be set
  81. \return previosly set category
  82. \return -1 if layer not available
  83. */
  84. int Digit::SetCategory(int layer, int cat)
  85. {
  86. int old_cat;
  87. if (cats.find(layer) != cats.end()) {
  88. old_cat = cats[layer];
  89. }
  90. else {
  91. old_cat = -1;
  92. }
  93. cats[layer] = cat;
  94. G_debug(3, "wxDigit.SetCategory(): layer=%d, cat=%d old_cat=%d",
  95. layer, cat, old_cat);
  96. return old_cat;
  97. }
  98. /**
  99. Get list of layers
  100. Requires InitCats() to be called.
  101. \return list of layers
  102. */
  103. std::vector<int> Digit::GetLayers()
  104. {
  105. std::vector<int> layers;
  106. for(std::map<int, int>::const_iterator b = cats.begin(), e = cats.end();
  107. b != e; ++b ) {
  108. layers.push_back(b->first);
  109. }
  110. return layers;
  111. }
  112. /**
  113. \brief Get list of layer/category(ies) for selected feature.
  114. \param line feature id (-1 for first selected feature)
  115. \return list of layer/cats
  116. */
  117. std::map<int, std::vector<int> > Digit::GetLineCats(int line_id)
  118. {
  119. std::map<int, std::vector<int> > lc;
  120. int line, n_dblinks;
  121. struct line_cats *Cats;
  122. struct field_info *fi;
  123. if (!display->mapInfo) {
  124. return lc;
  125. }
  126. if (line_id == -1 && display->selected->n_values < 1) {
  127. return lc;
  128. }
  129. line = line_id;
  130. if (line_id == -1) {
  131. line = display->selected->value[0];
  132. }
  133. if (!Vect_line_alive(display->mapInfo, line)) {
  134. return lc;
  135. }
  136. Cats = Vect_new_cats_struct();
  137. if (Vect_read_line(display->mapInfo, NULL, Cats, line) < 0) {
  138. Vect_destroy_cats_struct(Cats);
  139. return lc;
  140. }
  141. n_dblinks = Vect_get_num_dblinks(display->mapInfo);
  142. for (int dblink = 0; dblink < n_dblinks; dblink++) {
  143. fi = Vect_get_dblink(display->mapInfo, dblink);
  144. if (fi == NULL) {
  145. continue;
  146. }
  147. std::vector<int> cats;
  148. lc[fi->number] = cats;
  149. }
  150. for (int i = 0; i < Cats->n_cats; i++) {
  151. lc[Cats->field[i]].push_back(Cats->cat[i]);
  152. }
  153. Vect_destroy_cats_struct(Cats);
  154. return lc;
  155. }
  156. /**
  157. \brief Set categories for given feature/layer
  158. \param line feature id (-1 for first selected feature)
  159. \param layer layer number
  160. \param cats list of cats
  161. \param add True for add, False for delete
  162. \return new feature id (feature need to be rewritten)
  163. \return -1 on error
  164. */
  165. int Digit::SetLineCats(int line_id, int layer, std::vector<int> cats, bool add)
  166. {
  167. int line, ret, type;
  168. struct line_pnts *Points;
  169. struct line_cats *Cats;
  170. if (!display->mapInfo) {
  171. return -1;
  172. }
  173. if (line_id == -1 && display->selected->n_values < 1) {
  174. return -1;
  175. }
  176. line = -1;
  177. if (line_id == -1) {
  178. line = display->selected->value[0];
  179. }
  180. if (!Vect_line_alive(display->mapInfo, line)) {
  181. return -1;
  182. }
  183. Points = Vect_new_line_struct();
  184. Cats = Vect_new_cats_struct();
  185. type = Vect_read_line(display->mapInfo, Points, Cats, line);
  186. if (type < 0) {
  187. Vect_destroy_line_struct(Points);
  188. Vect_destroy_cats_struct(Cats);
  189. return -1;
  190. }
  191. for (std::vector<int>::const_iterator c = cats.begin(), e = cats.end();
  192. c != e; ++c) {
  193. if (add) {
  194. Vect_cat_set(Cats, layer, *c);
  195. }
  196. else {
  197. Vect_field_cat_del(Cats, layer, *c);
  198. }
  199. G_debug(3, "Digit.SetLineCats(): layer=%d, cat=%d, add=%d",
  200. layer, *c, add);
  201. }
  202. /* register changeset */
  203. AddActionToChangeset(changesets.size(), REWRITE, display->selected->value[0]);
  204. ret = Vect_rewrite_line(display->mapInfo, line, type,
  205. Points, Cats);
  206. if (ret > 0) {
  207. /* updates feature id (id is changed since line has been rewriten) */
  208. changesets[changesets.size()-1][0].line = ret;
  209. }
  210. else {
  211. changesets.erase(changesets.size()-1);
  212. }
  213. if (line_id == -1) {
  214. /* update line id since the line was rewritten */
  215. display->selected->value[0] = ret;
  216. }
  217. Vect_destroy_line_struct(Points);
  218. Vect_destroy_cats_struct(Cats);
  219. return ret;
  220. }
  221. /**
  222. \brief Copy categories from one vector feature to other
  223. \param cats list of layer/category to be copied
  224. \param ids list of line ids where to copy categories
  225. \return number of modified features
  226. \return -1 on error
  227. */
  228. int Digit::CopyCats(std::vector<std::vector<int> > cats, std::vector<int> ids)
  229. {
  230. /* TODO */
  231. return 0;
  232. }