1 /*
2 Copyright (c) <2007-2012> <Barbara Philippot - Olivier Courtin>
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 IN THE SOFTWARE.
21 */
22
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <assert.h>
27 #include <ctype.h>
28 #include <libpq-fe.h>
29 #include <string.h>
30
31 #include "ows.h"
32
33
34 /*
35 * Initialize proj structure
36 */
ows_srs_init()37 ows_srs *ows_srs_init()
38 {
39 ows_srs *c;
40
41 c = malloc(sizeof(ows_srs));
42 assert(c);
43
44 c->srid = -1;
45 c->auth_name = buffer_init();
46 c->auth_srid = 0;
47 c->is_degree = true;
48 c->is_reverse_axis = false;
49 c->is_eastern_axis = false;
50 c->is_long = false;
51
52 return c;
53 }
54
55
ows_srs_copy(ows_srs * d,ows_srs * s)56 ows_srs *ows_srs_copy(ows_srs * d, ows_srs * s)
57 {
58 assert(s);
59 assert(d);
60
61 d->srid = s->srid;
62 buffer_copy(d->auth_name, s->auth_name);
63 d->auth_srid = s->auth_srid;
64 d->is_degree = s->is_degree;
65 d->is_reverse_axis = s->is_reverse_axis;
66 d->is_eastern_axis = s->is_eastern_axis;
67 d->is_long = s->is_long;
68
69 return d;
70 }
71
72
73 /*
74 * Free proj structure
75 */
ows_srs_free(ows_srs * c)76 void ows_srs_free(ows_srs * c)
77 {
78 assert(c);
79
80 buffer_free(c->auth_name);
81 free(c);
82 c = NULL;
83 }
84
85
86 #ifdef OWS_DEBUG
87 /*
88 * Print ows structure state into a file
89 * (mainly for debug purpose)
90 */
ows_srs_flush(ows_srs * c,FILE * output)91 void ows_srs_flush(ows_srs * c, FILE * output)
92 {
93 assert(c);
94 assert(output);
95
96 fprintf(output, "[\n");
97 fprintf(output, " srid: %i\n", c->srid);
98 fprintf(output, " auth_name: %s\n", c->auth_name->buf);
99 fprintf(output, " auth_srid: %i\n", c->auth_srid);
100
101 if (c->is_degree) fprintf(output, " is_degree: true\n]\n");
102 else fprintf(output, " is_degree: false\n]\n");
103
104 if (c->is_reverse_axis)
105 fprintf(output, " is_reverse_axis: true\n]\n");
106 else
107 fprintf(output, " is_reverse_axis: false\n]\n");
108
109 if (c->is_eastern_axis)
110 fprintf(output, " is_eastern_axis: true\n]\n");
111 else
112 fprintf(output, " is_eastern_axis: false\n]\n");
113
114 if (c->is_long)
115 fprintf(output, " is_long: true\n]\n");
116 else
117 fprintf(output, " is_long: false\n]\n");
118 }
119 #endif
120
121
122 /*
123 * Set projection value into srs structure
124 */
ows_srs_set(ows * o,ows_srs * c,const buffer * auth_name,int auth_srid)125 bool ows_srs_set(ows * o, ows_srs * c, const buffer * auth_name, int auth_srid)
126 {
127 PGresult *res;
128 buffer *sql;
129
130 assert(o);
131 assert(c);
132 assert(o->pg);
133 assert(auth_name);
134
135 sql = buffer_init();
136 buffer_add_str(sql, "SELECT srid, position('+units=m ' in proj4text)");
137 buffer_add_str(sql, ", (position('AXIS[\"X\",NORTH]]' in srtext) + position('AXIS[\"Easting\",EAST]]' in srtext))");
138 buffer_add_str(sql, " FROM spatial_ref_sys WHERE auth_name='");
139 buffer_copy(sql, auth_name);
140 buffer_add_str(sql, "' AND auth_srid=");
141 buffer_add_int(sql, auth_srid);
142
143 res = ows_psql_exec(o, sql->buf);
144 buffer_free(sql);
145
146 /* If query dont return exactly 1 result, it means projection is not handled */
147 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
148 PQclear(res);
149 return false;
150 }
151
152 buffer_empty(c->auth_name);
153 buffer_copy(c->auth_name, auth_name);
154 c->auth_srid = auth_srid;
155
156 c->srid = atoi(PQgetvalue(res, 0, 0));
157
158 /* Such a way to know if units is meter or degree */
159 if (atoi(PQgetvalue(res, 0, 1)) == 0)
160 c->is_degree = true;
161 else
162 c->is_degree = false;
163
164 /* Is northing-easting SRID ? */
165 if (atoi(PQgetvalue(res, 0, 2)) != 0)
166 c->is_eastern_axis = true;
167
168 PQclear(res);
169 return true;
170 }
171
172
173 /*
174 * Aim is to avoid all pg connection,
175 * not a big deal as we already know values
176 */
ows_srs_set_geobbox(ows * o,ows_srs * s)177 bool ows_srs_set_geobbox(ows * o, ows_srs * s)
178 {
179 assert(o);
180 assert(s);
181
182 s->srid = 4326;
183 buffer_empty(s->auth_name);
184 buffer_add_str(s->auth_name, "EPSG");
185 s->auth_srid = 4326;
186 s->is_degree = true;
187 s->is_reverse_axis = false;
188 s->is_eastern_axis = false;
189
190 return true;
191 }
192
193
194 /*
195 * Set projection value into srs structure
196 */
ows_srs_set_from_srid(ows * o,ows_srs * s,int srid)197 bool ows_srs_set_from_srid(ows * o, ows_srs * s, int srid)
198 {
199 PGresult *res;
200 buffer *sql;
201
202 assert(o);
203 assert(s);
204
205 if (srid == -1 || srid == 0) {
206 s->srid = -1;
207 buffer_empty(s->auth_name);
208 s->auth_srid = 0;
209 s->is_degree = true;
210 s->is_reverse_axis = false;
211 s->is_eastern_axis = false;
212
213 return true;
214 }
215
216 sql = buffer_init();
217 buffer_add_str(sql, "SELECT auth_name, auth_srid, ");
218 buffer_add_str(sql, "position('+units=m ' in proj4text), ");
219 buffer_add_str(sql, "(position('AXIS[\"X\",NORTH]]' in srtext) + position('AXIS[\"Easting\",EAST]]' in srtext)) ");
220 buffer_add_str(sql, "FROM spatial_ref_sys WHERE srid = '");
221 buffer_add_int(sql, srid);
222 buffer_add_str(sql, "'");
223
224 res = ows_psql_exec(o, sql->buf);
225 buffer_free(sql);
226
227 /* If query dont return exactly 1 result, it mean projection not handled */
228 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
229 PQclear(res);
230 return false;
231 }
232
233 buffer_add_str(s->auth_name, PQgetvalue(res, 0, 0));
234 s->auth_srid = atoi(PQgetvalue(res, 0, 1));
235 s->srid = srid;
236
237 /* Such a way to know if units is meter or degree */
238 if (atoi(PQgetvalue(res, 0, 2)) == 0)
239 s->is_degree = true;
240 else
241 s->is_degree = false;
242
243 /* Is northing-easting SRID ? */
244 if (atoi(PQgetvalue(res, 0, 3)) != 0)
245 s->is_eastern_axis = true;
246
247 PQclear(res);
248 return true;
249 }
250
251
252 /*
253 * Set projection value into srs structure
254 */
ows_srs_set_from_srsname(ows * o,ows_srs * s,const char * srsname)255 bool ows_srs_set_from_srsname(ows * o, ows_srs * s, const char *srsname)
256 {
257 char sep;
258 int srid = -1;
259 const char *p = NULL;
260
261 assert(o);
262 assert(s);
263 assert(srsname);
264
265 /* Severals srsName formats are available...
266 * cf WFS 1.1.0 -> 9.2 (p36)
267 * cf ISO 19142 -> 7.9.2.4.4 (p34)
268 * cf RFC 5165 <http://tools.ietf.org/html/rfc5165>
269 * cf CITE WFS-1.1 (GetFeature-tc17.2)
270 */
271
272 /* SRS pattern like: EPSG:4326
273 urn:EPSG:geographicCRS:4326
274 urn:ogc:def:crs:EPSG:4326
275 urn:ogc:def:crs:EPSG::4326
276 urn:ogc:def:crs:EPSG:6.6:4326
277 urn:x-ogc:def:crs:EPSG:6.6:4326
278 http://www.opengis.net/gml/srs/epsg.xml#4326
279 spatialreferencing.org:900913
280 */
281 s->is_long = true;
282
283 if (!strncmp((char *) srsname, "EPSG:", 5)
284 || !strncmp((char *) srsname, "spatialreferencing.org", 22)) {
285 sep = ':';
286 s->is_reverse_axis = false;
287 s->is_long = false;
288
289 } else if (!strncmp((char *) srsname, "urn:ogc:def:crs:EPSG:", 21)
290 || !strncmp((char *) srsname, "urn:x-ogc:def:crs:EPSG:", 23)
291 || !strncmp((char *) srsname, "urn:EPSG:geographicCRS:", 23)) {
292 sep = ':';
293 s->is_reverse_axis = true;
294
295 } else if (!strncmp((char *) srsname, "http://www.opengis.net/gml/srs/epsg.xml#", 40)) {
296 sep = '#';
297 s->is_reverse_axis = false;
298 } else return false; /* FIXME must we really not allow other value ? */
299
300 /* Retrieve from last separator to the end of srsName string */
301 for (p = srsname ; *p ; p++);
302 for (--p ; *p != sep ; p--)
303 if (!isdigit(*p)) return false;
304 srid = atoi(++p);
305
306 return ows_srs_set_from_srid(o, s, srid);
307 }
308
309
310 /*
311 * Check if a layer's srs has meter or degree units
312 */
ows_srs_meter_units(ows * o,buffer * layer_name)313 bool ows_srs_meter_units(ows * o, buffer * layer_name)
314 {
315 ows_layer_node * ln;
316
317 assert(o);
318 assert(layer_name);
319
320 for (ln = o->layers->first ; ln ; ln = ln->next)
321 if (ln->layer->name && ln->layer->storage && !strcmp(ln->layer->name->buf, layer_name->buf))
322 return !ln->layer->storage->is_degree;
323
324 assert(0); /* Should not happen */
325 return false;
326 }
327
328
329 /*
330 * Retrieve a srs from a layer
331 */
ows_srs_get_srid_from_layer(ows * o,buffer * layer_name)332 int ows_srs_get_srid_from_layer(ows * o, buffer * layer_name)
333 {
334 ows_layer_node * ln;
335
336 assert(o);
337 assert(layer_name);
338
339 for (ln = o->layers->first ; ln ; ln = ln->next)
340 if (ln->layer->name && ln->layer->storage && !strcmp(ln->layer->name->buf, layer_name->buf))
341 return ln->layer->storage->srid;
342
343 return -1;
344 }
345
346
347 /*
348 * Retrieve a list of srs from an srid list
349 */
ows_srs_get_from_srid(ows * o,list * l)350 list *ows_srs_get_from_srid(ows * o, list * l)
351 {
352 list_node *ln;
353 buffer *b;
354 list *srs;
355
356 assert(o);
357 assert(l);
358
359 srs = list_init();
360
361 if (l->size == 0) return srs;
362
363 for (ln = l->first; ln ; ln = ln->next) {
364 b = ows_srs_get_from_a_srid(o, atoi(ln->value->buf));
365 list_add(srs, b);
366 }
367
368 return srs;
369 }
370
371
372 /*
373 * Retrieve a srs from a srid
374 */
ows_srs_get_from_a_srid(ows * o,int srid)375 buffer *ows_srs_get_from_a_srid(ows * o, int srid)
376 {
377 buffer *b;
378 buffer *sql;
379 PGresult *res;
380
381 assert(o);
382
383 sql = buffer_init();
384 buffer_add_str(sql, "SELECT auth_name||':'||auth_srid AS srs ");
385 buffer_add_str(sql, "FROM spatial_ref_sys ");
386 buffer_add_str(sql, "WHERE srid=");
387 buffer_add_int(sql, srid);
388
389 res = ows_psql_exec(o, sql->buf);
390 buffer_free(sql);
391
392 b = buffer_init();
393
394 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
395 PQclear(res);
396 return b;
397 }
398
399 buffer_add_str(b, PQgetvalue(res, 0, 0));
400
401 PQclear(res);
402
403 return b;
404 }
405
406
407 /*
408 * vim: expandtab sw=4 ts=4
409 */
410