1 : /******************************************************************************
2 : * $Id: ogr_srs_validate.cpp 18033 2009-11-15 19:18:57Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implementation of the OGRSpatialReference::Validate() method and
6 : * related infrastructure.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.com>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "ogr_spatialref.h"
32 : #include "ogr_p.h"
33 :
34 : CPL_CVSID("$Id: ogr_srs_validate.cpp 18033 2009-11-15 19:18:57Z rouault $");
35 :
36 : /* why would fipszone and zone be paramers when they relate to a composite
37 : projection which renders done into a non-zoned projection? */
38 :
39 : static const char *papszParameters[] =
40 : {
41 : SRS_PP_CENTRAL_MERIDIAN,
42 : SRS_PP_SCALE_FACTOR,
43 : SRS_PP_STANDARD_PARALLEL_1,
44 : SRS_PP_STANDARD_PARALLEL_2,
45 : SRS_PP_LONGITUDE_OF_CENTER,
46 : SRS_PP_LATITUDE_OF_CENTER,
47 : SRS_PP_LONGITUDE_OF_ORIGIN,
48 : SRS_PP_LATITUDE_OF_ORIGIN,
49 : SRS_PP_FALSE_EASTING,
50 : SRS_PP_FALSE_NORTHING,
51 : SRS_PP_AZIMUTH,
52 : SRS_PP_LONGITUDE_OF_POINT_1,
53 : SRS_PP_LATITUDE_OF_POINT_1,
54 : SRS_PP_LONGITUDE_OF_POINT_2,
55 : SRS_PP_LATITUDE_OF_POINT_2,
56 : SRS_PP_LONGITUDE_OF_POINT_3,
57 : SRS_PP_LATITUDE_OF_POINT_3,
58 : SRS_PP_LANDSAT_NUMBER,
59 : SRS_PP_PATH_NUMBER,
60 : SRS_PP_PERSPECTIVE_POINT_HEIGHT,
61 : SRS_PP_FIPSZONE,
62 : SRS_PP_ZONE,
63 : SRS_PP_RECTIFIED_GRID_ANGLE,
64 : SRS_PP_SATELLITE_HEIGHT,
65 : SRS_PP_PSEUDO_STD_PARALLEL_1,
66 : SRS_PP_LATITUDE_OF_1ST_POINT,
67 : SRS_PP_LONGITUDE_OF_1ST_POINT,
68 : SRS_PP_LATITUDE_OF_2ND_POINT,
69 : SRS_PP_LONGITUDE_OF_2ND_POINT,
70 : NULL
71 : };
72 :
73 : // the following projection lists are incomplete. they will likely
74 : // change after the CT RPF response. Examples show alternate forms with
75 : // underscores instead of spaces. Should we use the EPSG names were available?
76 : // Plate-Caree has an accent in the spec!
77 :
78 : static const char *papszProjectionSupported[] =
79 : {
80 : SRS_PT_CASSINI_SOLDNER,
81 : SRS_PT_BONNE,
82 : SRS_PT_EQUIDISTANT_CONIC,
83 : SRS_PT_EQUIRECTANGULAR,
84 : SRS_PT_ECKERT_I,
85 : SRS_PT_ECKERT_II,
86 : SRS_PT_ECKERT_III,
87 : SRS_PT_ECKERT_IV,
88 : SRS_PT_ECKERT_V,
89 : SRS_PT_ECKERT_VI,
90 : SRS_PT_MERCATOR_1SP,
91 : SRS_PT_MERCATOR_2SP,
92 : SRS_PT_ROBINSON,
93 : SRS_PT_ALBERS_CONIC_EQUAL_AREA,
94 : SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
95 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP,
96 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM,
97 : SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA,
98 : SRS_PT_TRANSVERSE_MERCATOR,
99 : SRS_PT_OBLIQUE_STEREOGRAPHIC,
100 : SRS_PT_POLAR_STEREOGRAPHIC,
101 : SRS_PT_HOTINE_OBLIQUE_MERCATOR,
102 : SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN,
103 : SRS_PT_LABORDE_OBLIQUE_MERCATOR,
104 : SRS_PT_SWISS_OBLIQUE_CYLINDRICAL,
105 : SRS_PT_AZIMUTHAL_EQUIDISTANT,
106 : SRS_PT_MILLER_CYLINDRICAL,
107 : SRS_PT_NEW_ZEALAND_MAP_GRID,
108 : SRS_PT_SINUSOIDAL,
109 : SRS_PT_STEREOGRAPHIC,
110 : SRS_PT_GNOMONIC,
111 : SRS_PT_ORTHOGRAPHIC,
112 : SRS_PT_POLYCONIC,
113 : SRS_PT_VANDERGRINTEN,
114 : SRS_PT_GEOSTATIONARY_SATELLITE,
115 : SRS_PT_TWO_POINT_EQUIDISTANT,
116 : SRS_PT_IMW_POLYCONIC,
117 : SRS_PT_WAGNER_I,
118 : SRS_PT_WAGNER_II,
119 : SRS_PT_WAGNER_III,
120 : SRS_PT_WAGNER_IV,
121 : SRS_PT_WAGNER_V,
122 : SRS_PT_WAGNER_VI,
123 : SRS_PT_WAGNER_VII,
124 : SRS_PT_GAUSSSCHREIBERTMERCATOR,
125 : NULL
126 : };
127 :
128 : static const char *papszProjectionUnsupported[] =
129 : {
130 : SRS_PT_NEW_ZEALAND_MAP_GRID,
131 : SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED,
132 : SRS_PT_TUNISIA_MINING_GRID,
133 : NULL
134 : };
135 :
136 : /*
137 : ** List of supported projections with the PARAMETERS[] acceptable for each.
138 : */
139 : static const char *papszProjWithParms[] = {
140 :
141 : SRS_PT_TRANSVERSE_MERCATOR,
142 : SRS_PP_LATITUDE_OF_ORIGIN,
143 : SRS_PP_CENTRAL_MERIDIAN,
144 : SRS_PP_SCALE_FACTOR,
145 : SRS_PP_FALSE_EASTING,
146 : SRS_PP_FALSE_NORTHING,
147 : NULL,
148 :
149 : SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED,
150 : SRS_PP_LATITUDE_OF_ORIGIN,
151 : SRS_PP_CENTRAL_MERIDIAN,
152 : SRS_PP_SCALE_FACTOR,
153 : SRS_PP_FALSE_EASTING,
154 : SRS_PP_FALSE_NORTHING,
155 : NULL,
156 :
157 : SRS_PT_TUNISIA_MINING_GRID,
158 : SRS_PP_LATITUDE_OF_ORIGIN,
159 : SRS_PP_CENTRAL_MERIDIAN,
160 : SRS_PP_FALSE_EASTING,
161 : SRS_PP_FALSE_NORTHING,
162 : NULL,
163 :
164 : SRS_PT_ALBERS_CONIC_EQUAL_AREA,
165 : SRS_PP_LATITUDE_OF_CENTER,
166 : SRS_PP_LONGITUDE_OF_CENTER,
167 : SRS_PP_STANDARD_PARALLEL_1,
168 : SRS_PP_STANDARD_PARALLEL_2,
169 : SRS_PP_FALSE_EASTING,
170 : SRS_PP_FALSE_NORTHING,
171 : NULL,
172 :
173 : SRS_PT_AZIMUTHAL_EQUIDISTANT,
174 : SRS_PP_LATITUDE_OF_CENTER,
175 : SRS_PP_LONGITUDE_OF_CENTER,
176 : SRS_PP_FALSE_EASTING,
177 : SRS_PP_FALSE_NORTHING,
178 : NULL,
179 :
180 : SRS_PT_BONNE,
181 : SRS_PP_STANDARD_PARALLEL_1,
182 : SRS_PP_CENTRAL_MERIDIAN,
183 : SRS_PP_FALSE_EASTING,
184 : SRS_PP_FALSE_NORTHING,
185 : NULL,
186 :
187 : SRS_PT_CYLINDRICAL_EQUAL_AREA,
188 : SRS_PP_STANDARD_PARALLEL_1,
189 : SRS_PP_CENTRAL_MERIDIAN,
190 : SRS_PP_FALSE_EASTING,
191 : SRS_PP_FALSE_NORTHING,
192 : NULL,
193 :
194 : SRS_PT_CASSINI_SOLDNER,
195 : SRS_PP_LATITUDE_OF_ORIGIN,
196 : SRS_PP_CENTRAL_MERIDIAN,
197 : SRS_PP_FALSE_EASTING,
198 : SRS_PP_FALSE_NORTHING,
199 : NULL,
200 :
201 : SRS_PT_EQUIDISTANT_CONIC,
202 : SRS_PP_STANDARD_PARALLEL_1,
203 : SRS_PP_STANDARD_PARALLEL_2,
204 : SRS_PP_LATITUDE_OF_CENTER,
205 : SRS_PP_LONGITUDE_OF_CENTER,
206 : SRS_PP_FALSE_EASTING,
207 : SRS_PP_FALSE_NORTHING,
208 : NULL,
209 :
210 : SRS_PT_ECKERT_IV,
211 : SRS_PP_CENTRAL_MERIDIAN,
212 : SRS_PP_FALSE_EASTING,
213 : SRS_PP_FALSE_NORTHING,
214 : NULL,
215 :
216 : SRS_PT_ECKERT_VI,
217 : SRS_PP_CENTRAL_MERIDIAN,
218 : SRS_PP_FALSE_EASTING,
219 : SRS_PP_FALSE_NORTHING,
220 : NULL,
221 :
222 : SRS_PT_EQUIRECTANGULAR,
223 : SRS_PP_LATITUDE_OF_ORIGIN,
224 : SRS_PP_CENTRAL_MERIDIAN,
225 : SRS_PP_STANDARD_PARALLEL_1,
226 : SRS_PP_FALSE_EASTING,
227 : SRS_PP_FALSE_NORTHING,
228 : NULL,
229 :
230 : SRS_PT_GALL_STEREOGRAPHIC,
231 : SRS_PP_CENTRAL_MERIDIAN,
232 : SRS_PP_FALSE_EASTING,
233 : SRS_PP_FALSE_NORTHING,
234 : NULL,
235 :
236 : SRS_PT_GNOMONIC,
237 : SRS_PP_LATITUDE_OF_ORIGIN,
238 : SRS_PP_CENTRAL_MERIDIAN,
239 : SRS_PP_FALSE_EASTING,
240 : SRS_PP_FALSE_NORTHING,
241 : NULL,
242 :
243 : SRS_PT_HOTINE_OBLIQUE_MERCATOR,
244 : SRS_PP_LATITUDE_OF_CENTER,
245 : SRS_PP_LONGITUDE_OF_CENTER,
246 : SRS_PP_AZIMUTH,
247 : SRS_PP_RECTIFIED_GRID_ANGLE,
248 : SRS_PP_SCALE_FACTOR,
249 : SRS_PP_FALSE_EASTING,
250 : SRS_PP_FALSE_NORTHING,
251 : NULL,
252 :
253 : SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN,
254 : SRS_PP_LATITUDE_OF_CENTER,
255 : SRS_PP_LATITUDE_OF_POINT_1,
256 : SRS_PP_LONGITUDE_OF_POINT_1,
257 : SRS_PP_LATITUDE_OF_POINT_2,
258 : SRS_PP_LONGITUDE_OF_POINT_2
259 : SRS_PP_SCALE_FACTOR,
260 : SRS_PP_FALSE_EASTING,
261 : SRS_PP_FALSE_NORTHING,
262 : NULL,
263 :
264 : SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA,
265 : SRS_PP_LATITUDE_OF_CENTER,
266 : SRS_PP_LONGITUDE_OF_CENTER,
267 : SRS_PP_FALSE_EASTING,
268 : SRS_PP_FALSE_NORTHING,
269 : NULL,
270 :
271 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP,
272 : SRS_PP_STANDARD_PARALLEL_1,
273 : SRS_PP_STANDARD_PARALLEL_2,
274 : SRS_PP_LATITUDE_OF_ORIGIN,
275 : SRS_PP_CENTRAL_MERIDIAN,
276 : SRS_PP_FALSE_EASTING,
277 : SRS_PP_FALSE_NORTHING,
278 : NULL,
279 :
280 : SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
281 : SRS_PP_LATITUDE_OF_ORIGIN,
282 : SRS_PP_CENTRAL_MERIDIAN,
283 : SRS_PP_SCALE_FACTOR,
284 : SRS_PP_FALSE_EASTING,
285 : SRS_PP_FALSE_NORTHING,
286 : NULL,
287 :
288 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM,
289 : SRS_PP_STANDARD_PARALLEL_1,
290 : SRS_PP_STANDARD_PARALLEL_2,
291 : SRS_PP_LATITUDE_OF_ORIGIN,
292 : SRS_PP_CENTRAL_MERIDIAN,
293 : SRS_PP_FALSE_EASTING,
294 : SRS_PP_FALSE_NORTHING,
295 : NULL,
296 :
297 : SRS_PT_MILLER_CYLINDRICAL,
298 : SRS_PP_LATITUDE_OF_CENTER,
299 : SRS_PP_LONGITUDE_OF_CENTER,
300 : SRS_PP_FALSE_EASTING,
301 : SRS_PP_FALSE_NORTHING,
302 : NULL,
303 :
304 : SRS_PT_MERCATOR_1SP,
305 : SRS_PP_LATITUDE_OF_ORIGIN,
306 : SRS_PP_CENTRAL_MERIDIAN,
307 : SRS_PP_SCALE_FACTOR,
308 : SRS_PP_FALSE_EASTING,
309 : SRS_PP_FALSE_NORTHING,
310 : NULL,
311 :
312 : SRS_PT_MERCATOR_2SP,
313 : SRS_PP_STANDARD_PARALLEL_1,
314 : SRS_PP_LATITUDE_OF_ORIGIN,
315 : SRS_PP_CENTRAL_MERIDIAN,
316 : SRS_PP_FALSE_EASTING,
317 : SRS_PP_FALSE_NORTHING,
318 : NULL,
319 :
320 : SRS_PT_MOLLWEIDE,
321 : SRS_PP_CENTRAL_MERIDIAN,
322 : SRS_PP_FALSE_EASTING,
323 : SRS_PP_FALSE_NORTHING,
324 : NULL,
325 :
326 : SRS_PT_NEW_ZEALAND_MAP_GRID,
327 : SRS_PP_LATITUDE_OF_ORIGIN,
328 : SRS_PP_CENTRAL_MERIDIAN,
329 : SRS_PP_FALSE_EASTING,
330 : SRS_PP_FALSE_NORTHING,
331 : NULL,
332 :
333 : SRS_PT_ORTHOGRAPHIC,
334 : SRS_PP_LATITUDE_OF_ORIGIN,
335 : SRS_PP_CENTRAL_MERIDIAN,
336 : SRS_PP_FALSE_EASTING,
337 : SRS_PP_FALSE_NORTHING,
338 : NULL,
339 :
340 : SRS_PT_POLYCONIC,
341 : SRS_PP_LATITUDE_OF_ORIGIN,
342 : SRS_PP_CENTRAL_MERIDIAN,
343 : SRS_PP_FALSE_EASTING,
344 : SRS_PP_FALSE_NORTHING,
345 : NULL,
346 :
347 : SRS_PT_POLAR_STEREOGRAPHIC,
348 : SRS_PP_LATITUDE_OF_ORIGIN,
349 : SRS_PP_CENTRAL_MERIDIAN,
350 : SRS_PP_SCALE_FACTOR,
351 : SRS_PP_FALSE_EASTING,
352 : SRS_PP_FALSE_NORTHING,
353 : NULL,
354 :
355 : SRS_PT_ROBINSON,
356 : SRS_PP_LONGITUDE_OF_CENTER,
357 : SRS_PP_FALSE_EASTING,
358 : SRS_PP_FALSE_NORTHING,
359 : NULL,
360 :
361 : SRS_PT_SINUSOIDAL,
362 : SRS_PP_LONGITUDE_OF_CENTER,
363 : SRS_PP_FALSE_EASTING,
364 : SRS_PP_FALSE_NORTHING,
365 : NULL,
366 :
367 : SRS_PT_STEREOGRAPHIC,
368 : SRS_PP_LATITUDE_OF_ORIGIN,
369 : SRS_PP_CENTRAL_MERIDIAN,
370 : SRS_PP_SCALE_FACTOR,
371 : SRS_PP_FALSE_EASTING,
372 : SRS_PP_FALSE_NORTHING,
373 : NULL,
374 :
375 : SRS_PT_SWISS_OBLIQUE_CYLINDRICAL,
376 : SRS_PP_LATITUDE_OF_CENTER,
377 : SRS_PP_CENTRAL_MERIDIAN,
378 : SRS_PP_FALSE_EASTING,
379 : SRS_PP_FALSE_NORTHING,
380 : NULL,
381 :
382 : SRS_PT_OBLIQUE_STEREOGRAPHIC,
383 : SRS_PP_LATITUDE_OF_ORIGIN,
384 : SRS_PP_CENTRAL_MERIDIAN,
385 : SRS_PP_SCALE_FACTOR,
386 : SRS_PP_FALSE_EASTING,
387 : SRS_PP_FALSE_NORTHING,
388 : NULL,
389 :
390 : SRS_PT_VANDERGRINTEN,
391 : SRS_PP_CENTRAL_MERIDIAN,
392 : SRS_PP_FALSE_EASTING,
393 : SRS_PP_FALSE_NORTHING,
394 : NULL,
395 :
396 : SRS_PT_GEOSTATIONARY_SATELLITE,
397 : SRS_PP_CENTRAL_MERIDIAN,
398 : SRS_PP_SATELLITE_HEIGHT,
399 : SRS_PP_FALSE_EASTING,
400 : SRS_PP_FALSE_NORTHING,
401 : NULL,
402 :
403 : SRS_PT_KROVAK,
404 : SRS_PP_LATITUDE_OF_CENTER,
405 : SRS_PP_LONGITUDE_OF_CENTER,
406 : SRS_PP_AZIMUTH,
407 : SRS_PP_PSEUDO_STD_PARALLEL_1,
408 : SRS_PP_SCALE_FACTOR,
409 : SRS_PP_FALSE_EASTING,
410 : SRS_PP_FALSE_NORTHING,
411 : NULL,
412 :
413 : SRS_PT_TWO_POINT_EQUIDISTANT,
414 : SRS_PP_LATITUDE_OF_1ST_POINT,
415 : SRS_PP_LONGITUDE_OF_1ST_POINT,
416 : SRS_PP_LATITUDE_OF_2ND_POINT,
417 : SRS_PP_LONGITUDE_OF_2ND_POINT,
418 : SRS_PP_FALSE_EASTING,
419 : SRS_PP_FALSE_NORTHING,
420 : NULL,
421 :
422 : SRS_PT_IMW_POLYCONIC,
423 : SRS_PP_LATITUDE_OF_1ST_POINT,
424 : SRS_PP_LATITUDE_OF_2ND_POINT,
425 : SRS_PP_CENTRAL_MERIDIAN,
426 : SRS_PP_FALSE_EASTING,
427 : SRS_PP_FALSE_NORTHING,
428 : NULL,
429 :
430 : SRS_PT_WAGNER_I,
431 : SRS_PP_FALSE_EASTING,
432 : SRS_PP_FALSE_NORTHING,
433 : NULL,
434 :
435 : SRS_PT_WAGNER_II,
436 : SRS_PP_FALSE_EASTING,
437 : SRS_PP_FALSE_NORTHING,
438 : NULL,
439 :
440 : SRS_PT_WAGNER_III,
441 : SRS_PP_LATITUDE_OF_ORIGIN,
442 : SRS_PP_FALSE_EASTING,
443 : SRS_PP_FALSE_NORTHING,
444 : NULL,
445 :
446 : SRS_PT_WAGNER_IV,
447 : SRS_PP_FALSE_EASTING,
448 : SRS_PP_FALSE_NORTHING,
449 : NULL,
450 :
451 : SRS_PT_WAGNER_V,
452 : SRS_PP_FALSE_EASTING,
453 : SRS_PP_FALSE_NORTHING,
454 : NULL,
455 :
456 : SRS_PT_WAGNER_VI,
457 : SRS_PP_FALSE_EASTING,
458 : SRS_PP_FALSE_NORTHING,
459 : NULL,
460 :
461 : SRS_PT_WAGNER_VII,
462 : SRS_PP_FALSE_EASTING,
463 : SRS_PP_FALSE_NORTHING,
464 : NULL,
465 :
466 : SRS_PT_GAUSSSCHREIBERTMERCATOR,
467 : SRS_PP_LATITUDE_OF_ORIGIN,
468 : SRS_PP_CENTRAL_MERIDIAN,
469 : SRS_PP_SCALE_FACTOR,
470 : SRS_PP_FALSE_EASTING,
471 : SRS_PP_FALSE_NORTHING,
472 : NULL,
473 :
474 : NULL
475 : };
476 :
477 : static const char *papszAliasGroupList[] = {
478 : SRS_PP_LATITUDE_OF_ORIGIN,
479 : SRS_PP_LATITUDE_OF_CENTER,
480 : NULL,
481 : SRS_PP_CENTRAL_MERIDIAN,
482 : SRS_PP_LONGITUDE_OF_CENTER,
483 : SRS_PP_LONGITUDE_OF_ORIGIN,
484 : NULL,
485 : NULL
486 : };
487 :
488 :
489 : /************************************************************************/
490 : /* Validate() */
491 : /************************************************************************/
492 :
493 : /**
494 : * \brief Validate SRS tokens.
495 : *
496 : * This method attempts to verify that the spatial reference system is
497 : * well formed, and consists of known tokens. The validation is not
498 : * comprehensive.
499 : *
500 : * This method is the same as the C function OSRValidate().
501 : *
502 : * @return OGRERR_NONE if all is fine, OGRERR_CORRUPT_DATA if the SRS is
503 : * not well formed, and OGRERR_UNSUPPORTED_SRS if the SRS is well formed,
504 : * but contains non-standard PROJECTION[] values.
505 : */
506 :
507 2 : OGRErr OGRSpatialReference::Validate()
508 :
509 : {
510 : /* -------------------------------------------------------------------- */
511 : /* Validate root node. */
512 : /* -------------------------------------------------------------------- */
513 2 : if( poRoot == NULL )
514 : {
515 : CPLDebug( "OGRSpatialReference::Validate",
516 0 : "No root pointer.\n" );
517 0 : return OGRERR_CORRUPT_DATA;
518 : }
519 :
520 2 : if( !EQUAL(poRoot->GetValue(),"GEOGCS")
521 : && !EQUAL(poRoot->GetValue(),"PROJCS")
522 : && !EQUAL(poRoot->GetValue(),"LOCAL_CS")
523 : && !EQUAL(poRoot->GetValue(),"GEOCCS") )
524 : {
525 : CPLDebug( "OGRSpatialReference::Validate",
526 : "Unrecognised root node `%s'\n",
527 0 : poRoot->GetValue() );
528 0 : return OGRERR_CORRUPT_DATA;
529 : }
530 :
531 : /* -------------------------------------------------------------------- */
532 : /* For a PROJCS, validate subparameters (other than GEOGCS). */
533 : /* -------------------------------------------------------------------- */
534 2 : if( EQUAL(poRoot->GetValue(),"PROJCS") )
535 : {
536 : OGR_SRSNode *poNode;
537 : int i;
538 :
539 22 : for( i = 1; i < poRoot->GetChildCount(); i++ )
540 : {
541 20 : poNode = poRoot->GetChild(i);
542 :
543 20 : if( EQUAL(poNode->GetValue(),"GEOGCS") )
544 : {
545 : /* validated elsewhere */
546 : }
547 18 : else if( EQUAL(poNode->GetValue(),"UNIT") )
548 : {
549 2 : if( poNode->GetChildCount() != 2
550 : && poNode->GetChildCount() != 3 )
551 : {
552 : CPLDebug( "OGRSpatialReference::Validate",
553 : "UNIT has wrong number of children (%d), not 2.\n",
554 0 : poNode->GetChildCount() );
555 0 : return OGRERR_CORRUPT_DATA;
556 : }
557 2 : else if( CPLAtof(poNode->GetChild(1)->GetValue()) == 0.0 )
558 : {
559 : CPLDebug( "OGRSpatialReference::Validate",
560 : "UNIT does not appear to have meaningful"
561 : "coefficient (%s).\n",
562 0 : poNode->GetChild(1)->GetValue() );
563 0 : return OGRERR_CORRUPT_DATA;
564 : }
565 : }
566 16 : else if( EQUAL(poNode->GetValue(),"PARAMETER") )
567 : {
568 10 : if( poNode->GetChildCount() != 2 )
569 : {
570 : CPLDebug( "OGRSpatialReference::Validate",
571 : "PARAMETER has wrong number of children (%d),"
572 : "not 2 as expected.\n",
573 0 : poNode->GetChildCount() );
574 :
575 0 : return OGRERR_CORRUPT_DATA;
576 : }
577 10 : else if( CSLFindString( (char **)papszParameters,
578 : poNode->GetChild(0)->GetValue()) == -1)
579 : {
580 : CPLDebug( "OGRSpatialReference::Validate",
581 : "Unrecognised PARAMETER `%s'.\n",
582 0 : poNode->GetChild(0)->GetValue() );
583 :
584 0 : return OGRERR_UNSUPPORTED_SRS;
585 : }
586 : }
587 6 : else if( EQUAL(poNode->GetValue(),"PROJECTION") )
588 : {
589 2 : if( poNode->GetChildCount() != 1 )
590 : {
591 : CPLDebug( "OGRSpatialReference::Validate",
592 : "PROJECTION has wrong number of children (%d),"
593 : "not 1 as expected.\n",
594 0 : poNode->GetChildCount() );
595 :
596 0 : return OGRERR_CORRUPT_DATA;
597 : }
598 2 : else if( CSLFindString( (char **)papszProjectionSupported,
599 : poNode->GetChild(0)->GetValue()) == -1
600 : && CSLFindString( (char **)papszProjectionUnsupported,
601 : poNode->GetChild(0)->GetValue()) == -1)
602 : {
603 : CPLDebug( "OGRSpatialReference::Validate",
604 : "Unrecognised PROJECTION `%s'.\n",
605 0 : poNode->GetChild(0)->GetValue() );
606 :
607 0 : return OGRERR_UNSUPPORTED_SRS;
608 : }
609 2 : else if( CSLFindString( (char **)papszProjectionSupported,
610 : poNode->GetChild(0)->GetValue()) == -1)
611 : {
612 : CPLDebug( "OGRSpatialReference::Validate",
613 : "Unsupported, but recognised PROJECTION `%s'.\n",
614 0 : poNode->GetChild(0)->GetValue() );
615 :
616 0 : return OGRERR_UNSUPPORTED_SRS;
617 : }
618 : }
619 4 : else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
620 : {
621 1 : if( poNode->GetChildCount() != 2 )
622 : {
623 : CPLDebug( "OGRSpatialReference::Validate",
624 : "AUTHORITY has wrong number of children (%d), not 2.\n",
625 0 : poNode->GetChildCount() );
626 0 : return OGRERR_CORRUPT_DATA;
627 : }
628 : }
629 3 : else if( EQUAL(poNode->GetValue(),"AXIS") )
630 : {
631 2 : if( poNode->GetChildCount() != 2 )
632 : {
633 : CPLDebug( "OGRSpatialReference::Validate",
634 : "AXIS has wrong number of children (%d), not 2.\n",
635 0 : poNode->GetChildCount() );
636 0 : return OGRERR_CORRUPT_DATA;
637 : }
638 : }
639 1 : else if( EQUAL(poNode->GetValue(),"EXTENSION") )
640 : {
641 : // We do not try to control the sub-organization of
642 : // EXTENSION nodes.
643 : }
644 : else
645 : {
646 : CPLDebug( "OGRSpatialReference::Validate",
647 : "Unexpected child for PROJCS `%s'.\n",
648 0 : poNode->GetValue() );
649 :
650 0 : return OGRERR_CORRUPT_DATA;
651 : }
652 : }
653 : }
654 :
655 : /* -------------------------------------------------------------------- */
656 : /* Validate GEOGCS if found. */
657 : /* -------------------------------------------------------------------- */
658 2 : OGR_SRSNode *poGEOGCS = poRoot->GetNode( "GEOGCS" );
659 :
660 2 : if( poGEOGCS != NULL )
661 : {
662 : OGR_SRSNode *poNode;
663 : int i;
664 :
665 9 : for( i = 1; i < poGEOGCS->GetChildCount(); i++ )
666 : {
667 7 : poNode = poGEOGCS->GetChild(i);
668 :
669 7 : if( EQUAL(poNode->GetValue(),"DATUM") )
670 : {
671 : /* validated elsewhere */
672 : }
673 5 : else if( EQUAL(poNode->GetValue(),"PRIMEM") )
674 : {
675 2 : if( poNode->GetChildCount() < 2
676 : || poNode->GetChildCount() > 3 )
677 : {
678 : CPLDebug( "OGRSpatialReference::Validate",
679 : "PRIMEM has wrong number of children (%d),"
680 : "not 2 or 3 as expected.\n",
681 0 : poNode->GetChildCount() );
682 :
683 0 : return OGRERR_CORRUPT_DATA;
684 : }
685 : }
686 3 : else if( EQUAL(poNode->GetValue(),"UNIT") )
687 : {
688 2 : if( poNode->GetChildCount() != 2
689 : && poNode->GetChildCount() != 3 )
690 : {
691 : CPLDebug( "OGRSpatialReference::Validate",
692 : "UNIT has wrong number of children (%d), not 2 or 3.\n",
693 0 : poNode->GetChildCount() );
694 0 : return OGRERR_CORRUPT_DATA;
695 : }
696 2 : else if( CPLAtof(poNode->GetChild(1)->GetValue()) == 0.0 )
697 : {
698 : CPLDebug( "OGRSpatialReference::Validate",
699 : "UNIT does not appear to have meaningful"
700 : "coefficient (%s).\n",
701 0 : poNode->GetChild(1)->GetValue() );
702 0 : return OGRERR_CORRUPT_DATA;
703 : }
704 : }
705 1 : else if( EQUAL(poNode->GetValue(),"AXIS") )
706 : {
707 0 : if( poNode->GetChildCount() != 2 )
708 : {
709 : CPLDebug( "OGRSpatialReference::Validate",
710 : "AXIS has wrong number of children (%d), not 2.\n",
711 0 : poNode->GetChildCount() );
712 0 : return OGRERR_CORRUPT_DATA;
713 : }
714 : }
715 1 : else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
716 : {
717 1 : if( poNode->GetChildCount() != 2 )
718 : {
719 : CPLDebug( "OGRSpatialReference::Validate",
720 : "AUTHORITY has wrong number of children (%d), not 2.\n",
721 0 : poNode->GetChildCount() );
722 0 : return OGRERR_CORRUPT_DATA;
723 : }
724 : }
725 : else
726 : {
727 : CPLDebug( "OGRSpatialReference::Validate",
728 : "Unexpected child for GEOGCS `%s'.\n",
729 0 : poNode->GetValue() );
730 :
731 0 : return OGRERR_CORRUPT_DATA;
732 : }
733 : }
734 :
735 2 : if( poGEOGCS->GetNode("DATUM") == NULL )
736 : {
737 : CPLDebug( "OGRSpatialReference::Validate",
738 0 : "No DATUM child in GEOGCS.\n" );
739 :
740 0 : return OGRERR_CORRUPT_DATA;
741 : }
742 : }
743 :
744 : /* -------------------------------------------------------------------- */
745 : /* Validate DATUM/SPHEROID. */
746 : /* -------------------------------------------------------------------- */
747 2 : OGR_SRSNode *poDATUM = poRoot->GetNode( "DATUM" );
748 :
749 2 : if( poDATUM != NULL )
750 : {
751 : OGR_SRSNode *poSPHEROID;
752 2 : int bGotSpheroid = FALSE;
753 : int i;
754 :
755 2 : if( poDATUM->GetChildCount() == 0 )
756 : {
757 : CPLDebug( "OGRSpatialReference::Validate",
758 0 : "DATUM has no children." );
759 :
760 0 : return OGRERR_CORRUPT_DATA;
761 : }
762 :
763 6 : for( i = 1; i < poDATUM->GetChildCount(); i++ )
764 : {
765 : OGR_SRSNode *poNode;
766 4 : poNode = poDATUM->GetChild(i);
767 :
768 4 : if( EQUAL(poNode->GetValue(),"SPHEROID") )
769 : {
770 2 : poSPHEROID = poDATUM->GetChild(1);
771 2 : bGotSpheroid = TRUE;
772 :
773 2 : if( poSPHEROID->GetChildCount() != 3
774 : && poSPHEROID->GetChildCount() != 4 )
775 : {
776 : CPLDebug( "OGRSpatialReference::Validate",
777 : "SPHEROID has wrong number of children (%d),"
778 : "not 3 or 4 as expected.\n",
779 0 : poSPHEROID->GetChildCount() );
780 :
781 0 : return OGRERR_CORRUPT_DATA;
782 : }
783 2 : else if( CPLAtof(poSPHEROID->GetChild(1)->GetValue()) == 0.0 )
784 : {
785 : CPLDebug( "OGRSpatialReference::Validate",
786 : "SPHEROID semi-major axis is zero (%s)!\n",
787 0 : poSPHEROID->GetChild(1)->GetValue() );
788 0 : return OGRERR_CORRUPT_DATA;
789 : }
790 : }
791 2 : else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
792 : {
793 1 : if( poNode->GetChildCount() != 2 )
794 : {
795 : CPLDebug( "OGRSpatialReference::Validate",
796 : "AUTHORITY has wrong number of children (%d), not 2.\n",
797 0 : poNode->GetChildCount() );
798 0 : return OGRERR_CORRUPT_DATA;
799 : }
800 : }
801 1 : else if( EQUAL(poNode->GetValue(),"TOWGS84") )
802 : {
803 1 : if( poNode->GetChildCount() != 3
804 : && poNode->GetChildCount() != 7)
805 : {
806 : CPLDebug( "OGRSpatialReference::Validate",
807 : "TOWGS84 has wrong number of children (%d), not 3 or 7.\n",
808 0 : poNode->GetChildCount() );
809 0 : return OGRERR_CORRUPT_DATA;
810 : }
811 : }
812 : else
813 : {
814 : CPLDebug( "OGRSpatialReference::Validate",
815 : "Unexpected child for DATUM `%s'.\n",
816 0 : poNode->GetValue() );
817 :
818 0 : return OGRERR_CORRUPT_DATA;
819 : }
820 : }
821 :
822 2 : if( !bGotSpheroid )
823 : {
824 : CPLDebug( "OGRSpatialReference::Validate",
825 0 : "No SPHEROID child in DATUM.\n" );
826 :
827 0 : return OGRERR_CORRUPT_DATA;
828 : }
829 : }
830 :
831 : /* -------------------------------------------------------------------- */
832 : /* If this is projected, try to validate the detailed set of */
833 : /* parameters used for the projection. */
834 : /* -------------------------------------------------------------------- */
835 : OGRErr eErr;
836 :
837 2 : eErr = ValidateProjection();
838 2 : if( eErr != OGRERR_NONE )
839 0 : return eErr;
840 :
841 : /* -------------------------------------------------------------------- */
842 : /* Final check. */
843 : /* -------------------------------------------------------------------- */
844 2 : if( EQUAL(poRoot->GetValue(),"GEOCCS") )
845 0 : return OGRERR_UNSUPPORTED_SRS;
846 :
847 2 : return OGRERR_NONE;
848 : }
849 :
850 : /************************************************************************/
851 : /* OSRValidate() */
852 : /************************************************************************/
853 : /**
854 : * \brief Validate SRS tokens.
855 : *
856 : * This function is the same as the C++ method OGRSpatialReference::Validate().
857 : */
858 2 : OGRErr OSRValidate( OGRSpatialReferenceH hSRS )
859 :
860 : {
861 2 : VALIDATE_POINTER1( hSRS, "OSRValidate", CE_Failure );
862 :
863 2 : return ((OGRSpatialReference *) hSRS)->Validate();
864 : }
865 :
866 : /************************************************************************/
867 : /* IsAliasFor() */
868 : /************************************************************************/
869 :
870 : /**
871 : * \brief Return whether the first string passed in an acceptable alias for the
872 : * second string according to the AliasGroupList
873 : *
874 : * @param pszParm1 first string
875 : * @param pszParm2 second string
876 : *
877 : * @return TRUE if both strings are aliases according to the AliasGroupList, FALSE otherwise
878 : */
879 : int OGRSpatialReference::IsAliasFor( const char *pszParm1,
880 0 : const char *pszParm2 )
881 :
882 : {
883 : int iGroup;
884 :
885 : /* -------------------------------------------------------------------- */
886 : /* Look for a group containing pszParm1. */
887 : /* -------------------------------------------------------------------- */
888 0 : for( iGroup = 0; papszAliasGroupList[iGroup] != NULL; iGroup++ )
889 : {
890 : int i;
891 :
892 0 : for( i = iGroup; papszAliasGroupList[i] != NULL; i++ )
893 : {
894 0 : if( EQUAL(pszParm1,papszAliasGroupList[i]) )
895 0 : break;
896 : }
897 :
898 0 : if( papszAliasGroupList[i] == NULL )
899 0 : iGroup = i;
900 : else
901 0 : break;
902 : }
903 :
904 : /* -------------------------------------------------------------------- */
905 : /* Does this group also contain pszParm2? */
906 : /* -------------------------------------------------------------------- */
907 0 : while( papszAliasGroupList[iGroup] != NULL )
908 : {
909 0 : if( EQUAL(papszAliasGroupList[iGroup++],pszParm2) )
910 0 : return TRUE;
911 : }
912 :
913 0 : return FALSE;
914 : }
915 :
916 : /************************************************************************/
917 : /* ValidateProjection() */
918 : /************************************************************************/
919 :
920 : /**
921 : * \brief Validate the current PROJECTION's arguments.
922 : *
923 : * @return OGRERR_NONE if the PROJECTION's arguments validate, an error code
924 : * otherwise
925 : */
926 2 : OGRErr OGRSpatialReference::ValidateProjection()
927 :
928 : {
929 2 : OGR_SRSNode *poPROJCS = poRoot->GetNode( "PROJCS" );
930 :
931 2 : if( poPROJCS == NULL )
932 0 : return OGRERR_NONE;
933 :
934 2 : if( poPROJCS->GetNode( "PROJECTION" ) == NULL )
935 : {
936 : CPLDebug( "OGRSpatialReference::Validate",
937 0 : "PROJCS does not have PROJECTION subnode." );
938 0 : return OGRERR_CORRUPT_DATA;
939 : }
940 :
941 : /* -------------------------------------------------------------------- */
942 : /* Find the matching group in the proj and parms table. */
943 : /* -------------------------------------------------------------------- */
944 : const char *pszProjection;
945 : int iOffset;
946 :
947 2 : pszProjection = poPROJCS->GetNode("PROJECTION")->GetChild(0)->GetValue();
948 :
949 26 : for( iOffset = 0;
950 : papszProjWithParms[iOffset] != NULL
951 : && !EQUAL(papszProjWithParms[iOffset],pszProjection); )
952 : {
953 170 : while( papszProjWithParms[iOffset] != NULL )
954 126 : iOffset++;
955 22 : iOffset++;
956 : }
957 :
958 2 : if( papszProjWithParms[iOffset] == NULL )
959 0 : return OGRERR_UNSUPPORTED_SRS;
960 :
961 2 : iOffset++;
962 :
963 : /* -------------------------------------------------------------------- */
964 : /* Check all parameters, and verify they are in the permitted */
965 : /* list. */
966 : /* -------------------------------------------------------------------- */
967 : int iNode;
968 :
969 24 : for( iNode = 0; iNode < poPROJCS->GetChildCount(); iNode++ )
970 : {
971 22 : OGR_SRSNode *poParm = poPROJCS->GetChild(iNode);
972 : int i;
973 : const char *pszParmName;
974 :
975 22 : if( !EQUAL(poParm->GetValue(),"PARAMETER") )
976 12 : continue;
977 :
978 10 : pszParmName = poParm->GetChild(0)->GetValue();
979 :
980 30 : for( i = iOffset; papszProjWithParms[i] != NULL; i++ )
981 : {
982 30 : if( EQUAL(papszProjWithParms[i],pszParmName) )
983 10 : break;
984 : }
985 :
986 : /* This parameter is not an exact match, is it an alias? */
987 10 : if( papszProjWithParms[i] == NULL )
988 : {
989 0 : for( i = iOffset; papszProjWithParms[i] != NULL; i++ )
990 : {
991 0 : if( IsAliasFor(papszProjWithParms[i],pszParmName) )
992 0 : break;
993 : }
994 :
995 0 : if( papszProjWithParms[i] == NULL )
996 : {
997 : CPLDebug( "OGRSpatialReference::Validate",
998 : "PARAMETER %s for PROJECTION %s is not permitted.",
999 0 : pszParmName, pszProjection );
1000 0 : return OGRERR_CORRUPT_DATA;
1001 : }
1002 : else
1003 : {
1004 : CPLDebug( "OGRSpatialReference::Validate",
1005 : "PARAMETER %s for PROJECTION %s is an alias for %s.",
1006 : pszParmName, pszProjection,
1007 0 : papszProjWithParms[i] );
1008 0 : return OGRERR_CORRUPT_DATA;
1009 : }
1010 : }
1011 : }
1012 :
1013 2 : return OGRERR_NONE;
1014 : }
|