1 /*
2  * projection checking
3  *
4  * Copyright 2011-2015 by Markus Metz, and The GRASS Development Team
5  * Authors:
6  *  Markus Metz (v.in.lidar)
7  *  Vaclav Petras (move code to standalone functions)
8  *
9  * This program is free software licensed under the GPL (>=v2).
10  * Read the COPYING file that comes with GRASS for details.
11  *
12  */
13 
14 #include <string.h>
15 
16 #include <grass/gis.h>
17 #include <grass/glocale.h>
18 #include <grass/gprojects.h>
19 
projection_mismatch_report(struct Cell_head cellhd,struct Cell_head loc_wind,struct Key_Value * loc_proj_info,struct Key_Value * loc_proj_units,struct Key_Value * proj_info,struct Key_Value * proj_units,int err)20 void projection_mismatch_report(struct Cell_head cellhd,
21                                 struct Cell_head loc_wind,
22                                 struct Key_Value *loc_proj_info,
23                                 struct Key_Value *loc_proj_units,
24                                 struct Key_Value *proj_info,
25                                 struct Key_Value *proj_units, int err)
26 {
27     int i_value;
28     char error_msg[8192];
29 
30     strcpy(error_msg,
31            _("Projection of dataset does not"
32              " appear to match current location.\n\n"));
33 
34     /* TODO: output this info sorted by key: */
35     if (loc_wind.proj != cellhd.proj || err != -2) {
36         if (loc_proj_info != NULL) {
37             strcat(error_msg, _("GRASS LOCATION PROJ_INFO is:\n"));
38             for (i_value = 0; i_value < loc_proj_info->nitems; i_value++)
39                 sprintf(error_msg + strlen(error_msg), "%s: %s\n",
40                         loc_proj_info->key[i_value],
41                         loc_proj_info->value[i_value]);
42             strcat(error_msg, "\n");
43         }
44 
45         if (proj_info != NULL) {
46             strcat(error_msg, _("Import dataset PROJ_INFO is:\n"));
47             for (i_value = 0; i_value < proj_info->nitems; i_value++)
48                 sprintf(error_msg + strlen(error_msg), "%s: %s\n",
49                         proj_info->key[i_value], proj_info->value[i_value]);
50         }
51         else {
52             strcat(error_msg, _("Import dataset PROJ_INFO is:\n"));
53             if (cellhd.proj == PROJECTION_XY)
54                 sprintf(error_msg + strlen(error_msg),
55                         "Dataset proj = %d (unreferenced/unknown)\n",
56                         cellhd.proj);
57             else if (cellhd.proj == PROJECTION_LL)
58                 sprintf(error_msg + strlen(error_msg),
59                         "Dataset proj = %d (lat/long)\n", cellhd.proj);
60             else if (cellhd.proj == PROJECTION_UTM)
61                 sprintf(error_msg + strlen(error_msg),
62                         "Dataset proj = %d (UTM), zone = %d\n",
63                         cellhd.proj, cellhd.zone);
64             else
65                 sprintf(error_msg + strlen(error_msg),
66                         "Dataset proj = %d (unknown), zone = %d\n",
67                         cellhd.proj, cellhd.zone);
68         }
69     }
70     else {
71         if (loc_proj_units != NULL) {
72             strcat(error_msg, "GRASS LOCATION PROJ_UNITS is:\n");
73             for (i_value = 0; i_value < loc_proj_units->nitems; i_value++)
74                 sprintf(error_msg + strlen(error_msg), "%s: %s\n",
75                         loc_proj_units->key[i_value],
76                         loc_proj_units->value[i_value]);
77             strcat(error_msg, "\n");
78         }
79 
80         if (proj_units != NULL) {
81             strcat(error_msg, "Import dataset PROJ_UNITS is:\n");
82             for (i_value = 0; i_value < proj_units->nitems; i_value++)
83                 sprintf(error_msg + strlen(error_msg), "%s: %s\n",
84                         proj_units->key[i_value], proj_units->value[i_value]);
85         }
86     }
87     sprintf(error_msg + strlen(error_msg),
88             _("\nIn case of no significant differences in the projection definitions,"
89              " use the -o flag to ignore them and use"
90              " current location definition.\n"));
91     strcat(error_msg,
92            _("Consider generating a new location with 'location' parameter"
93              " from input data set.\n"));
94     G_fatal_error("%s", error_msg);
95 }
96 
projection_check_wkt(struct Cell_head cellhd,struct Cell_head loc_wind,const char * projstr,int override,int verbose)97 void projection_check_wkt(struct Cell_head cellhd,
98                           struct Cell_head loc_wind,
99                           const char *projstr, int override, int verbose)
100 {
101     struct Key_Value *loc_proj_info = NULL, *loc_proj_units = NULL;
102     struct Key_Value *proj_info, *proj_units;
103     int err = 0;
104 
105     proj_info = NULL;
106     proj_units = NULL;
107 
108     /* Projection only required for checking so convert non-interactively */
109     if (GPJ_wkt_to_grass(&cellhd, &proj_info, &proj_units, projstr, 0) < 0)
110         G_warning(_("Unable to convert input map projection information to "
111                     "GRASS format for checking"));
112 
113     /* Does the projection of the current location match the dataset? */
114 
115     /* fetch LOCATION PROJ info */
116     if (loc_wind.proj != PROJECTION_XY) {
117         loc_proj_info = G_get_projinfo();
118         loc_proj_units = G_get_projunits();
119     }
120 
121     if (override) {
122         cellhd.proj = loc_wind.proj;
123         cellhd.zone = loc_wind.zone;
124         if (verbose)
125             G_message(_("Overriding projection check"));
126     }
127     else if (loc_wind.proj != cellhd.proj
128              || (err =
129                  G_compare_projections(loc_proj_info, loc_proj_units,
130                                        proj_info, proj_units)) != TRUE) {
131         projection_mismatch_report(cellhd, loc_wind, loc_proj_info,
132                                    loc_proj_units,
133                                    proj_info, proj_units, err);
134     }
135     else {
136         if (verbose) {
137             G_message(_("Projection of input dataset and current location "
138                         "appear to match"));
139         }
140     }
141 }
142 
143 
144 /* Does the projection of the current location match the dataset? */
is_wkt_projection_same_as_loc(const char * wkt)145 int is_wkt_projection_same_as_loc(const char *wkt)
146 {
147     struct Key_Value *loc_proj_info = NULL, *loc_proj_units = NULL;
148     struct Key_Value *proj_info = NULL, *proj_units = NULL;
149     struct Cell_head cellhd;
150     struct Cell_head loc_wind;
151 
152     G_get_default_window(&loc_wind);
153 
154     /* Projection only required for checking so convert non-interactively */
155     if (GPJ_wkt_to_grass(&cellhd, &proj_info, &proj_units, wkt, 0) < 0)
156         G_warning(_("Unable to convert input map projection information to "
157                     "GRASS format for checking"));
158 
159     /* fetch LOCATION PROJ info */
160     if (loc_wind.proj != PROJECTION_XY) {
161         loc_proj_info = G_get_projinfo();
162         loc_proj_units = G_get_projunits();
163     }
164 
165     if (loc_wind.proj != cellhd.proj) {
166         return FALSE;
167     }
168     else if (G_compare_projections(loc_proj_info, loc_proj_units,
169                                    proj_info, proj_units) != 1) {
170         return FALSE;
171     }
172     else {
173         return TRUE;
174     }
175 }
176 
177 /* Does the projection of the current location match the dataset? */
wkt_projection_mismatch_report(const char * wkt)178 void wkt_projection_mismatch_report(const char *wkt)
179 {
180     struct Key_Value *loc_proj_info = NULL, *loc_proj_units = NULL;
181     struct Key_Value *proj_info = NULL, *proj_units = NULL;
182     struct Cell_head cellhd;
183     struct Cell_head loc_wind;
184 
185     G_get_default_window(&loc_wind);
186 
187     /* Projection only required for checking so convert non-interactively */
188     if (GPJ_wkt_to_grass(&cellhd, &proj_info, &proj_units, wkt, 0) < 0)
189         G_warning(_("Unable to convert input map projection information to "
190                     "GRASS format for checking"));
191 
192     /* fetch LOCATION PROJ info */
193     if (loc_wind.proj != PROJECTION_XY) {
194         loc_proj_info = G_get_projinfo();
195         loc_proj_units = G_get_projunits();
196     }
197     int err = G_compare_projections(loc_proj_info, loc_proj_units,
198                                     proj_info, proj_units);
199 
200     projection_mismatch_report(cellhd, loc_wind, loc_proj_info,
201                                loc_proj_units, proj_info, proj_units, err);
202 }
203 
204 /* caller should free the returned string */
location_projection_as_wkt(int prettify)205 char *location_projection_as_wkt(int prettify)
206 {
207     struct Key_Value *proj_info = G_get_projinfo();
208     struct Key_Value *proj_units = G_get_projunits();
209     char *proj_wkt = GPJ_grass_to_wkt(proj_info, proj_units, FALSE, prettify);
210 
211     G_free_key_value(proj_info);
212     G_free_key_value(proj_units);
213     return proj_wkt;
214 }
215