gv3.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /*!
  2. \file lib/ogsf/gv3.c
  3. \brief OGSF library - loading vector sets (lower level functions)
  4. GRASS OpenGL gsurf OGSF Library
  5. (C) 1999-2008, 2011 by the GRASS Development Team
  6. This program is free software under the GNU General Public License
  7. (>=v2). Read the file COPYING that comes with GRASS for details.
  8. \author Bill Brown USACERL (December 1993)
  9. \author Updated by Martin Landa <landa.martin gmail.com>
  10. (doxygenized in May 2008, thematic mapping in August 2011)
  11. */
  12. #include <stdlib.h>
  13. #include <grass/gis.h>
  14. #include <grass/colors.h>
  15. #include <grass/raster.h>
  16. #include <grass/vector.h>
  17. #include <grass/dbmi.h>
  18. #include <grass/glocale.h>
  19. #include <grass/ogsf.h>
  20. /*
  21. #define TRAK_MEM
  22. */
  23. #ifdef TRAK_MEM
  24. static int Tot_mem = 0;
  25. #endif
  26. /*!
  27. \brief Load vector map to memory
  28. The other alternative may be to load to a tmp file
  29. \param grassname vector map name
  30. \param[out] number of loaded features
  31. \return pointer to geoline struct
  32. \return NULL on failure
  33. */
  34. geoline *Gv_load_vect(const char *grassname, int *nlines)
  35. {
  36. struct Map_info map;
  37. struct line_pnts *points;
  38. struct line_cats *Cats = NULL;
  39. geoline *top, *gln, *prev;
  40. int np, i, n, nareas, nl = 0, area, type, is3d;
  41. struct Cell_head wind;
  42. float vect[2][3];
  43. const char *mapset;
  44. mapset = G_find_vector2(grassname, "");
  45. if (!mapset) {
  46. G_warning(_("Vector map <%s> not found"), grassname);
  47. return NULL;
  48. }
  49. Vect_set_open_level(2);
  50. if (Vect_open_old(&map, grassname, "") == -1) {
  51. G_warning(_("Unable to open vector map <%s>"),
  52. G_fully_qualified_name(grassname, mapset));
  53. return NULL;
  54. }
  55. top = gln = (geoline *) G_malloc(sizeof(geoline)); /* G_fatal_error */
  56. if (!top) {
  57. return NULL;
  58. }
  59. prev = top;
  60. #ifdef TRAK_MEM
  61. Tot_mem += sizeof(geoline);
  62. #endif
  63. points = Vect_new_line_struct();
  64. Cats = Vect_new_cats_struct();
  65. G_get_set_window(&wind);
  66. Vect_set_constraint_region(&map, wind.north, wind.south, wind.east,
  67. wind.west, PORT_DOUBLE_MAX, -PORT_DOUBLE_MAX);
  68. is3d = Vect_is_3d(&map);
  69. /* Read areas */
  70. n = Vect_get_num_areas(&map);
  71. nareas = 0;
  72. G_debug(3, "Reading vector areas (nareas = %d)", n);
  73. for (area = 1; area <= n; area++) {
  74. G_debug(3, " area %d", area);
  75. Vect_get_area_points(&map, area, points);
  76. if (points->n_points < 3)
  77. continue;
  78. /* initialize style */
  79. gln->highlighted = 0;
  80. gln->type = OGSF_POLYGON;
  81. gln->npts = np = points->n_points;
  82. G_debug(3, " np = %d", np);
  83. if (is3d) {
  84. gln->dims = 3;
  85. gln->p3 = (Point3 *) G_calloc(np, sizeof(Point3)); /* G_fatal_error */
  86. if (!gln->p3) {
  87. return (NULL);
  88. }
  89. #ifdef TRAK_MEM
  90. Tot_mem += (np * sizeof(Point3));
  91. #endif
  92. }
  93. else {
  94. gln->dims = 2;
  95. gln->p2 = (Point2 *) G_calloc(np, sizeof(Point2)); /* G_fatal_error */
  96. if (!gln->p2) {
  97. return (NULL);
  98. }
  99. #ifdef TRAK_MEM
  100. Tot_mem += (np * sizeof(Point2));
  101. #endif
  102. }
  103. for (i = 0; i < np; i++) {
  104. if (is3d) {
  105. gln->p3[i][X] = points->x[i];
  106. gln->p3[i][Y] = points->y[i];
  107. gln->p3[i][Z] = points->z[i];
  108. }
  109. else {
  110. gln->p2[i][X] = points->x[i];
  111. gln->p2[i][Y] = points->y[i];
  112. }
  113. }
  114. /* Calc normal (should be average) */
  115. if (is3d) {
  116. vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
  117. vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
  118. vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
  119. vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
  120. vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
  121. vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
  122. GS_v3cross(vect[1], vect[0], gln->norm);
  123. }
  124. gln->cats = NULL;
  125. gln->next = (geoline *) G_malloc(sizeof(geoline)); /* G_fatal_error */
  126. if (!gln->next) {
  127. return (NULL);
  128. }
  129. #ifdef TRAK_MEM
  130. Tot_mem += sizeof(geoline);
  131. #endif
  132. prev = gln;
  133. gln = gln->next;
  134. nareas++;
  135. }
  136. G_debug(3, "%d areas loaded", nareas);
  137. /* Read all lines */
  138. G_debug(3, "Reading vector lines ...");
  139. while (-1 < (type = Vect_read_next_line(&map, points, Cats))) {
  140. G_debug(3, "line type = %d", type);
  141. if (type & (GV_LINES | GV_FACE)) {
  142. if (type & (GV_LINES)) {
  143. gln->type = OGSF_LINE;
  144. }
  145. else {
  146. gln->type = OGSF_POLYGON;
  147. /* Vect_append_point ( points, points->x[0], points->y[0], points->z[0] ); */
  148. }
  149. /* initialize style */
  150. gln->highlighted = 0;
  151. gln->npts = np = points->n_points;
  152. G_debug(3, " np = %d", np);
  153. if (is3d) {
  154. gln->dims = 3;
  155. gln->p3 = (Point3 *) G_calloc(np, sizeof(Point3)); /* G_fatal_error */
  156. if (!gln->p3) {
  157. return (NULL);
  158. }
  159. #ifdef TRAK_MEM
  160. Tot_mem += (np * sizeof(Point3));
  161. #endif
  162. }
  163. else {
  164. gln->dims = 2;
  165. gln->p2 = (Point2 *) G_calloc(np, sizeof(Point2)); /* G_fatal_error */
  166. if (!gln->p2) {
  167. return (NULL);
  168. }
  169. #ifdef TRAK_MEM
  170. Tot_mem += (np * sizeof(Point2));
  171. #endif
  172. }
  173. for (i = 0; i < np; i++) {
  174. if (is3d) {
  175. gln->p3[i][X] = points->x[i];
  176. gln->p3[i][Y] = points->y[i];
  177. gln->p3[i][Z] = points->z[i];
  178. }
  179. else {
  180. gln->p2[i][X] = points->x[i];
  181. gln->p2[i][Y] = points->y[i];
  182. }
  183. }
  184. /* Calc normal (should be average) */
  185. if (is3d && gln->type == OGSF_POLYGON) {
  186. vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
  187. vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
  188. vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
  189. vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
  190. vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
  191. vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
  192. GS_v3cross(vect[1], vect[0], gln->norm);
  193. G_debug(3, "norm %f %f %f", gln->norm[0], gln->norm[1],
  194. gln->norm[2]);
  195. }
  196. /* Store category info for thematic display */
  197. if (Cats->n_cats > 0) {
  198. gln->cats = Cats;
  199. Cats = Vect_new_cats_struct();
  200. }
  201. else {
  202. gln->cats = NULL;
  203. Vect_reset_cats(Cats);
  204. }
  205. gln->next = (geoline *) G_malloc(sizeof(geoline)); /* G_fatal_error */
  206. if (!gln->next) {
  207. return (NULL);
  208. }
  209. #ifdef TRAK_MEM
  210. Tot_mem += sizeof(geoline);
  211. #endif
  212. prev = gln;
  213. gln = gln->next;
  214. nl++;
  215. }
  216. }
  217. G_debug(3, "%d lines loaded", nl);
  218. nl += nareas;
  219. prev->next = NULL;
  220. G_free(gln);
  221. #ifdef TRAK_MEM
  222. Tot_mem -= sizeof(geoline);
  223. #endif
  224. Vect_close(&map);
  225. if (!nl) {
  226. G_warning(_("No features from vector map <%s> fall within current region"),
  227. G_fully_qualified_name(grassname, mapset));
  228. return (NULL);
  229. }
  230. else {
  231. G_message(_("Vector map <%s> loaded (%d features)"),
  232. G_fully_qualified_name(grassname, mapset), nl);
  233. }
  234. *nlines = nl;
  235. #ifdef TRAK_MEM
  236. G_debug(3, "Total vect memory = %d Kbytes", Tot_mem / 1000);
  237. #endif
  238. return (top);
  239. }
  240. /*!
  241. \brief Tracking memory
  242. \param minus mimus number
  243. */
  244. void sub_Vectmem(int minus)
  245. {
  246. G_debug(5, "sub_Vectmem(): minus=%d", minus);
  247. #ifdef TRAK_MEM
  248. {
  249. Tot_mem -= minus;
  250. }
  251. #endif
  252. return;
  253. }
  254. /*!
  255. \brief Load styles for geolines based on thematic mapping
  256. \param gv pointer to geovect structure
  257. \param colors pointer to Colors structure or NULL
  258. \return number of features defined by thematic mapping
  259. \return -1 on error
  260. */
  261. int Gv_load_vect_thematic(geovect *gv, struct Colors *colors)
  262. {
  263. geoline *gvt;
  264. struct Map_info Map;
  265. struct field_info *Fi;
  266. int nvals, cat, nlines, nskipped;
  267. int red, blu, grn;
  268. const char *str;
  269. const char *mapset;
  270. dbDriver *driver;
  271. dbValue value;
  272. if(!gv || !gv->tstyle || !gv->filename)
  273. return -1;
  274. mapset = G_find_vector2(gv->filename, "");
  275. if (!mapset) {
  276. G_fatal_error(_("Vector map <%s> not found"), gv->filename);
  277. }
  278. Vect_set_open_level(1);
  279. if (Vect_open_old(&Map, gv->filename, "") == -1) {
  280. G_fatal_error(_("Unable to open vector map <%s>"),
  281. G_fully_qualified_name(gv->filename, mapset));
  282. }
  283. Fi = Vect_get_field(&Map, gv->tstyle->layer);
  284. if (!Fi) {
  285. G_warning(_("Database connection not defined for layer %d"),
  286. gv->tstyle->layer);
  287. }
  288. else {
  289. driver = db_start_driver_open_database(Fi->driver, Fi->database);
  290. if (!driver)
  291. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  292. Fi->database, Fi->driver);
  293. }
  294. G_message(_("Loading thematic vector layer <%s>..."),
  295. G_fully_qualified_name(gv->filename, mapset));
  296. nlines = nskipped = 0;
  297. for(gvt = gv->lines; gvt; gvt = gvt->next) {
  298. gvt->style = (gvstyle *) G_malloc(sizeof(gvstyle));
  299. G_zero(gvt->style, sizeof(gvstyle));
  300. /* use default style */
  301. gvt->style->color = gv->style->color;
  302. gvt->style->symbol = gv->style->symbol;
  303. gvt->style->size = gv->style->size;
  304. gvt->style->width = gv->style->width;
  305. cat = -1;
  306. if (gvt->cats)
  307. Vect_cat_get(gvt->cats, gv->tstyle->layer, &cat);
  308. if (cat < 0) {
  309. nskipped++;
  310. continue;
  311. }
  312. /* color */
  313. if (colors) {
  314. if (!Rast_get_c_color((const CELL *) &cat, &red, &grn, &blu, colors)) {
  315. G_warning(_("No color rule defined for category %d"), cat);
  316. gvt->style->color = gv->style->color;
  317. }
  318. gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
  319. ((int)((blu) << 16) & BLU_MASK);
  320. }
  321. if (gv->tstyle->color_column) {
  322. nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->color_column, &value);
  323. if (nvals < 1)
  324. continue;
  325. str = db_get_value_string(&value);
  326. if (!str)
  327. continue;
  328. if (G_str_to_color(str, &red, &grn, &blu) != 1) {
  329. G_warning(_("Invalid color definition (%s)"),
  330. str);
  331. gvt->style->color = gv->style->color;
  332. }
  333. else {
  334. gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
  335. ((int)((blu) << 16) & BLU_MASK);
  336. }
  337. }
  338. /* width */
  339. if (gv->tstyle->width_column) {
  340. nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->width_column, &value);
  341. if (nvals < 1)
  342. continue;
  343. gvt->style->width = db_get_value_int(&value);
  344. }
  345. nlines++;
  346. }
  347. if (nskipped > 0)
  348. G_warning(_("%d features without category. "
  349. "Unable to determine color rules for features without category."),
  350. nskipped);
  351. return nlines;
  352. }