Gv3.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  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. gln->type = OGSF_POLYGON;
  79. gln->npts = np = points->n_points;
  80. G_debug(3, " np = %d", np);
  81. if (is3d) {
  82. gln->dims = 3;
  83. gln->p3 = (Point3 *) G_calloc(np, sizeof(Point3)); /* G_fatal_error */
  84. if (!gln->p3) {
  85. return (NULL);
  86. }
  87. #ifdef TRAK_MEM
  88. Tot_mem += (np * sizeof(Point3));
  89. #endif
  90. }
  91. else {
  92. gln->dims = 2;
  93. gln->p2 = (Point2 *) G_calloc(np, sizeof(Point2)); /* G_fatal_error */
  94. if (!gln->p2) {
  95. return (NULL);
  96. }
  97. #ifdef TRAK_MEM
  98. Tot_mem += (np * sizeof(Point2));
  99. #endif
  100. }
  101. for (i = 0; i < np; i++) {
  102. if (is3d) {
  103. gln->p3[i][X] = points->x[i];
  104. gln->p3[i][Y] = points->y[i];
  105. gln->p3[i][Z] = points->z[i];
  106. }
  107. else {
  108. gln->p2[i][X] = points->x[i];
  109. gln->p2[i][Y] = points->y[i];
  110. }
  111. }
  112. /* Calc normal (should be average) */
  113. if (is3d) {
  114. vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
  115. vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
  116. vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
  117. vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
  118. vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
  119. vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
  120. GS_v3cross(vect[1], vect[0], gln->norm);
  121. }
  122. gln->cats = NULL;
  123. gln->next = (geoline *) G_malloc(sizeof(geoline)); /* G_fatal_error */
  124. if (!gln->next) {
  125. return (NULL);
  126. }
  127. #ifdef TRAK_MEM
  128. Tot_mem += sizeof(geoline);
  129. #endif
  130. prev = gln;
  131. gln = gln->next;
  132. nareas++;
  133. }
  134. G_debug(3, "%d areas loaded", nareas);
  135. /* Read all lines */
  136. G_debug(3, "Reading vector lines ...");
  137. while (-1 < (type = Vect_read_next_line(&map, points, Cats))) {
  138. G_debug(3, "line type = %d", type);
  139. if (type & (GV_LINES | GV_FACE)) {
  140. if (type & (GV_LINES)) {
  141. gln->type = OGSF_LINE;
  142. }
  143. else {
  144. gln->type = OGSF_POLYGON;
  145. /* Vect_append_point ( points, points->x[0], points->y[0], points->z[0] ); */
  146. }
  147. gln->npts = np = points->n_points;
  148. G_debug(3, " np = %d", np);
  149. if (is3d) {
  150. gln->dims = 3;
  151. gln->p3 = (Point3 *) G_calloc(np, sizeof(Point3)); /* G_fatal_error */
  152. if (!gln->p3) {
  153. return (NULL);
  154. }
  155. #ifdef TRAK_MEM
  156. Tot_mem += (np * sizeof(Point3));
  157. #endif
  158. }
  159. else {
  160. gln->dims = 2;
  161. gln->p2 = (Point2 *) G_calloc(np, sizeof(Point2)); /* G_fatal_error */
  162. if (!gln->p2) {
  163. return (NULL);
  164. }
  165. #ifdef TRAK_MEM
  166. Tot_mem += (np * sizeof(Point2));
  167. #endif
  168. }
  169. for (i = 0; i < np; i++) {
  170. if (is3d) {
  171. gln->p3[i][X] = points->x[i];
  172. gln->p3[i][Y] = points->y[i];
  173. gln->p3[i][Z] = points->z[i];
  174. }
  175. else {
  176. gln->p2[i][X] = points->x[i];
  177. gln->p2[i][Y] = points->y[i];
  178. }
  179. }
  180. /* Calc normal (should be average) */
  181. if (is3d && gln->type == OGSF_POLYGON) {
  182. vect[0][X] = (float)(gln->p3[0][X] - gln->p3[1][X]);
  183. vect[0][Y] = (float)(gln->p3[0][Y] - gln->p3[1][Y]);
  184. vect[0][Z] = (float)(gln->p3[0][Z] - gln->p3[1][Z]);
  185. vect[1][X] = (float)(gln->p3[2][X] - gln->p3[1][X]);
  186. vect[1][Y] = (float)(gln->p3[2][Y] - gln->p3[1][Y]);
  187. vect[1][Z] = (float)(gln->p3[2][Z] - gln->p3[1][Z]);
  188. GS_v3cross(vect[1], vect[0], gln->norm);
  189. G_debug(3, "norm %f %f %f", gln->norm[0], gln->norm[1],
  190. gln->norm[2]);
  191. }
  192. /* Store category info for thematic display */
  193. if (Cats->n_cats > 0) {
  194. gln->cats = Cats;
  195. Cats = Vect_new_cats_struct();
  196. }
  197. else {
  198. gln->cats = NULL;
  199. Vect_reset_cats(Cats);
  200. }
  201. gln->next = (geoline *) G_malloc(sizeof(geoline)); /* G_fatal_error */
  202. if (!gln->next) {
  203. return (NULL);
  204. }
  205. #ifdef TRAK_MEM
  206. Tot_mem += sizeof(geoline);
  207. #endif
  208. prev = gln;
  209. gln = gln->next;
  210. nl++;
  211. }
  212. }
  213. G_debug(3, "%d lines loaded", nl);
  214. nl += nareas;
  215. prev->next = NULL;
  216. G_free(gln);
  217. #ifdef TRAK_MEM
  218. Tot_mem -= sizeof(geoline);
  219. #endif
  220. Vect_close(&map);
  221. if (!nl) {
  222. G_warning(_("No features from vector map <%s> fall within current region"),
  223. G_fully_qualified_name(grassname, mapset));
  224. return (NULL);
  225. }
  226. else {
  227. G_message(_("Vector map <%s> loaded (%d features)"),
  228. G_fully_qualified_name(grassname, mapset), nl);
  229. }
  230. *nlines = nl;
  231. #ifdef TRAK_MEM
  232. G_debug(3, "Total vect memory = %d Kbytes", Tot_mem / 1000);
  233. #endif
  234. return (top);
  235. }
  236. /*!
  237. \brief Tracking memory
  238. \param minus mimus number
  239. */
  240. void sub_Vectmem(int minus)
  241. {
  242. G_debug(5, "sub_Vectmem(): minus=%d", minus);
  243. #ifdef TRAK_MEM
  244. {
  245. Tot_mem -= minus;
  246. }
  247. #endif
  248. return;
  249. }
  250. /*!
  251. \brief Load styles for geolines based on thematic mapping
  252. \param gv pointer to geovect structure
  253. \param colors pointer to Colors structure or NULL
  254. \return number of features defined by thematic mapping
  255. \return -1 on error
  256. */
  257. int Gv_load_vect_thematic(geovect *gv, struct Colors *colors)
  258. {
  259. geoline *gvt;
  260. struct Map_info Map;
  261. struct field_info *Fi;
  262. int nvals, cat, nlines, nskipped;
  263. int red, blu, grn;
  264. const char *str;
  265. const char *mapset;
  266. dbDriver *driver;
  267. dbValue value;
  268. if(!gv || !gv->tstyle || !gv->filename)
  269. return -1;
  270. mapset = G_find_vector2(gv->filename, "");
  271. if (!mapset) {
  272. G_fatal_error(_("Vector map <%s> not found"), gv->filename);
  273. }
  274. Vect_set_open_level(1);
  275. if (Vect_open_old(&Map, gv->filename, "") == -1) {
  276. G_fatal_error(_("Unable to open vector map <%s>"),
  277. G_fully_qualified_name(gv->filename, mapset));
  278. }
  279. Fi = Vect_get_field(&Map, gv->tstyle->layer);
  280. if (!Fi) {
  281. G_warning(_("Database connection not defined for layer %d"),
  282. gv->tstyle->layer);
  283. }
  284. else {
  285. driver = db_start_driver_open_database(Fi->driver, Fi->database);
  286. if (!driver)
  287. G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
  288. Fi->database, Fi->driver);
  289. }
  290. G_message(_("Loading thematic vector layer <%s>..."),
  291. G_fully_qualified_name(gv->filename, mapset));
  292. nlines = nskipped = 0;
  293. for(gvt = gv->lines; gvt; gvt = gvt->next) {
  294. gvt->style = (gvstyle *) G_malloc(sizeof(gvstyle));
  295. G_zero(gvt->style, sizeof(gvstyle));
  296. /* use default style */
  297. gvt->style->color = gv->style->color;
  298. gvt->style->symbol = gv->style->symbol;
  299. gvt->style->size = gv->style->size;
  300. gvt->style->width = gv->style->width;
  301. cat = -1;
  302. if (gvt->cats)
  303. Vect_cat_get(gvt->cats, gv->tstyle->layer, &cat);
  304. if (cat < 0) {
  305. nskipped++;
  306. continue;
  307. }
  308. /* color */
  309. if (colors) {
  310. if (!Rast_get_c_color((const CELL *) &cat, &red, &grn, &blu, colors)) {
  311. G_warning(_("No color rule defined for category %d"), cat);
  312. gvt->style->color = gv->style->color;
  313. }
  314. gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
  315. ((int)((blu) << 16) & BLU_MASK);
  316. }
  317. if (gv->tstyle->color_column) {
  318. nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->color_column, &value);
  319. if (nvals < 1)
  320. continue;
  321. str = db_get_value_string(&value);
  322. if (!str)
  323. continue;
  324. if (G_str_to_color(str, &red, &grn, &blu) != 1) {
  325. G_warning(_("Invalid color definition (%s)"),
  326. str);
  327. gvt->style->color = gv->style->color;
  328. }
  329. else {
  330. gvt->style->color = (red & RED_MASK) + ((int)((grn) << 8) & GRN_MASK) +
  331. ((int)((blu) << 16) & BLU_MASK);
  332. }
  333. }
  334. /* width */
  335. if (gv->tstyle->width_column) {
  336. nvals = db_select_value(driver, Fi->table, Fi->key, cat, gv->tstyle->width_column, &value);
  337. if (nvals < 1)
  338. continue;
  339. gvt->style->width = db_get_value_int(&value);
  340. }
  341. nlines++;
  342. }
  343. if (nskipped > 0)
  344. G_warning(_("%d features without category. "
  345. "Unable to determine color rules for features without category."),
  346. nskipped);
  347. return nlines;
  348. }