1 /*!
2    \file lib/vector/Vlib/header.c
3 
4    \brief Vector library - header manipulation
5 
6    Higher level functions for reading/writing/manipulating vectors.
7 
8    (C) 2001-2010 by the GRASS Development Team
9 
10    This program is free software under the GNU General Public License
11    (>=v2). Read the file COPYING that comes with GRASS for details.
12 
13    \author Original author CERL, probably Dave Gerdes or Mike Higgins.
14    \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
15    \author Update to GRASS 7 (OGR support) by Martin Landa <landa.martin gmail.com>
16  */
17 
18 #include <stdlib.h>
19 #include <string.h>
20 #include <grass/vector.h>
21 #include <grass/glocale.h>
22 
23 #include "local_proto.h"
24 
25 /*!
26    \brief Print vector map header to stdout
27 
28    \param Map pointer to Map_info structure
29 
30    \return 0 on success
31 */
Vect_print_header(const struct Map_info * Map)32 int Vect_print_header(const struct Map_info *Map)
33 {
34     fprintf(stdout, "\nSelected information from dig header\n");
35     fprintf(stdout, " Organization:  %s\n", Vect_get_organization(Map));
36     fprintf(stdout, " Map Name:      %s\n", Vect_get_map_name(Map));
37     fprintf(stdout, " Source Date:   %s\n", Vect_get_map_date(Map));
38     fprintf(stdout, " Orig. Scale:   %d\n", Vect_get_scale(Map));
39 
40     return 0;
41 }
42 
43 /*!
44    \brief Read vector map header from map head file
45 
46    \param Map pointrt to Map_info structure
47 
48    \return 0
49 */
Vect_read_header(struct Map_info * Map)50 int Vect_read_header(struct Map_info *Map)
51 {
52     Vect__read_head(Map);
53     return 0;
54 }
55 
56 /*!
57    \brief Write vector map header to map head file
58 
59    \param Map pointer to Map_info structure
60 
61    \return 0
62 */
Vect_write_header(const struct Map_info * Map)63 int Vect_write_header(const struct Map_info *Map)
64 {
65     /* do some sanity checking here */
66     Vect__write_head(Map);
67     return 0;
68 }
69 
70 /*!
71    \brief Writes head information to text file (GV_HEAD_ELEMENT)
72 
73    \param Map pointer to Map_info structure
74 
75    \return 0 on success
76    \return -1 on error
77  */
Vect__write_head(const struct Map_info * Map)78 int Vect__write_head(const struct Map_info *Map)
79 {
80     char path[GPATH_MAX];
81     FILE *head_fp;
82 
83     Vect__get_path(path, Map);
84     head_fp = G_fopen_new(path, GV_HEAD_ELEMENT);
85     if (head_fp == NULL) {
86 	G_warning(_("Unable to create header file for vector map <%s>"),
87 		  Vect_get_full_name(Map));
88 	return -1;
89     }
90 
91     fprintf(head_fp, "ORGANIZATION: %s\n", Vect_get_organization(Map));
92     fprintf(head_fp, "DIGIT DATE:   %s\n", Vect_get_date(Map));
93     fprintf(head_fp, "DIGIT NAME:   %s\n", Vect_get_person(Map));
94     fprintf(head_fp, "MAP NAME:     %s\n", Vect_get_map_name(Map));
95     fprintf(head_fp, "MAP DATE:     %s\n", Vect_get_map_date(Map));
96     fprintf(head_fp, "MAP SCALE:    %d\n", Vect_get_scale(Map));
97     fprintf(head_fp, "OTHER INFO:   %s\n", Vect_get_comment(Map));
98     if (Vect_get_proj(Map) > 0)
99 	fprintf(head_fp, "PROJ:         %d\n", Vect_get_proj(Map));
100     fprintf(head_fp, "ZONE:         %d\n", Vect_get_zone(Map));
101     fprintf(head_fp, "MAP THRESH:   %f\n", Vect_get_thresh(Map));
102 
103     fclose(head_fp);
104 
105     return 0;
106 }
107 
108 /*!
109    \brief Reads head information from text file (GV_HEAD_ELEMENT) - for internal use only
110 
111    \param Map pointer to Map_info structure
112 
113    \return 0 on success
114    \return -1 on error
115  */
Vect__read_head(struct Map_info * Map)116 int Vect__read_head(struct Map_info *Map)
117 {
118     FILE *head_fp;
119     char buff[2000];
120     char path[GPATH_MAX], *ptr;
121 
122     /* Reset / init */
123     Vect__init_head(Map);
124 
125     G_debug(1, "Vect__read_head(): vector = %s@%s", Map->name, Map->mapset);
126     Vect__get_path(path, Map);
127     head_fp = G_fopen_old(path, GV_HEAD_ELEMENT, Map->mapset);
128     if (head_fp == NULL) {
129 	G_warning(_("Unable to open header file of vector <%s>"),
130 		  Vect_get_full_name(Map));
131 	return -1;
132     }
133 
134     while (G_getl2(buff, 2000, head_fp)) {
135 
136 	if (!(ptr = strchr(buff, ':'))) {
137 	    G_warning(_("Corrupted row in head: %s"), buff);
138 	    continue;
139 	}
140 
141 	ptr++;			/* Search for the start of text */
142 	while (*ptr == ' ')
143 	    ptr++;
144 
145 	if (strncmp(buff, "ORGANIZATION:", sizeof(char) * 13) == 0)
146 	    Vect_set_organization(Map, ptr);
147 	else if (strncmp(buff, "DIGIT DATE:", sizeof(char) * 11) == 0)
148 	    Vect_set_date(Map, ptr);
149 	else if (strncmp(buff, "DIGIT NAME:", sizeof(char) * 11) == 0)
150 	    Vect_set_person(Map, ptr);
151 	else if (strncmp(buff, "MAP NAME:", sizeof(char) * 9) == 0)
152 	    Vect_set_map_name(Map, ptr);
153 	else if (strncmp(buff, "MAP DATE:", sizeof(char) * 9) == 0)
154 	    Vect_set_map_date(Map, ptr);
155 	else if (strncmp(buff, "MAP SCALE:", sizeof(char) * 10) == 0)
156 	    Vect_set_scale(Map, atoi(ptr));
157 	else if (strncmp(buff, "OTHER INFO:", sizeof(char) * 11) == 0)
158 	    Vect_set_comment(Map, ptr);
159 	else if (strncmp(buff, "PROJ:", sizeof(char) * 5) == 0)
160 	    Vect_set_proj(Map, atoi(ptr));
161 	else if (strncmp(buff, "ZONE:", sizeof(char) * 5) == 0 ||
162 		 strncmp(buff, "UTM ZONE:", sizeof(char) * 9) == 0)
163 	    Vect_set_zone(Map, atoi(ptr));
164 	else if (strncmp(buff, "WEST EDGE:", sizeof(char) * 10) == 0) {
165 	}
166 	else if (strncmp(buff, "EAST EDGE:", sizeof(char) * 10) == 0) {
167 	}
168 	else if (strncmp(buff, "SOUTH EDGE:", sizeof(char) * 11) == 0) {
169 	}
170 	else if (strncmp(buff, "NORTH EDGE:", sizeof(char) * 11) == 0) {
171 	}
172 	else if (strncmp(buff, "MAP THRESH:", sizeof(char) * 11) == 0)
173 	    Vect_set_thresh(Map, atof(ptr));
174 	else
175 	    G_warning(_("Unknown keyword '%s' in vector head"), buff);
176     }
177 
178     fclose(head_fp);
179 
180     return 0;
181 }
182 
183 /*!
184    \brief Get name of vector map
185 
186    \param Map pointer to Map_info structure
187 
188    \return string containing name
189 */
Vect_get_name(const struct Map_info * Map)190 const char *Vect_get_name(const struct Map_info *Map)
191 {
192     return Map->name;
193 }
194 
195 /*!
196    \brief Get name of mapset where vector map lives
197 
198    \param Map pointer to Map_info structure
199 
200    \return string containing mapset name
201 */
Vect_get_mapset(const struct Map_info * Map)202 const char *Vect_get_mapset(const struct Map_info *Map)
203 {
204     return Map->mapset;
205 }
206 
207 /*!
208   \brief Get fully qualified name of vector map
209 
210   - for GV_FORMAT_NATIVE and GV_FORMAT_OGR returns "map@mapset"
211   - for GV_FORMAT_OGR_DIRECT returns "layer@datasourse"
212 
213   Allocated string should be freed by G_free().
214 
215   \param Map pointer to Map_info structure
216 
217   \return allocated string "name@mapset"
218  */
Vect_get_full_name(const struct Map_info * Map)219 const char *Vect_get_full_name(const struct Map_info *Map)
220 {
221     char *ptr;
222 
223     if (Map->format == GV_FORMAT_OGR_DIRECT &&
224 	Map->fInfo.ogr.dsn &&
225 	Map->fInfo.ogr.layer_name) {
226 	ptr = (char *) G_malloc(strlen(Map->fInfo.ogr.layer_name) +
227 				strlen(Map->fInfo.ogr.dsn) + 2);
228 	sprintf(ptr, "%s@%s", Map->fInfo.ogr.layer_name,
229 		Map->fInfo.ogr.dsn);
230 
231 	return ptr;
232     }
233 
234     ptr = (char *) G_malloc(strlen(Map->name) + strlen(Map->mapset) + 2);
235     if (strlen(Map->mapset) > 0) {
236 	sprintf(ptr, "%s@%s", Map->name, Map->mapset);
237     }
238     else {
239 	sprintf(ptr, "%s", Map->name);
240     }
241 
242     return ptr;
243 }
244 
245 /*!
246    \brief Check if vector map is 3D
247 
248    Check vector map header.
249 
250    \param Map pointer to Map_info structure
251 
252    \return TRUE  vector map is 3D
253    \return FALSE vector map is not 3D
254  */
Vect_is_3d(const struct Map_info * Map)255 int Vect_is_3d(const struct Map_info *Map)
256 {
257     return Map->head.with_z;
258 }
259 
260 /*!
261    \brief Set organization string in map header
262 
263    \param Map pointer to Map_info structure
264    \param str organization name
265 
266    \return 0
267 */
Vect_set_organization(struct Map_info * Map,const char * str)268 int Vect_set_organization(struct Map_info *Map, const char *str)
269 {
270     G_free(Map->head.organization);
271     Map->head.organization = G_store(str);
272 
273     return 0;
274 }
275 
276 /*!
277    \brief Get organization string from map header
278 
279    \param Map pointer to Map_info structure
280 
281    \return string containing organization name
282  */
Vect_get_organization(const struct Map_info * Map)283 const char *Vect_get_organization(const struct Map_info *Map)
284 {
285     return Map->head.organization;
286 }
287 
288 /*!
289    \brief Set date of digitization in map header
290 
291    \todo This should be coupled to DateTime functions to support
292    time series
293 
294    \param Map pointer to Map_info structure
295    \param str date given as string
296 
297    \return 0
298 */
Vect_set_date(struct Map_info * Map,const char * str)299 int Vect_set_date(struct Map_info *Map, const char *str)
300 {
301     G_free(Map->head.date);
302     Map->head.date = G_store(str);
303 
304     return 0;
305 }
306 
307 /*!
308    \brief Get date of digitization from map header
309 
310    \param Map pointer to Map_info structure
311 
312    \return date of digitization string
313  */
Vect_get_date(const struct Map_info * Map)314 const char *Vect_get_date(const struct Map_info *Map)
315 {
316     return (Map->head.date);
317 }
318 
319 /*!
320    \brief Set name of user who digitized the map in map header
321 
322    \param Map pointer to Map_info structure
323    \param str user name
324 
325    \return 0
326 */
Vect_set_person(struct Map_info * Map,const char * str)327 int Vect_set_person(struct Map_info *Map, const char *str)
328 {
329     G_free(Map->head.user_name);
330     Map->head.user_name = G_store(str);
331 
332     return 0;
333 }
334 
335 /*!
336    \brief Get user name string who digitized the map from map header
337 
338    \param Map pointer to Map_info structure
339 
340    \return string containing user name
341  */
Vect_get_person(const struct Map_info * Map)342 const char *Vect_get_person(const struct Map_info *Map)
343 {
344     return (Map->head.user_name);
345 }
346 
347 /*!
348    \brief Set map name in map header
349 
350    \param Map pointer to Map_info structure
351    \param str map name to be set
352 
353    \return 0
354  */
Vect_set_map_name(struct Map_info * Map,const char * str)355 int Vect_set_map_name(struct Map_info *Map, const char *str)
356 {
357     G_free(Map->head.map_name);
358     Map->head.map_name = G_store(str);
359 
360     return 0;
361 }
362 
363 /*!
364    \brief Get map name from map header
365 
366    \param Map pointer to Map_info structure
367 
368    \return string containing map name
369 */
Vect_get_map_name(const struct Map_info * Map)370 const char *Vect_get_map_name(const struct Map_info *Map)
371 {
372     return Map->head.map_name;
373 }
374 
375 /*!
376    \brief Set date when the source map was originally produced in map header
377 
378    \param Map pointer to Map_info structure
379    \param str date given as a string
380 
381    \return 0
382  */
Vect_set_map_date(struct Map_info * Map,const char * str)383 int Vect_set_map_date(struct Map_info *Map, const char *str)
384 {
385     G_free(Map->head.source_date);
386     Map->head.source_date = G_store(str);
387 
388     return 0;
389 }
390 
391 /*!
392    \brief Get date when the source map was originally produced from map header
393 
394    \param Map pointer to Map_info structure
395 
396    \return string containing a date
397  */
Vect_get_map_date(const struct Map_info * Map)398 const char *Vect_get_map_date(const struct Map_info *Map)
399 {
400     return Map->head.source_date;
401 }
402 
403 /*!
404    \brief Set map scale in map header
405 
406    \param Map pointer to Map_info structure
407    \param scale map scale
408 
409    \return 0
410  */
Vect_set_scale(struct Map_info * Map,int scale)411 int Vect_set_scale(struct Map_info *Map, int scale)
412 {
413     Map->head.orig_scale = scale;
414 
415     return 0;
416 }
417 
418 /*!
419    \brief Get map scale from map header
420 
421    \param Map pointer to Map_info structure
422 
423    \return map scale
424  */
Vect_get_scale(const struct Map_info * Map)425 int Vect_get_scale(const struct Map_info *Map)
426 {
427     return (int) Map->head.orig_scale;
428 }
429 
430 /*!
431    \brief Set comment or other info string in map header
432 
433    \param Map pointer to Map_info structure
434    \param str comment or other info string
435 
436    \return 0
437  */
Vect_set_comment(struct Map_info * Map,const char * str)438 int Vect_set_comment(struct Map_info *Map, const char *str)
439 {
440     G_free(Map->head.comment);
441     Map->head.comment = G_store(str);
442 
443     return 0;
444 }
445 
446 /*!
447    \brief Get comment or other info string from map header
448 
449    \param Map pointer to Map_info structure
450 
451    \return comment or other info string
452  */
Vect_get_comment(const struct Map_info * Map)453 const char *Vect_get_comment(const struct Map_info *Map)
454 {
455     return (Map->head.comment);
456 }
457 
458 /*!
459    \brief Set projection zone in map header
460 
461    \param Map pointer to Map_info structure
462    \param zone projection zone
463 
464    \return 0
465  */
Vect_set_zone(struct Map_info * Map,int zone)466 int Vect_set_zone(struct Map_info *Map, int zone)
467 {
468     Map->head.plani_zone = zone;
469 
470     return 0;
471 }
472 
473 /*!
474    \brief Get projection zone from map header
475 
476    \param Map pointer to Map_info structure
477 
478    \return projection zone
479  */
Vect_get_zone(const struct Map_info * Map)480 int Vect_get_zone(const struct Map_info *Map)
481 {
482     /* return Map->head.plani_zone; */
483 
484     /* use utm zone of current location,
485      * a vector in a given location can not be in a different CRS */
486     return G_zone();
487 }
488 
489 /*!
490    \brief Set projection in map header
491 
492    Supported projections:
493     - PROJECTION_XY  0 - x,y (Raw imagery),
494     - PROJECTION_UTM 1 - UTM   Universal Transverse Mercator,
495     - PROJECTION_LL  3 - Latitude-Longitude
496 
497    \param Map pointer to Map_info structure
498    \param proj projection code
499 
500    \return 0
501  */
Vect_set_proj(struct Map_info * Map,int proj)502 int Vect_set_proj(struct Map_info *Map, int proj)
503 {
504     Map->head.proj = proj;
505 
506     return 0;
507 }
508 
509 /*!
510    \brief Get projection from map header
511 
512    \param Map pointer to Map_info structure
513 
514    \return PROJECTION_XY  0 - x,y (Raw imagery),
515    \return PROJECTION_UTM 1 - UTM   Universal Transverse Mercator,
516    \return PROJECTION_LL  3 - Latitude-Longitude
517 */
Vect_get_proj(const struct Map_info * Map)518 int Vect_get_proj(const struct Map_info *Map)
519 {
520     return (Map->head.proj);
521 }
522 
523 /*!
524    \brief Query cartographic projection name of pointer to Map_info structure
525 
526    Returns a pointer to a string which is a printable name for
527    projection code <em>proj</em> (as returned by Vect_get_proj()).
528 
529    \param Map pointer to Map_info structure
530 
531    \return allocated string containing projection name
532    \return NULL if <em>proj</em> is not a valid projection
533  */
534 
Vect_get_proj_name(const struct Map_info * Map)535 const char *Vect_get_proj_name(const struct Map_info *Map)
536 {
537     char name[256];
538     int n;
539 
540     switch (n = Vect_get_proj(Map)) {
541     case PROJECTION_XY:
542     case PROJECTION_UTM:
543     case PROJECTION_LL:
544 	return G_projection_name(n);
545     case PROJECTION_OTHER:
546 	/* this won't protect against differing "other" projections, so
547 	   better to just include P_OTHER in the above list so we return the
548 	   strictly more correct, but less nice, string: "Other projection" ? */
549 	return G_database_projection_name();
550     default:
551 	G_debug(1, "Vect_get_proj_name(): "
552 		   "Vect_get_proj() returned an invalid result (%d)", n);
553 	break;
554     }
555 
556     strcpy(name, _("Unknown projection"));
557     return G_store(name);
558 }
559 
560 /*!
561    \brief Set threshold used for digitization in map header
562 
563    \param Map pointer to Map_info structure
564    \param thresh threshold used for digitization
565 
566    \return 0
567  */
Vect_set_thresh(struct Map_info * Map,double thresh)568 int Vect_set_thresh(struct Map_info *Map, double thresh)
569 {
570     G_debug(1, "Vect_set_thresh(): thresh = %f", thresh);
571     Map->head.digit_thresh = thresh;
572     return 0;
573 }
574 
575 /*!
576    \brief Get threshold used for digitization from map header
577 
578    \param Map pointer to Map_info structure
579 
580    \return threshold used for digitization
581  */
Vect_get_thresh(const struct Map_info * Map)582 double Vect_get_thresh(const struct Map_info *Map)
583 {
584     return Map->head.digit_thresh;
585 }
586