1 : /******************************************************************************
2 : * $Id: ogr_srs_validate.cpp 22786 2011-07-23 21:17:24Z 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 22786 2011-07-23 21:17:24Z 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_MOLLWEIDE,
93 : SRS_PT_ROBINSON,
94 : SRS_PT_ALBERS_CONIC_EQUAL_AREA,
95 : SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
96 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP,
97 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM,
98 : SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA,
99 : SRS_PT_TRANSVERSE_MERCATOR,
100 : SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED,
101 : SRS_PT_OBLIQUE_STEREOGRAPHIC,
102 : SRS_PT_POLAR_STEREOGRAPHIC,
103 : SRS_PT_HOTINE_OBLIQUE_MERCATOR,
104 : SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN,
105 : SRS_PT_LABORDE_OBLIQUE_MERCATOR,
106 : SRS_PT_SWISS_OBLIQUE_CYLINDRICAL,
107 : SRS_PT_AZIMUTHAL_EQUIDISTANT,
108 : SRS_PT_MILLER_CYLINDRICAL,
109 : SRS_PT_NEW_ZEALAND_MAP_GRID,
110 : SRS_PT_SINUSOIDAL,
111 : SRS_PT_STEREOGRAPHIC,
112 : SRS_PT_GNOMONIC,
113 : SRS_PT_GALL_STEREOGRAPHIC,
114 : SRS_PT_ORTHOGRAPHIC,
115 : SRS_PT_POLYCONIC,
116 : SRS_PT_VANDERGRINTEN,
117 : SRS_PT_GEOSTATIONARY_SATELLITE,
118 : SRS_PT_TWO_POINT_EQUIDISTANT,
119 : SRS_PT_IMW_POLYCONIC,
120 : SRS_PT_WAGNER_I,
121 : SRS_PT_WAGNER_II,
122 : SRS_PT_WAGNER_III,
123 : SRS_PT_WAGNER_IV,
124 : SRS_PT_WAGNER_V,
125 : SRS_PT_WAGNER_VI,
126 : SRS_PT_WAGNER_VII,
127 : SRS_PT_GAUSSSCHREIBERTMERCATOR,
128 : SRS_PT_KROVAK,
129 : SRS_PT_CYLINDRICAL_EQUAL_AREA,
130 : SRS_PT_GOODE_HOMOLOSINE,
131 : SRS_PT_IGH,
132 : NULL
133 : };
134 :
135 : static const char *papszProjectionUnsupported[] =
136 : {
137 : SRS_PT_NEW_ZEALAND_MAP_GRID,
138 : SRS_PT_TUNISIA_MINING_GRID,
139 : NULL
140 : };
141 :
142 : /*
143 : ** List of supported projections with the PARAMETERS[] acceptable for each.
144 : */
145 : static const char *papszProjWithParms[] = {
146 :
147 : SRS_PT_TRANSVERSE_MERCATOR,
148 : SRS_PP_LATITUDE_OF_ORIGIN,
149 : SRS_PP_CENTRAL_MERIDIAN,
150 : SRS_PP_SCALE_FACTOR,
151 : SRS_PP_FALSE_EASTING,
152 : SRS_PP_FALSE_NORTHING,
153 : NULL,
154 :
155 : SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED,
156 : SRS_PP_LATITUDE_OF_ORIGIN,
157 : SRS_PP_CENTRAL_MERIDIAN,
158 : SRS_PP_SCALE_FACTOR,
159 : SRS_PP_FALSE_EASTING,
160 : SRS_PP_FALSE_NORTHING,
161 : NULL,
162 :
163 : SRS_PT_TUNISIA_MINING_GRID,
164 : SRS_PP_LATITUDE_OF_ORIGIN,
165 : SRS_PP_CENTRAL_MERIDIAN,
166 : SRS_PP_FALSE_EASTING,
167 : SRS_PP_FALSE_NORTHING,
168 : NULL,
169 :
170 : SRS_PT_ALBERS_CONIC_EQUAL_AREA,
171 : SRS_PP_LATITUDE_OF_CENTER,
172 : SRS_PP_LONGITUDE_OF_CENTER,
173 : SRS_PP_STANDARD_PARALLEL_1,
174 : SRS_PP_STANDARD_PARALLEL_2,
175 : SRS_PP_FALSE_EASTING,
176 : SRS_PP_FALSE_NORTHING,
177 : NULL,
178 :
179 : SRS_PT_AZIMUTHAL_EQUIDISTANT,
180 : SRS_PP_LATITUDE_OF_CENTER,
181 : SRS_PP_LONGITUDE_OF_CENTER,
182 : SRS_PP_FALSE_EASTING,
183 : SRS_PP_FALSE_NORTHING,
184 : NULL,
185 :
186 : SRS_PT_BONNE,
187 : SRS_PP_STANDARD_PARALLEL_1,
188 : SRS_PP_CENTRAL_MERIDIAN,
189 : SRS_PP_FALSE_EASTING,
190 : SRS_PP_FALSE_NORTHING,
191 : NULL,
192 :
193 : SRS_PT_CYLINDRICAL_EQUAL_AREA,
194 : SRS_PP_STANDARD_PARALLEL_1,
195 : SRS_PP_CENTRAL_MERIDIAN,
196 : SRS_PP_FALSE_EASTING,
197 : SRS_PP_FALSE_NORTHING,
198 : NULL,
199 :
200 : SRS_PT_CASSINI_SOLDNER,
201 : SRS_PP_LATITUDE_OF_ORIGIN,
202 : SRS_PP_CENTRAL_MERIDIAN,
203 : SRS_PP_FALSE_EASTING,
204 : SRS_PP_FALSE_NORTHING,
205 : NULL,
206 :
207 : SRS_PT_EQUIDISTANT_CONIC,
208 : SRS_PP_STANDARD_PARALLEL_1,
209 : SRS_PP_STANDARD_PARALLEL_2,
210 : SRS_PP_LATITUDE_OF_CENTER,
211 : SRS_PP_LONGITUDE_OF_CENTER,
212 : SRS_PP_FALSE_EASTING,
213 : SRS_PP_FALSE_NORTHING,
214 : NULL,
215 :
216 : SRS_PT_ECKERT_I,
217 : SRS_PP_CENTRAL_MERIDIAN,
218 : SRS_PP_FALSE_EASTING,
219 : SRS_PP_FALSE_NORTHING,
220 : NULL,
221 :
222 : SRS_PT_ECKERT_II,
223 : SRS_PP_CENTRAL_MERIDIAN,
224 : SRS_PP_FALSE_EASTING,
225 : SRS_PP_FALSE_NORTHING,
226 : NULL,
227 :
228 : SRS_PT_ECKERT_III,
229 : SRS_PP_CENTRAL_MERIDIAN,
230 : SRS_PP_FALSE_EASTING,
231 : SRS_PP_FALSE_NORTHING,
232 : NULL,
233 :
234 : SRS_PT_ECKERT_IV,
235 : SRS_PP_CENTRAL_MERIDIAN,
236 : SRS_PP_FALSE_EASTING,
237 : SRS_PP_FALSE_NORTHING,
238 : NULL,
239 :
240 : SRS_PT_ECKERT_V,
241 : SRS_PP_CENTRAL_MERIDIAN,
242 : SRS_PP_FALSE_EASTING,
243 : SRS_PP_FALSE_NORTHING,
244 : NULL,
245 :
246 : SRS_PT_ECKERT_VI,
247 : SRS_PP_CENTRAL_MERIDIAN,
248 : SRS_PP_FALSE_EASTING,
249 : SRS_PP_FALSE_NORTHING,
250 : NULL,
251 :
252 : SRS_PT_EQUIRECTANGULAR,
253 : SRS_PP_LATITUDE_OF_ORIGIN,
254 : SRS_PP_CENTRAL_MERIDIAN,
255 : SRS_PP_STANDARD_PARALLEL_1,
256 : SRS_PP_FALSE_EASTING,
257 : SRS_PP_FALSE_NORTHING,
258 : NULL,
259 :
260 : SRS_PT_GALL_STEREOGRAPHIC,
261 : SRS_PP_CENTRAL_MERIDIAN,
262 : SRS_PP_FALSE_EASTING,
263 : SRS_PP_FALSE_NORTHING,
264 : NULL,
265 :
266 : SRS_PT_GNOMONIC,
267 : SRS_PP_LATITUDE_OF_ORIGIN,
268 : SRS_PP_CENTRAL_MERIDIAN,
269 : SRS_PP_FALSE_EASTING,
270 : SRS_PP_FALSE_NORTHING,
271 : NULL,
272 :
273 : SRS_PT_HOTINE_OBLIQUE_MERCATOR,
274 : SRS_PP_LATITUDE_OF_CENTER,
275 : SRS_PP_LONGITUDE_OF_CENTER,
276 : SRS_PP_AZIMUTH,
277 : SRS_PP_RECTIFIED_GRID_ANGLE,
278 : SRS_PP_SCALE_FACTOR,
279 : SRS_PP_FALSE_EASTING,
280 : SRS_PP_FALSE_NORTHING,
281 : NULL,
282 :
283 : SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN,
284 : SRS_PP_LATITUDE_OF_CENTER,
285 : SRS_PP_LATITUDE_OF_POINT_1,
286 : SRS_PP_LONGITUDE_OF_POINT_1,
287 : SRS_PP_LATITUDE_OF_POINT_2,
288 : SRS_PP_LONGITUDE_OF_POINT_2
289 : SRS_PP_SCALE_FACTOR,
290 : SRS_PP_FALSE_EASTING,
291 : SRS_PP_FALSE_NORTHING,
292 : NULL,
293 :
294 : SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA,
295 : SRS_PP_LATITUDE_OF_CENTER,
296 : SRS_PP_LONGITUDE_OF_CENTER,
297 : SRS_PP_FALSE_EASTING,
298 : SRS_PP_FALSE_NORTHING,
299 : NULL,
300 :
301 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP,
302 : SRS_PP_STANDARD_PARALLEL_1,
303 : SRS_PP_STANDARD_PARALLEL_2,
304 : SRS_PP_LATITUDE_OF_ORIGIN,
305 : SRS_PP_CENTRAL_MERIDIAN,
306 : SRS_PP_FALSE_EASTING,
307 : SRS_PP_FALSE_NORTHING,
308 : NULL,
309 :
310 : SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP,
311 : SRS_PP_LATITUDE_OF_ORIGIN,
312 : SRS_PP_CENTRAL_MERIDIAN,
313 : SRS_PP_SCALE_FACTOR,
314 : SRS_PP_FALSE_EASTING,
315 : SRS_PP_FALSE_NORTHING,
316 : NULL,
317 :
318 : SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM,
319 : SRS_PP_STANDARD_PARALLEL_1,
320 : SRS_PP_STANDARD_PARALLEL_2,
321 : SRS_PP_LATITUDE_OF_ORIGIN,
322 : SRS_PP_CENTRAL_MERIDIAN,
323 : SRS_PP_FALSE_EASTING,
324 : SRS_PP_FALSE_NORTHING,
325 : NULL,
326 :
327 : SRS_PT_MILLER_CYLINDRICAL,
328 : SRS_PP_LATITUDE_OF_CENTER,
329 : SRS_PP_LONGITUDE_OF_CENTER,
330 : SRS_PP_FALSE_EASTING,
331 : SRS_PP_FALSE_NORTHING,
332 : NULL,
333 :
334 : SRS_PT_MERCATOR_1SP,
335 : SRS_PP_LATITUDE_OF_ORIGIN,
336 : SRS_PP_CENTRAL_MERIDIAN,
337 : SRS_PP_SCALE_FACTOR,
338 : SRS_PP_FALSE_EASTING,
339 : SRS_PP_FALSE_NORTHING,
340 : NULL,
341 :
342 : SRS_PT_MERCATOR_2SP,
343 : SRS_PP_STANDARD_PARALLEL_1,
344 : SRS_PP_LATITUDE_OF_ORIGIN,
345 : SRS_PP_CENTRAL_MERIDIAN,
346 : SRS_PP_FALSE_EASTING,
347 : SRS_PP_FALSE_NORTHING,
348 : NULL,
349 :
350 : SRS_PT_MOLLWEIDE,
351 : SRS_PP_CENTRAL_MERIDIAN,
352 : SRS_PP_FALSE_EASTING,
353 : SRS_PP_FALSE_NORTHING,
354 : NULL,
355 :
356 : SRS_PT_NEW_ZEALAND_MAP_GRID,
357 : SRS_PP_LATITUDE_OF_ORIGIN,
358 : SRS_PP_CENTRAL_MERIDIAN,
359 : SRS_PP_FALSE_EASTING,
360 : SRS_PP_FALSE_NORTHING,
361 : NULL,
362 :
363 : SRS_PT_ORTHOGRAPHIC,
364 : SRS_PP_LATITUDE_OF_ORIGIN,
365 : SRS_PP_CENTRAL_MERIDIAN,
366 : SRS_PP_FALSE_EASTING,
367 : SRS_PP_FALSE_NORTHING,
368 : NULL,
369 :
370 : SRS_PT_POLYCONIC,
371 : SRS_PP_LATITUDE_OF_ORIGIN,
372 : SRS_PP_CENTRAL_MERIDIAN,
373 : SRS_PP_FALSE_EASTING,
374 : SRS_PP_FALSE_NORTHING,
375 : NULL,
376 :
377 : SRS_PT_POLAR_STEREOGRAPHIC,
378 : SRS_PP_LATITUDE_OF_ORIGIN,
379 : SRS_PP_CENTRAL_MERIDIAN,
380 : SRS_PP_SCALE_FACTOR,
381 : SRS_PP_FALSE_EASTING,
382 : SRS_PP_FALSE_NORTHING,
383 : NULL,
384 :
385 : SRS_PT_ROBINSON,
386 : SRS_PP_LONGITUDE_OF_CENTER,
387 : SRS_PP_FALSE_EASTING,
388 : SRS_PP_FALSE_NORTHING,
389 : NULL,
390 :
391 : SRS_PT_SINUSOIDAL,
392 : SRS_PP_LONGITUDE_OF_CENTER,
393 : SRS_PP_FALSE_EASTING,
394 : SRS_PP_FALSE_NORTHING,
395 : NULL,
396 :
397 : SRS_PT_STEREOGRAPHIC,
398 : SRS_PP_LATITUDE_OF_ORIGIN,
399 : SRS_PP_CENTRAL_MERIDIAN,
400 : SRS_PP_SCALE_FACTOR,
401 : SRS_PP_FALSE_EASTING,
402 : SRS_PP_FALSE_NORTHING,
403 : NULL,
404 :
405 : SRS_PT_SWISS_OBLIQUE_CYLINDRICAL,
406 : SRS_PP_LATITUDE_OF_CENTER,
407 : SRS_PP_CENTRAL_MERIDIAN,
408 : SRS_PP_FALSE_EASTING,
409 : SRS_PP_FALSE_NORTHING,
410 : NULL,
411 :
412 : SRS_PT_OBLIQUE_STEREOGRAPHIC,
413 : SRS_PP_LATITUDE_OF_ORIGIN,
414 : SRS_PP_CENTRAL_MERIDIAN,
415 : SRS_PP_SCALE_FACTOR,
416 : SRS_PP_FALSE_EASTING,
417 : SRS_PP_FALSE_NORTHING,
418 : NULL,
419 :
420 : SRS_PT_VANDERGRINTEN,
421 : SRS_PP_CENTRAL_MERIDIAN,
422 : SRS_PP_FALSE_EASTING,
423 : SRS_PP_FALSE_NORTHING,
424 : NULL,
425 :
426 : SRS_PT_GEOSTATIONARY_SATELLITE,
427 : SRS_PP_CENTRAL_MERIDIAN,
428 : SRS_PP_SATELLITE_HEIGHT,
429 : SRS_PP_FALSE_EASTING,
430 : SRS_PP_FALSE_NORTHING,
431 : NULL,
432 :
433 : SRS_PT_KROVAK,
434 : SRS_PP_LATITUDE_OF_CENTER,
435 : SRS_PP_LONGITUDE_OF_CENTER,
436 : SRS_PP_AZIMUTH,
437 : SRS_PP_PSEUDO_STD_PARALLEL_1,
438 : SRS_PP_SCALE_FACTOR,
439 : SRS_PP_FALSE_EASTING,
440 : SRS_PP_FALSE_NORTHING,
441 : NULL,
442 :
443 : SRS_PT_TWO_POINT_EQUIDISTANT,
444 : SRS_PP_LATITUDE_OF_1ST_POINT,
445 : SRS_PP_LONGITUDE_OF_1ST_POINT,
446 : SRS_PP_LATITUDE_OF_2ND_POINT,
447 : SRS_PP_LONGITUDE_OF_2ND_POINT,
448 : SRS_PP_FALSE_EASTING,
449 : SRS_PP_FALSE_NORTHING,
450 : NULL,
451 :
452 : SRS_PT_IMW_POLYCONIC,
453 : SRS_PP_LATITUDE_OF_1ST_POINT,
454 : SRS_PP_LATITUDE_OF_2ND_POINT,
455 : SRS_PP_CENTRAL_MERIDIAN,
456 : SRS_PP_FALSE_EASTING,
457 : SRS_PP_FALSE_NORTHING,
458 : NULL,
459 :
460 : SRS_PT_WAGNER_I,
461 : SRS_PP_FALSE_EASTING,
462 : SRS_PP_FALSE_NORTHING,
463 : NULL,
464 :
465 : SRS_PT_WAGNER_II,
466 : SRS_PP_FALSE_EASTING,
467 : SRS_PP_FALSE_NORTHING,
468 : NULL,
469 :
470 : SRS_PT_WAGNER_III,
471 : SRS_PP_LATITUDE_OF_ORIGIN,
472 : SRS_PP_FALSE_EASTING,
473 : SRS_PP_FALSE_NORTHING,
474 : NULL,
475 :
476 : SRS_PT_WAGNER_IV,
477 : SRS_PP_FALSE_EASTING,
478 : SRS_PP_FALSE_NORTHING,
479 : NULL,
480 :
481 : SRS_PT_WAGNER_V,
482 : SRS_PP_FALSE_EASTING,
483 : SRS_PP_FALSE_NORTHING,
484 : NULL,
485 :
486 : SRS_PT_WAGNER_VI,
487 : SRS_PP_FALSE_EASTING,
488 : SRS_PP_FALSE_NORTHING,
489 : NULL,
490 :
491 : SRS_PT_WAGNER_VII,
492 : SRS_PP_FALSE_EASTING,
493 : SRS_PP_FALSE_NORTHING,
494 : NULL,
495 :
496 : SRS_PT_GAUSSSCHREIBERTMERCATOR,
497 : SRS_PP_LATITUDE_OF_ORIGIN,
498 : SRS_PP_CENTRAL_MERIDIAN,
499 : SRS_PP_SCALE_FACTOR,
500 : SRS_PP_FALSE_EASTING,
501 : SRS_PP_FALSE_NORTHING,
502 : NULL,
503 :
504 : SRS_PT_GOODE_HOMOLOSINE,
505 : SRS_PP_CENTRAL_MERIDIAN,
506 : SRS_PP_FALSE_EASTING,
507 : SRS_PP_FALSE_NORTHING,
508 : NULL,
509 :
510 : SRS_PT_IGH,
511 : NULL,
512 :
513 : NULL
514 : };
515 :
516 : static const char *papszAliasGroupList[] = {
517 : SRS_PP_LATITUDE_OF_ORIGIN,
518 : SRS_PP_LATITUDE_OF_CENTER,
519 : NULL,
520 : SRS_PP_CENTRAL_MERIDIAN,
521 : SRS_PP_LONGITUDE_OF_CENTER,
522 : SRS_PP_LONGITUDE_OF_ORIGIN,
523 : NULL,
524 : NULL
525 : };
526 :
527 :
528 : /************************************************************************/
529 : /* Validate() */
530 : /************************************************************************/
531 :
532 : /**
533 : * \brief Validate SRS tokens.
534 : *
535 : * This method attempts to verify that the spatial reference system is
536 : * well formed, and consists of known tokens. The validation is not
537 : * comprehensive.
538 : *
539 : * This method is the same as the C function OSRValidate().
540 : *
541 : * @return OGRERR_NONE if all is fine, OGRERR_CORRUPT_DATA if the SRS is
542 : * not well formed, and OGRERR_UNSUPPORTED_SRS if the SRS is well formed,
543 : * but contains non-standard PROJECTION[] values.
544 : */
545 :
546 62 : OGRErr OGRSpatialReference::Validate()
547 :
548 : {
549 : /* -------------------------------------------------------------------- */
550 : /* Validate root node. */
551 : /* -------------------------------------------------------------------- */
552 62 : if( poRoot == NULL )
553 : {
554 : CPLDebug( "OGRSpatialReference::Validate",
555 0 : "No root pointer.\n" );
556 0 : return OGRERR_CORRUPT_DATA;
557 : }
558 :
559 62 : return Validate(poRoot);
560 : }
561 :
562 :
563 64 : OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
564 : {
565 64 : if( !EQUAL(poRoot->GetValue(),"GEOGCS")
566 : && !EQUAL(poRoot->GetValue(),"PROJCS")
567 : && !EQUAL(poRoot->GetValue(),"LOCAL_CS")
568 : && !EQUAL(poRoot->GetValue(),"GEOCCS")
569 : && !EQUAL(poRoot->GetValue(),"VERT_CS")
570 : && !EQUAL(poRoot->GetValue(),"COMPD_CS"))
571 : {
572 : CPLDebug( "OGRSpatialReference::Validate",
573 : "Unrecognised root node `%s'\n",
574 0 : poRoot->GetValue() );
575 0 : return OGRERR_CORRUPT_DATA;
576 : }
577 :
578 : /* -------------------------------------------------------------------- */
579 : /* For a COMPD_CS, validate subparameters and head & tail cs */
580 : /* -------------------------------------------------------------------- */
581 64 : if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
582 : {
583 : OGR_SRSNode *poNode;
584 : int i;
585 :
586 4 : for( i = 1; i < poRoot->GetChildCount(); i++ )
587 : {
588 3 : poNode = poRoot->GetChild(i);
589 :
590 3 : if( EQUAL(poNode->GetValue(),"GEOGCS") ||
591 : EQUAL(poNode->GetValue(),"PROJCS") ||
592 : EQUAL(poNode->GetValue(),"LOCAL_CS") ||
593 : EQUAL(poNode->GetValue(),"GEOCCS") ||
594 : EQUAL(poNode->GetValue(),"VERT_CS") ||
595 : EQUAL(poNode->GetValue(),"COMPD_CS") )
596 : {
597 2 : OGRErr eErr = Validate(poNode);
598 2 : if (eErr != OGRERR_NONE)
599 0 : return eErr;
600 : }
601 1 : else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
602 : {
603 1 : OGRErr eErr = ValidateAuthority(poNode);
604 1 : if (eErr != OGRERR_NONE)
605 0 : return eErr;
606 : }
607 : else
608 : {
609 : CPLDebug( "OGRSpatialReference::Validate",
610 : "Unexpected child for COMPD_CS `%s'.\n",
611 0 : poNode->GetValue() );
612 :
613 0 : return OGRERR_CORRUPT_DATA;
614 : }
615 : }
616 :
617 1 : return OGRERR_NONE;
618 : }
619 :
620 : /* -------------------------------------------------------------------- */
621 : /* Validate VERT_CS */
622 : /* -------------------------------------------------------------------- */
623 63 : if( EQUAL(poRoot->GetValue(),"VERT_CS") )
624 : {
625 : OGR_SRSNode *poNode;
626 : int i;
627 1 : int bGotVertDatum = FALSE;
628 1 : int bGotUnit = FALSE;
629 1 : int nCountAxis = 0;
630 :
631 5 : for( i = 1; i < poRoot->GetChildCount(); i++ )
632 : {
633 4 : poNode = poRoot->GetChild(i);
634 :
635 4 : if( EQUAL(poNode->GetValue(),"VERT_DATUM") )
636 : {
637 1 : OGRErr eErr = ValidateVertDatum(poNode);
638 1 : if (eErr != OGRERR_NONE)
639 0 : return eErr;
640 1 : bGotVertDatum = TRUE;
641 : }
642 3 : else if( EQUAL(poNode->GetValue(),"UNIT") )
643 : {
644 1 : OGRErr eErr = ValidateUnit(poNode);
645 1 : if (eErr != OGRERR_NONE)
646 0 : return eErr;
647 1 : bGotUnit = TRUE;
648 : }
649 2 : else if( EQUAL(poNode->GetValue(),"AXIS") )
650 : {
651 1 : OGRErr eErr = ValidateAxis(poNode);
652 1 : if (eErr != OGRERR_NONE)
653 0 : return eErr;
654 1 : nCountAxis ++;
655 : }
656 1 : else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
657 : {
658 1 : OGRErr eErr = ValidateAuthority(poNode);
659 1 : if (eErr != OGRERR_NONE)
660 0 : return eErr;
661 : }
662 : else
663 : {
664 : CPLDebug( "OGRSpatialReference::Validate",
665 : "Unexpected child for VERT_CS `%s'.\n",
666 0 : poNode->GetValue() );
667 :
668 0 : return OGRERR_CORRUPT_DATA;
669 : }
670 : }
671 :
672 1 : if (!bGotVertDatum)
673 : {
674 : CPLDebug( "OGRSpatialReference::Validate",
675 0 : "No VERT_DATUM child in VERT_CS.\n" );
676 :
677 0 : return OGRERR_CORRUPT_DATA;
678 : }
679 :
680 1 : if (!bGotUnit)
681 : {
682 : CPLDebug( "OGRSpatialReference::Validate",
683 0 : "No UNIT child in VERT_CS.\n" );
684 :
685 0 : return OGRERR_CORRUPT_DATA;
686 : }
687 :
688 1 : if (nCountAxis > 1)
689 : {
690 : CPLDebug( "OGRSpatialReference::Validate",
691 0 : "Too many AXIS children in VERT_CS.\n" );
692 :
693 0 : return OGRERR_CORRUPT_DATA;
694 : }
695 1 : return OGRERR_NONE;
696 : }
697 :
698 : /* -------------------------------------------------------------------- */
699 : /* Validate GEOCCS */
700 : /* -------------------------------------------------------------------- */
701 62 : if( EQUAL(poRoot->GetValue(),"GEOCCS") )
702 : {
703 : OGR_SRSNode *poNode;
704 : int i;
705 4 : int bGotDatum = FALSE;
706 4 : int bGotPrimeM = FALSE;
707 4 : int bGotUnit = FALSE;
708 4 : int nCountAxis = 0;
709 :
710 27 : for( i = 1; i < poRoot->GetChildCount(); i++ )
711 : {
712 23 : poNode = poRoot->GetChild(i);
713 :
714 23 : if( EQUAL(poNode->GetValue(),"DATUM") )
715 : {
716 4 : bGotDatum = TRUE;
717 : }
718 19 : else if( EQUAL(poNode->GetValue(),"PRIMEM") )
719 : {
720 4 : bGotPrimeM = TRUE;
721 :
722 4 : if( poNode->GetChildCount() < 2
723 : || poNode->GetChildCount() > 3 )
724 : {
725 : CPLDebug( "OGRSpatialReference::Validate",
726 : "PRIMEM has wrong number of children (%d),"
727 : "not 2 or 3 as expected.\n",
728 0 : poNode->GetChildCount() );
729 :
730 0 : return OGRERR_CORRUPT_DATA;
731 : }
732 : }
733 15 : else if( EQUAL(poNode->GetValue(),"UNIT") )
734 : {
735 3 : OGRErr eErr = ValidateUnit(poNode);
736 3 : if (eErr != OGRERR_NONE)
737 0 : return eErr;
738 3 : bGotUnit = TRUE;
739 : }
740 12 : else if( EQUAL(poNode->GetValue(),"AXIS") )
741 : {
742 9 : OGRErr eErr = ValidateAxis(poNode);
743 9 : if (eErr != OGRERR_NONE)
744 0 : return eErr;
745 9 : nCountAxis ++;
746 : }
747 3 : else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
748 : {
749 3 : OGRErr eErr = ValidateAuthority(poNode);
750 3 : if (eErr != OGRERR_NONE)
751 0 : return eErr;
752 : }
753 : else
754 : {
755 : CPLDebug( "OGRSpatialReference::Validate",
756 : "Unexpected child for GEOCCS `%s'.\n",
757 0 : poNode->GetValue() );
758 :
759 0 : return OGRERR_CORRUPT_DATA;
760 : }
761 : }
762 :
763 4 : if (!bGotDatum)
764 : {
765 : CPLDebug( "OGRSpatialReference::Validate",
766 0 : "No DATUM child in GEOCCS.\n" );
767 :
768 0 : return OGRERR_CORRUPT_DATA;
769 : }
770 :
771 4 : if (!bGotPrimeM)
772 : {
773 : CPLDebug( "OGRSpatialReference::Validate",
774 0 : "No PRIMEM child in GEOCCS.\n" );
775 :
776 0 : return OGRERR_CORRUPT_DATA;
777 : }
778 :
779 4 : if (!bGotUnit)
780 : {
781 : CPLDebug( "OGRSpatialReference::Validate",
782 1 : "No UNIT child in GEOCCS.\n" );
783 :
784 1 : return OGRERR_CORRUPT_DATA;
785 : }
786 :
787 3 : if (nCountAxis != 0 && nCountAxis != 3 )
788 : {
789 : CPLDebug( "OGRSpatialReference::Validate",
790 0 : "Wrong number of AXIS children in GEOCCS.\n" );
791 :
792 0 : return OGRERR_CORRUPT_DATA;
793 : }
794 : }
795 :
796 : /* -------------------------------------------------------------------- */
797 : /* For a PROJCS, validate subparameters (other than GEOGCS). */
798 : /* -------------------------------------------------------------------- */
799 61 : if( EQUAL(poRoot->GetValue(),"PROJCS") )
800 : {
801 : OGR_SRSNode *poNode;
802 : int i;
803 :
804 410 : for( i = 1; i < poRoot->GetChildCount(); i++ )
805 : {
806 354 : poNode = poRoot->GetChild(i);
807 :
808 354 : if( EQUAL(poNode->GetValue(),"GEOGCS") )
809 : {
810 : /* validated elsewhere */
811 : }
812 298 : else if( EQUAL(poNode->GetValue(),"UNIT") )
813 : {
814 8 : OGRErr eErr = ValidateUnit(poNode);
815 8 : if (eErr != OGRERR_NONE)
816 0 : return eErr;
817 : }
818 290 : else if( EQUAL(poNode->GetValue(),"PARAMETER") )
819 : {
820 227 : if( poNode->GetChildCount() != 2 )
821 : {
822 : CPLDebug( "OGRSpatialReference::Validate",
823 : "PARAMETER has wrong number of children (%d),"
824 : "not 2 as expected.\n",
825 0 : poNode->GetChildCount() );
826 :
827 0 : return OGRERR_CORRUPT_DATA;
828 : }
829 227 : else if( CSLFindString( (char **)papszParameters,
830 : poNode->GetChild(0)->GetValue()) == -1)
831 : {
832 : CPLDebug( "OGRSpatialReference::Validate",
833 : "Unrecognised PARAMETER `%s'.\n",
834 0 : poNode->GetChild(0)->GetValue() );
835 :
836 0 : return OGRERR_UNSUPPORTED_SRS;
837 : }
838 : }
839 63 : else if( EQUAL(poNode->GetValue(),"PROJECTION") )
840 : {
841 56 : if( poNode->GetChildCount() != 1 && poNode->GetChildCount() != 2 )
842 : {
843 : CPLDebug( "OGRSpatialReference::Validate",
844 : "PROJECTION has wrong number of children (%d),"
845 : "not 1 or 2 as expected.\n",
846 0 : poNode->GetChildCount() );
847 :
848 0 : return OGRERR_CORRUPT_DATA;
849 : }
850 56 : else if( CSLFindString( (char **)papszProjectionSupported,
851 : poNode->GetChild(0)->GetValue()) == -1
852 : && CSLFindString( (char **)papszProjectionUnsupported,
853 : poNode->GetChild(0)->GetValue()) == -1)
854 : {
855 : CPLDebug( "OGRSpatialReference::Validate",
856 : "Unrecognised PROJECTION `%s'.\n",
857 0 : poNode->GetChild(0)->GetValue() );
858 :
859 0 : return OGRERR_UNSUPPORTED_SRS;
860 : }
861 56 : else if( CSLFindString( (char **)papszProjectionSupported,
862 : poNode->GetChild(0)->GetValue()) == -1)
863 : {
864 : CPLDebug( "OGRSpatialReference::Validate",
865 : "Unsupported, but recognised PROJECTION `%s'.\n",
866 0 : poNode->GetChild(0)->GetValue() );
867 :
868 0 : return OGRERR_UNSUPPORTED_SRS;
869 : }
870 :
871 56 : if (poNode->GetChildCount() == 2)
872 : {
873 0 : poNode = poNode->GetChild(1);
874 0 : if( EQUAL(poNode->GetValue(),"AUTHORITY") )
875 : {
876 0 : OGRErr eErr = ValidateAuthority(poNode);
877 0 : if (eErr != OGRERR_NONE)
878 0 : return eErr;
879 : }
880 : else
881 : {
882 : CPLDebug( "OGRSpatialReference::Validate",
883 : "Unexpected child for PROJECTION `%s'.\n",
884 0 : poNode->GetValue() );
885 :
886 0 : return OGRERR_CORRUPT_DATA;
887 : }
888 : }
889 : }
890 7 : else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
891 : {
892 2 : OGRErr eErr = ValidateAuthority(poNode);
893 2 : if (eErr != OGRERR_NONE)
894 0 : return eErr;
895 : }
896 5 : else if( EQUAL(poNode->GetValue(),"AXIS") )
897 : {
898 4 : OGRErr eErr = ValidateAxis(poNode);
899 4 : if (eErr != OGRERR_NONE)
900 0 : return eErr;
901 : }
902 1 : else if( EQUAL(poNode->GetValue(),"EXTENSION") )
903 : {
904 : // We do not try to control the sub-organization of
905 : // EXTENSION nodes.
906 : }
907 : else
908 : {
909 : CPLDebug( "OGRSpatialReference::Validate",
910 : "Unexpected child for PROJCS `%s'.\n",
911 0 : poNode->GetValue() );
912 :
913 0 : return OGRERR_CORRUPT_DATA;
914 : }
915 : }
916 : }
917 :
918 : /* -------------------------------------------------------------------- */
919 : /* Validate GEOGCS if found. */
920 : /* -------------------------------------------------------------------- */
921 61 : OGR_SRSNode *poGEOGCS = poRoot->GetNode( "GEOGCS" );
922 :
923 61 : if( poGEOGCS != NULL )
924 : {
925 : OGR_SRSNode *poNode;
926 : int i;
927 :
928 237 : for( i = 1; i < poGEOGCS->GetChildCount(); i++ )
929 : {
930 180 : poNode = poGEOGCS->GetChild(i);
931 :
932 180 : if( EQUAL(poNode->GetValue(),"DATUM") )
933 : {
934 : /* validated elsewhere */
935 : }
936 122 : else if( EQUAL(poNode->GetValue(),"PRIMEM") )
937 : {
938 58 : if( poNode->GetChildCount() < 2
939 : || poNode->GetChildCount() > 3 )
940 : {
941 : CPLDebug( "OGRSpatialReference::Validate",
942 : "PRIMEM has wrong number of children (%d),"
943 : "not 2 or 3 as expected.\n",
944 0 : poNode->GetChildCount() );
945 :
946 0 : return OGRERR_CORRUPT_DATA;
947 : }
948 : }
949 64 : else if( EQUAL(poNode->GetValue(),"UNIT") )
950 : {
951 58 : OGRErr eErr = ValidateUnit(poNode);
952 58 : if (eErr != OGRERR_NONE)
953 0 : return eErr;
954 : }
955 6 : else if( EQUAL(poNode->GetValue(),"AXIS") )
956 : {
957 2 : OGRErr eErr = ValidateAxis(poNode);
958 2 : if (eErr != OGRERR_NONE)
959 0 : return eErr;
960 : }
961 4 : else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
962 : {
963 3 : OGRErr eErr = ValidateAuthority(poNode);
964 3 : if (eErr != OGRERR_NONE)
965 0 : return eErr;
966 : }
967 : else
968 : {
969 : CPLDebug( "OGRSpatialReference::Validate",
970 : "Unexpected child for GEOGCS `%s'.\n",
971 1 : poNode->GetValue() );
972 :
973 1 : return OGRERR_CORRUPT_DATA;
974 : }
975 : }
976 :
977 57 : if( poGEOGCS->GetNode("DATUM") == NULL )
978 : {
979 : CPLDebug( "OGRSpatialReference::Validate",
980 0 : "No DATUM child in GEOGCS.\n" );
981 :
982 0 : return OGRERR_CORRUPT_DATA;
983 : }
984 : }
985 :
986 : /* -------------------------------------------------------------------- */
987 : /* Validate DATUM/SPHEROID. */
988 : /* -------------------------------------------------------------------- */
989 60 : OGR_SRSNode *poDATUM = poRoot->GetNode( "DATUM" );
990 :
991 60 : if( poDATUM != NULL )
992 : {
993 : OGR_SRSNode *poSPHEROID;
994 60 : int bGotSpheroid = FALSE;
995 : int i;
996 :
997 60 : if( poDATUM->GetChildCount() == 0 )
998 : {
999 : CPLDebug( "OGRSpatialReference::Validate",
1000 0 : "DATUM has no children." );
1001 :
1002 0 : return OGRERR_CORRUPT_DATA;
1003 : }
1004 :
1005 129 : for( i = 1; i < poDATUM->GetChildCount(); i++ )
1006 : {
1007 : OGR_SRSNode *poNode;
1008 69 : poNode = poDATUM->GetChild(i);
1009 :
1010 69 : if( EQUAL(poNode->GetValue(),"SPHEROID") )
1011 : {
1012 60 : poSPHEROID = poDATUM->GetChild(1);
1013 60 : bGotSpheroid = TRUE;
1014 :
1015 60 : if( poSPHEROID->GetChildCount() != 3
1016 : && poSPHEROID->GetChildCount() != 4 )
1017 : {
1018 : CPLDebug( "OGRSpatialReference::Validate",
1019 : "SPHEROID has wrong number of children (%d),"
1020 : "not 3 or 4 as expected.\n",
1021 0 : poSPHEROID->GetChildCount() );
1022 :
1023 0 : return OGRERR_CORRUPT_DATA;
1024 : }
1025 60 : else if( CPLAtof(poSPHEROID->GetChild(1)->GetValue()) == 0.0 )
1026 : {
1027 : CPLDebug( "OGRSpatialReference::Validate",
1028 : "SPHEROID semi-major axis is zero (%s)!\n",
1029 0 : poSPHEROID->GetChild(1)->GetValue() );
1030 0 : return OGRERR_CORRUPT_DATA;
1031 : }
1032 : }
1033 9 : else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
1034 : {
1035 6 : OGRErr eErr = ValidateAuthority(poNode);
1036 6 : if (eErr != OGRERR_NONE)
1037 0 : return eErr;
1038 : }
1039 3 : else if( EQUAL(poNode->GetValue(),"TOWGS84") )
1040 : {
1041 3 : if( poNode->GetChildCount() != 3
1042 : && poNode->GetChildCount() != 7)
1043 : {
1044 : CPLDebug( "OGRSpatialReference::Validate",
1045 : "TOWGS84 has wrong number of children (%d), not 3 or 7.\n",
1046 0 : poNode->GetChildCount() );
1047 0 : return OGRERR_CORRUPT_DATA;
1048 : }
1049 : }
1050 : else
1051 : {
1052 : CPLDebug( "OGRSpatialReference::Validate",
1053 : "Unexpected child for DATUM `%s'.\n",
1054 0 : poNode->GetValue() );
1055 :
1056 0 : return OGRERR_CORRUPT_DATA;
1057 : }
1058 : }
1059 :
1060 60 : if( !bGotSpheroid )
1061 : {
1062 : CPLDebug( "OGRSpatialReference::Validate",
1063 0 : "No SPHEROID child in DATUM.\n" );
1064 :
1065 0 : return OGRERR_CORRUPT_DATA;
1066 : }
1067 : }
1068 :
1069 : /* -------------------------------------------------------------------- */
1070 : /* If this is projected, try to validate the detailed set of */
1071 : /* parameters used for the projection. */
1072 : /* -------------------------------------------------------------------- */
1073 : OGRErr eErr;
1074 :
1075 60 : eErr = ValidateProjection(poRoot);
1076 60 : if( eErr != OGRERR_NONE )
1077 0 : return eErr;
1078 :
1079 60 : return OGRERR_NONE;
1080 : }
1081 :
1082 : /************************************************************************/
1083 : /* OSRValidate() */
1084 : /************************************************************************/
1085 : /**
1086 : * \brief Validate SRS tokens.
1087 : *
1088 : * This function is the same as the C++ method OGRSpatialReference::Validate().
1089 : */
1090 60 : OGRErr OSRValidate( OGRSpatialReferenceH hSRS )
1091 :
1092 : {
1093 60 : VALIDATE_POINTER1( hSRS, "OSRValidate", CE_Failure );
1094 :
1095 60 : return ((OGRSpatialReference *) hSRS)->Validate();
1096 : }
1097 :
1098 : /************************************************************************/
1099 : /* IsAliasFor() */
1100 : /************************************************************************/
1101 :
1102 : /**
1103 : * \brief Return whether the first string passed in an acceptable alias for the
1104 : * second string according to the AliasGroupList
1105 : *
1106 : * @param pszParm1 first string
1107 : * @param pszParm2 second string
1108 : *
1109 : * @return TRUE if both strings are aliases according to the AliasGroupList, FALSE otherwise
1110 : */
1111 0 : int OGRSpatialReference::IsAliasFor( const char *pszParm1,
1112 : const char *pszParm2 )
1113 :
1114 : {
1115 : int iGroup;
1116 :
1117 : /* -------------------------------------------------------------------- */
1118 : /* Look for a group containing pszParm1. */
1119 : /* -------------------------------------------------------------------- */
1120 0 : for( iGroup = 0; papszAliasGroupList[iGroup] != NULL; iGroup++ )
1121 : {
1122 : int i;
1123 :
1124 0 : for( i = iGroup; papszAliasGroupList[i] != NULL; i++ )
1125 : {
1126 0 : if( EQUAL(pszParm1,papszAliasGroupList[i]) )
1127 0 : break;
1128 : }
1129 :
1130 0 : if( papszAliasGroupList[i] == NULL )
1131 0 : iGroup = i;
1132 : else
1133 0 : break;
1134 : }
1135 :
1136 : /* -------------------------------------------------------------------- */
1137 : /* Does this group also contain pszParm2? */
1138 : /* -------------------------------------------------------------------- */
1139 0 : while( papszAliasGroupList[iGroup] != NULL )
1140 : {
1141 0 : if( EQUAL(papszAliasGroupList[iGroup++],pszParm2) )
1142 0 : return TRUE;
1143 : }
1144 :
1145 0 : return FALSE;
1146 : }
1147 :
1148 : /************************************************************************/
1149 : /* ValidateProjection() */
1150 : /************************************************************************/
1151 :
1152 : /**
1153 : * \brief Validate the current PROJECTION's arguments.
1154 : *
1155 : * @return OGRERR_NONE if the PROJECTION's arguments validate, an error code
1156 : * otherwise
1157 : */
1158 60 : OGRErr OGRSpatialReference::ValidateProjection(OGR_SRSNode *poRoot)
1159 : {
1160 60 : OGR_SRSNode *poPROJCS = poRoot->GetNode( "PROJCS" );
1161 :
1162 60 : if( poPROJCS == NULL )
1163 4 : return OGRERR_NONE;
1164 :
1165 56 : if( poPROJCS->GetNode( "PROJECTION" ) == NULL )
1166 : {
1167 : CPLDebug( "OGRSpatialReference::Validate",
1168 0 : "PROJCS does not have PROJECTION subnode." );
1169 0 : return OGRERR_CORRUPT_DATA;
1170 : }
1171 :
1172 : /* -------------------------------------------------------------------- */
1173 : /* Find the matching group in the proj and parms table. */
1174 : /* -------------------------------------------------------------------- */
1175 : const char *pszProjection;
1176 : int iOffset;
1177 :
1178 56 : pszProjection = poPROJCS->GetNode("PROJECTION")->GetChild(0)->GetValue();
1179 :
1180 1399 : for( iOffset = 0;
1181 1343 : papszProjWithParms[iOffset] != NULL
1182 : && !EQUAL(papszProjWithParms[iOffset],pszProjection); )
1183 : {
1184 9402 : while( papszProjWithParms[iOffset] != NULL )
1185 6828 : iOffset++;
1186 1287 : iOffset++;
1187 : }
1188 :
1189 56 : if( papszProjWithParms[iOffset] == NULL )
1190 0 : return OGRERR_UNSUPPORTED_SRS;
1191 :
1192 56 : iOffset++;
1193 :
1194 : /* -------------------------------------------------------------------- */
1195 : /* Check all parameters, and verify they are in the permitted */
1196 : /* list. */
1197 : /* -------------------------------------------------------------------- */
1198 : int iNode;
1199 :
1200 466 : for( iNode = 0; iNode < poPROJCS->GetChildCount(); iNode++ )
1201 : {
1202 410 : OGR_SRSNode *poParm = poPROJCS->GetChild(iNode);
1203 : int i;
1204 : const char *pszParmName;
1205 :
1206 410 : if( !EQUAL(poParm->GetValue(),"PARAMETER") )
1207 183 : continue;
1208 :
1209 227 : pszParmName = poParm->GetChild(0)->GetValue();
1210 :
1211 638 : for( i = iOffset; papszProjWithParms[i] != NULL; i++ )
1212 : {
1213 638 : if( EQUAL(papszProjWithParms[i],pszParmName) )
1214 227 : break;
1215 : }
1216 :
1217 : /* This parameter is not an exact match, is it an alias? */
1218 227 : if( papszProjWithParms[i] == NULL )
1219 : {
1220 0 : for( i = iOffset; papszProjWithParms[i] != NULL; i++ )
1221 : {
1222 0 : if( IsAliasFor(papszProjWithParms[i],pszParmName) )
1223 0 : break;
1224 : }
1225 :
1226 0 : if( papszProjWithParms[i] == NULL )
1227 : {
1228 : CPLDebug( "OGRSpatialReference::Validate",
1229 : "PARAMETER %s for PROJECTION %s is not permitted.",
1230 0 : pszParmName, pszProjection );
1231 0 : return OGRERR_CORRUPT_DATA;
1232 : }
1233 : else
1234 : {
1235 : CPLDebug( "OGRSpatialReference::Validate",
1236 : "PARAMETER %s for PROJECTION %s is an alias for %s.",
1237 : pszParmName, pszProjection,
1238 0 : papszProjWithParms[i] );
1239 0 : return OGRERR_CORRUPT_DATA;
1240 : }
1241 : }
1242 : }
1243 :
1244 56 : return OGRERR_NONE;
1245 : }
1246 :
1247 : /************************************************************************/
1248 : /* ValidateVertDatum() */
1249 : /************************************************************************/
1250 :
1251 : /**
1252 : * \brief Validate the current VERT_DATUM's arguments.
1253 : *
1254 : * @return OGRERR_NONE if the VERT_DATUM's arguments validate, an error code
1255 : * otherwise
1256 : */
1257 1 : OGRErr OGRSpatialReference::ValidateVertDatum(OGR_SRSNode *poRoot)
1258 : {
1259 1 : if ( !EQUAL(poRoot->GetValue(), "VERT_DATUM") )
1260 0 : return OGRERR_NONE;
1261 :
1262 1 : if (poRoot->GetChildCount() < 2 )
1263 : {
1264 : CPLDebug( "OGRSpatialReference::Validate",
1265 0 : "Invalid number of children : %d", poRoot->GetChildCount() );
1266 0 : return OGRERR_CORRUPT_DATA;
1267 : }
1268 :
1269 1 : if (atoi(poRoot->GetChild(1)->GetValue()) == 0)
1270 : {
1271 : CPLDebug( "OGRSpatialReference::Validate",
1272 : "Invalid value for datum type (%s) : must be a number\n",
1273 0 : poRoot->GetChild(1)->GetValue());
1274 0 : return OGRERR_CORRUPT_DATA;
1275 : }
1276 :
1277 : OGR_SRSNode *poNode;
1278 : int i;
1279 :
1280 2 : for( i = 2; i < poRoot->GetChildCount(); i++ )
1281 : {
1282 1 : poNode = poRoot->GetChild(i);
1283 :
1284 1 : if( EQUAL(poNode->GetValue(),"AUTHORITY") )
1285 : {
1286 1 : OGRErr eErr = ValidateAuthority(poNode);
1287 1 : if (eErr != OGRERR_NONE)
1288 0 : return eErr;
1289 : }
1290 0 : else if( EQUAL(poNode->GetValue(),"EXTENSION") )
1291 : {
1292 : // We do not try to control the sub-organization of
1293 : // EXTENSION nodes.
1294 : }
1295 : else
1296 : {
1297 : CPLDebug( "OGRSpatialReference::Validate",
1298 : "Unexpected child for VERT_DATUM `%s'.\n",
1299 0 : poNode->GetValue() );
1300 :
1301 0 : return OGRERR_CORRUPT_DATA;
1302 : }
1303 : }
1304 :
1305 1 : return OGRERR_NONE;
1306 : }
1307 :
1308 : /************************************************************************/
1309 : /* ValidateAuthority() */
1310 : /************************************************************************/
1311 :
1312 : /**
1313 : * \brief Validate the current AUTHORITY's arguments.
1314 : *
1315 : * @return OGRERR_NONE if the AUTHORITY's arguments validate, an error code
1316 : * otherwise
1317 : */
1318 17 : OGRErr OGRSpatialReference::ValidateAuthority(OGR_SRSNode *poRoot)
1319 : {
1320 17 : if ( !EQUAL(poRoot->GetValue(), "AUTHORITY") )
1321 0 : return OGRERR_NONE;
1322 :
1323 17 : if( poRoot->GetChildCount() != 2 )
1324 : {
1325 : CPLDebug( "OGRSpatialReference::Validate",
1326 : "AUTHORITY has wrong number of children (%d), not 2.\n",
1327 0 : poRoot->GetChildCount() );
1328 0 : return OGRERR_CORRUPT_DATA;
1329 : }
1330 :
1331 17 : return OGRERR_NONE;
1332 : }
1333 :
1334 : /************************************************************************/
1335 : /* ValidateAxis() */
1336 : /************************************************************************/
1337 :
1338 : /**
1339 : * \brief Validate the current AXIS's arguments.
1340 : *
1341 : * @return OGRERR_NONE if the AXIS's arguments validate, an error code
1342 : * otherwise
1343 : */
1344 16 : OGRErr OGRSpatialReference::ValidateAxis(OGR_SRSNode *poRoot)
1345 : {
1346 16 : if ( !EQUAL(poRoot->GetValue(), "AXIS") )
1347 0 : return OGRERR_NONE;
1348 :
1349 16 : if( poRoot->GetChildCount() != 2 )
1350 : {
1351 : CPLDebug( "OGRSpatialReference::Validate",
1352 : "AXIS has wrong number of children (%d), not 2.\n",
1353 0 : poRoot->GetChildCount() );
1354 0 : return OGRERR_CORRUPT_DATA;
1355 : }
1356 :
1357 16 : return OGRERR_NONE;
1358 : }
1359 :
1360 :
1361 : /************************************************************************/
1362 : /* ValidateUnit() */
1363 : /************************************************************************/
1364 :
1365 : /**
1366 : * \brief Validate the current UNIT's arguments.
1367 : *
1368 : * @return OGRERR_NONE if the UNIT's arguments validate, an error code
1369 : * otherwise
1370 : */
1371 70 : OGRErr OGRSpatialReference::ValidateUnit(OGR_SRSNode *poRoot)
1372 : {
1373 70 : if ( !EQUAL(poRoot->GetValue(), "UNIT") )
1374 0 : return OGRERR_NONE;
1375 :
1376 70 : if( poRoot->GetChildCount() != 2
1377 : && poRoot->GetChildCount() != 3 )
1378 : {
1379 : CPLDebug( "OGRSpatialReference::Validate",
1380 : "UNIT has wrong number of children (%d), not 2.\n",
1381 0 : poRoot->GetChildCount() );
1382 0 : return OGRERR_CORRUPT_DATA;
1383 : }
1384 70 : else if( CPLAtof(poRoot->GetChild(1)->GetValue()) == 0.0 )
1385 : {
1386 : CPLDebug( "OGRSpatialReference::Validate",
1387 : "UNIT does not appear to have meaningful"
1388 : "coefficient (%s).\n",
1389 0 : poRoot->GetChild(1)->GetValue() );
1390 0 : return OGRERR_CORRUPT_DATA;
1391 : }
1392 :
1393 70 : return OGRERR_NONE;
1394 : }
1395 :
|