tinyows 1.2.2
ows_srs.c
Go to the documentation of this file.
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 */
38{
39 ows_srs *c;
40
41 c = malloc(sizeof(ows_srs));
42 assert(c);
43
44 c->srid = -1;
46 c->auth_srid = 0;
47 c->is_geographic = true;
50 c->is_long = false;
51
52 return c;
53}
54
55
57{
58 assert(s);
59 assert(d);
60
61 d->srid = s->srid;
63 d->auth_srid = s->auth_srid;
67 d->is_long = s->is_long;
68
69 return d;
70}
71
72
73/*
74 * Free proj structure
75 */
77{
78 assert(c);
79
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 */
91void 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_geographic)
102 fprintf(output, " is_geographic: true\n]\n");
103 else
104 fprintf(output, " is_geographic: false\n]\n");
105
107 fprintf(output, " honours_authority_axis_order: true\n]\n");
108 else
109 fprintf(output, " honours_authority_axis_order: false\n]\n");
110
112 fprintf(output, " is_axis_order_gis_friendly: true\n]\n");
113 else
114 fprintf(output, " is_axis_order_gis_friendly: false\n]\n");
115
116 if (c->is_long)
117 fprintf(output, " is_long: true\n]\n");
118 else
119 fprintf(output, " is_long: false\n]\n");
120}
121#endif
122
123/*
124 * Set s->is_geographic and s->is_axis_order_gis_friendly
125 * from srtext.
126 */
128 ows_srs* s, const char* proj4text, const char* srtext)
129{
130 /* Use srtext in priority */
131 if (srtext && srtext[0] != '\0')
132 {
133 char* srtext_horizontal = (char*) malloc(strlen(srtext) + 1);
134 char* ptr;
135 strcpy(srtext_horizontal, srtext);
136
137 /* Remove the VERT_CS part if we are in a COMPD_CS */
138 ptr = strstr(srtext_horizontal, ",VERT_CS[");
139 if (ptr)
140 *ptr = '\0';
141
143 s->is_geographic = (strstr(srtext, "PROJCS[") == NULL &&
144 strstr(srtext, "GEOCCS[") == NULL &&
145 strstr(srtext, "BOUNDCRS[") == NULL) ||
146 strstr(srtext, "BOUNDCRS[SOURCECRS[GEOGCRS") != NULL;
147
148 if( strstr(srtext_horizontal, "AXIS[") == NULL &&
149 strstr(srtext_horizontal, "GEOCCS[") == NULL )
150 {
151 /* If there is no axis definition, then due to how GDAL < 3
152 * generated the WKT, this means that the axis order is not
153 * GIS friendly */
155 }
156 else if( strstr(srtext_horizontal,
157 "AXIS[\"Latitude\",NORTH],AXIS[\"Longitude\",EAST]") != NULL )
158 {
160 }
161 else if( strstr(srtext_horizontal,
162 "AXIS[\"Northing\",NORTH],AXIS[\"Easting\",EAST]") != NULL )
163 {
165 }
166 else if( strstr(srtext_horizontal,
167 "AXIS[\"geodetic latitude (Lat)\",north,ORDER[1]") != NULL )
168 {
170 }
171
172 free(srtext_horizontal);
173 }
174 else if( proj4text && proj4text[0] != '\0' )
175 {
176 s->is_geographic = strstr(proj4text, "+units=m") == NULL;
177 /* This will be wrong for a number of projected CRS ! */
179 }
180}
181
182/*
183 * Set projection value into srs structure
184 */
185bool ows_srs_set(ows * o, ows_srs * s, const buffer * auth_name, int auth_srid)
186{
187 PGresult *res;
188 buffer *sql;
189 const char* proj4text;
190 const char* srtext;
191
192 assert(o);
193 assert(s);
194 assert(o->pg);
195 assert(auth_name);
196
197 sql = buffer_init();
198 buffer_add_str(sql, "SELECT srid, proj4text, srtext "
199 "FROM spatial_ref_sys WHERE auth_name='");
200 buffer_copy(sql, auth_name);
201 buffer_add_str(sql, "' AND auth_srid=");
202 buffer_add_int(sql, auth_srid);
203
204 res = ows_psql_exec(o, sql->buf);
205 buffer_free(sql);
206
207 /* If query dont return exactly 1 result, it means projection is not handled */
208 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
209 PQclear(res);
210 return false;
211 }
212
214 buffer_copy(s->auth_name, auth_name);
215 s->auth_srid = auth_srid;
216
217 s->srid = atoi(PQgetvalue(res, 0, 0));
218
219 proj4text = PQgetvalue(res, 0, 1);
220 srtext = PQgetvalue(res, 0, 2);
222
223 PQclear(res);
224 return true;
225}
226
227
228/*
229 * Aim is to avoid all pg connection,
230 * not a big deal as we already know values
231 */
233{
234 assert(o);
235 assert(s);
236
237 s->srid = 4326;
239 buffer_add_str(s->auth_name, "EPSG");
240 s->auth_srid = 4326;
241 s->is_geographic = true;
243
244 return true;
245}
246
247
248/*
249 * Set projection value into srs structure
250 */
251bool ows_srs_set_from_srid(ows * o, ows_srs * s, int srid)
252{
253 PGresult *res;
254 buffer *sql;
255 const char *proj4text;
256 const char *srtext;
257
258 assert(o);
259 assert(s);
260
261 if (srid == -1 || srid == 0) {
262 s->srid = -1;
264 s->auth_srid = 0;
265 s->is_geographic = true;
268
269 return true;
270 }
271
272 sql = buffer_init();
273 buffer_add_str(sql, "SELECT auth_name, auth_srid, proj4text, srtext "
274 "FROM spatial_ref_sys WHERE srid = '");
275 buffer_add_int(sql, srid);
276 buffer_add_str(sql, "'");
277
278 res = ows_psql_exec(o, sql->buf);
279 buffer_free(sql);
280
281 /* If query dont return exactly 1 result, it mean projection not handled */
282 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
283 PQclear(res);
284 return false;
285 }
286
287 buffer_add_str(s->auth_name, PQgetvalue(res, 0, 0));
288 s->auth_srid = atoi(PQgetvalue(res, 0, 1));
289 s->srid = srid;
290
291 proj4text = PQgetvalue(res, 0, 2);
292 srtext = PQgetvalue(res, 0, 3);
294
295 PQclear(res);
296 return true;
297}
298
299
300/*
301 * Set projection value into srs structure
302 */
303bool ows_srs_set_from_srsname(ows * o, ows_srs * s, const char *srsname)
304{
305 char sep;
306 int srid = -1;
307 const char *p = NULL;
308
309 assert(o);
310 assert(s);
311 assert(srsname);
312
313 /* Severals srsName formats are available...
314 * cf WFS 1.1.0 -> 9.2 (p36)
315 * cf ISO 19142 -> 7.9.2.4.4 (p34)
316 * cf RFC 5165 <http://tools.ietf.org/html/rfc5165>
317 * cf CITE WFS-1.1 (GetFeature-tc17.2)
318 */
319
320 /* SRS pattern like: EPSG:4326
321 urn:EPSG:geographicCRS:4326
322 urn:ogc:def:crs:EPSG:4326
323 urn:ogc:def:crs:EPSG::4326
324 urn:ogc:def:crs:EPSG:6.6:4326
325 urn:x-ogc:def:crs:EPSG:6.6:4326
326 http://www.opengis.net/gml/srs/epsg.xml#4326
327 spatialreferencing.org:900913
328 */
329 s->is_long = true;
330
331 if (!strncmp((char *) srsname, "EPSG:", 5)
332 || !strncmp((char *) srsname, "spatialreferencing.org", 22)) {
333 sep = ':';
335 s->is_long = false;
336
337 } else if (!strncmp((char *) srsname, "urn:ogc:def:crs:EPSG:", 21)
338 || !strncmp((char *) srsname, "urn:x-ogc:def:crs:EPSG:", 23)
339 || !strncmp((char *) srsname, "urn:EPSG:geographicCRS:", 23)) {
340 sep = ':';
342
343 } else if (!strncmp((char *) srsname, "http://www.opengis.net/gml/srs/epsg.xml#", 40)) {
344 sep = '#';
346 } else return false; /* FIXME must we really not allow other value ? */
347
348 /* Retrieve from last separator to the end of srsName string */
349 for (p = srsname ; *p ; p++);
350 for (--p ; *p != sep ; p--)
351 if (!isdigit(*p)) return false;
352 srid = atoi(++p);
353
354 return ows_srs_set_from_srid(o, s, srid);
355}
356
357
358/*
359 * Check if a layer's srs has meter or degree units
360 */
361bool ows_srs_meter_units(ows * o, buffer * layer_name)
362{
363 ows_layer_node * ln;
364
365 assert(o);
366 assert(layer_name);
367
368 for (ln = o->layers->first ; ln ; ln = ln->next)
369 if (ln->layer->name && ln->layer->storage && !strcmp(ln->layer->name->buf, layer_name->buf))
370 return !ln->layer->storage->is_geographic;
371
372 assert(0); /* Should not happen */
373 return false;
374}
375
376
377/*
378 * Retrieve a srs from a layer
379 */
381{
382 ows_layer_node * ln;
383
384 assert(o);
385 assert(layer_name);
386
387 for (ln = o->layers->first ; ln ; ln = ln->next)
388 if (ln->layer->name && ln->layer->storage && !strcmp(ln->layer->name->buf, layer_name->buf))
389 return ln->layer->storage->srid;
390
391 return -1;
392}
393
394
395/*
396 * Retrieve a list of srs from an srid list
397 */
399{
400 list_node *ln;
401 buffer *b;
402 list *srs;
403
404 assert(o);
405 assert(l);
406
407 srs = list_init();
408
409 if (l->size == 0) return srs;
410
411 for (ln = l->first; ln ; ln = ln->next) {
412 b = ows_srs_get_from_a_srid(o, atoi(ln->value->buf));
413 list_add(srs, b);
414 }
415
416 return srs;
417}
418
419
420/*
421 * Retrieve a srs from a srid
422 */
424{
425 buffer *b;
426 buffer *sql;
427 PGresult *res;
428
429 assert(o);
430
431 sql = buffer_init();
432 buffer_add_str(sql, "SELECT auth_name||':'||auth_srid AS srs ");
433 buffer_add_str(sql, "FROM spatial_ref_sys ");
434 buffer_add_str(sql, "WHERE srid=");
435 buffer_add_int(sql, srid);
436
437 res = ows_psql_exec(o, sql->buf);
438 buffer_free(sql);
439
440 b = buffer_init();
441
442 if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) != 1) {
443 PQclear(res);
444 return b;
445 }
446
447 buffer_add_str(b, PQgetvalue(res, 0, 0));
448
449 PQclear(res);
450
451 return b;
452}
453
454
455/*
456 * vim: expandtab sw=4 ts=4
457 */
void buffer_empty(buffer *buf)
Definition buffer.c:100
PGresult * ows_psql_exec(ows *o, const char *sql)
Definition ows_psql.c:56
void buffer_copy(buffer *dest, const buffer *src)
Definition buffer.c:350
void buffer_add_str(buffer *buf, const char *str)
Definition buffer.c:254
list * list_init()
Definition list.c:36
void list_add(list *l, buffer *value)
Definition list.c:71
void ows_srs_flush(ows_srs *c, FILE *output)
void buffer_free(buffer *buf)
Definition buffer.c:83
void buffer_add_int(buffer *buf, int i)
Definition buffer.c:173
buffer * buffer_init()
Definition buffer.c:61
static void ows_srs_set_is_geographic_and_is_axis_order_gis_friendly_from_def(ows_srs *s, const char *proj4text, const char *srtext)
Definition ows_srs.c:127
bool ows_srs_meter_units(ows *o, buffer *layer_name)
Definition ows_srs.c:361
ows_srs * ows_srs_init()
Definition ows_srs.c:37
bool ows_srs_set_from_srsname(ows *o, ows_srs *s, const char *srsname)
Definition ows_srs.c:303
list * ows_srs_get_from_srid(ows *o, list *l)
Definition ows_srs.c:398
bool ows_srs_set_from_srid(ows *o, ows_srs *s, int srid)
Definition ows_srs.c:251
int ows_srs_get_srid_from_layer(ows *o, buffer *layer_name)
Definition ows_srs.c:380
bool ows_srs_set_geobbox(ows *o, ows_srs *s)
Definition ows_srs.c:232
void ows_srs_free(ows_srs *c)
Definition ows_srs.c:76
buffer * ows_srs_get_from_a_srid(ows *o, int srid)
Definition ows_srs.c:423
bool ows_srs_set(ows *o, ows_srs *s, const buffer *auth_name, int auth_srid)
Definition ows_srs.c:185
ows_srs * ows_srs_copy(ows_srs *d, ows_srs *s)
Definition ows_srs.c:56
struct List_node list_node
struct Ows_layer_node ows_layer_node
struct Buffer buffer
struct Ows ows
struct Ows_srs ows_srs
struct List list
char * buf
size to next realloc
Definition ows_struct.h:39
struct List_node * next
Definition ows_struct.h:45
buffer * value
Definition ows_struct.h:44
unsigned int size
Definition ows_struct.h:52
list_node * first
Definition ows_struct.h:50
ows_layer_node * first
Definition ows_struct.h:205
ows_layer * layer
Definition ows_struct.h:199
struct Ows_layer_node * next
Definition ows_struct.h:200
buffer * name
Definition ows_struct.h:177
ows_layer_storage * storage
Definition ows_struct.h:195
bool honours_authority_axis_order
Definition ows_struct.h:126
bool is_long
Definition ows_struct.h:129
buffer * auth_name
Definition ows_struct.h:112
int auth_srid
Definition ows_struct.h:113
bool is_geographic
Definition ows_struct.h:114
bool is_axis_order_gis_friendly
Definition ows_struct.h:118
PGconn * pg
Definition ows_struct.h:369
ows_layer_list * layers
Definition ows_struct.h:402

Generated for tinyows by doxygen 1.14.0