Coverage Report

Created: 2026-06-30 08:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogr_srs_usgs.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  OGRSpatialReference translation to/from USGS georeferencing
5
 *           information (used in GCTP package).
6
 * Author:   Andrey Kiselev, dron@ak4719.spb.edu
7
 *
8
 ******************************************************************************
9
 * Copyright (c) 2004, Andrey Kiselev <dron@ak4719.spb.edu>
10
 * Copyright (c) 2008-2009, Even Rouault <even dot rouault at spatialys.com>
11
 *
12
 * SPDX-License-Identifier: MIT
13
 ****************************************************************************/
14
15
#include "cpl_port.h"
16
#include "ogr_srs_api.h"
17
18
#include <cmath>
19
#include <cstddef>
20
21
#include "cpl_conv.h"
22
#include "cpl_csv.h"
23
#include "cpl_error.h"
24
#include "cpl_string.h"
25
#include "ogr_core.h"
26
#include "ogr_p.h"
27
#include "ogr_spatialref.h"
28
29
/************************************************************************/
30
/*                        GCTP projection codes.                        */
31
/************************************************************************/
32
33
constexpr long GEO = 0L;      // Geographic
34
constexpr long UTM = 1L;      // Universal Transverse Mercator (UTM)
35
constexpr long SPCS = 2L;     // State Plane Coordinates
36
constexpr long ALBERS = 3L;   // Albers Conical Equal Area
37
constexpr long LAMCC = 4L;    // Lambert Conformal Conic
38
constexpr long MERCAT = 5L;   // Mercator
39
constexpr long PS = 6L;       // Polar Stereographic
40
constexpr long POLYC = 7L;    // Polyconic
41
constexpr long EQUIDC = 8L;   // Equidistant Conic
42
constexpr long TM = 9L;       // Transverse Mercator
43
constexpr long STEREO = 10L;  // Stereographic
44
constexpr long LAMAZ = 11L;   // Lambert Azimuthal Equal Area
45
constexpr long AZMEQD = 12L;  // Azimuthal Equidistant
46
constexpr long GNOMON = 13L;  // Gnomonic
47
constexpr long ORTHO = 14L;   // Orthographic
48
// constexpr long GVNSP  = 15L;  // General Vertical Near-Side Perspective
49
constexpr long SNSOID = 16L;  // Sinusiodal
50
constexpr long EQRECT = 17L;  // Equirectangular
51
constexpr long MILLER = 18L;  // Miller Cylindrical
52
constexpr long VGRINT = 19L;  // Van der Grinten
53
constexpr long HOM = 20L;     // (Hotine) Oblique Mercator
54
constexpr long ROBIN = 21L;   // Robinson
55
// constexpr long SOM    = 22L;  // Space Oblique Mercator (SOM)
56
// constexpr long ALASKA = 23L;  // Alaska Conformal
57
// constexpr long GOODE  = 24L;  // Interrupted Goode Homolosine
58
constexpr long MOLL = 25L;  // Mollweide
59
// constexpr long IMOLL  = 26L;  // Interrupted Mollweide
60
// constexpr long HAMMER = 27L;  // Hammer
61
constexpr long WAGIV = 28L;   // Wagner IV
62
constexpr long WAGVII = 29L;  // Wagner VII
63
// constexpr long OBEQA  = 30L;  // Oblated Equal Area
64
// constexpr long ISINUS1 = 31L; // Integerized Sinusoidal Grid (the same as 99)
65
// constexpr long CEA    = 97L;  // Cylindrical Equal Area (Grid corners set
66
// in meters for EASE grid)
67
// constexpr long BCEA   = 98L;  // Cylindrical Equal Area (Grid corners set
68
// in DMS degs for EASE grid)
69
// constexpr long ISINUS = 99L;  // Integerized Sinusoidal Grid
70
// (added by Raj Gejjagaraguppe ARC for MODIS)
71
72
/************************************************************************/
73
/*                        GCTP ellipsoid codes.                         */
74
/************************************************************************/
75
76
constexpr long CLARKE1866 = 0L;
77
// constexpr long CLARKE1880         = 1L;
78
// constexpr long BESSEL             = 2L;
79
// constexpr long INTERNATIONAL1967  = 3L;
80
// constexpr long INTERNATIONAL1909  = 4L;
81
// constexpr long WGS72              = 5L;
82
// constexpr long EVEREST            = 6L;
83
// constexpr long WGS66              = 7L;
84
constexpr long GRS1980 = 8L;
85
// constexpr long AIRY               = 9L;
86
// constexpr long MODIFIED_EVEREST   = 10L;
87
// constexpr long MODIFIED_AIRY      = 11L;
88
constexpr long WGS84 = 12L;
89
// constexpr long SOUTHEAST_ASIA     = 13L;
90
// constexpr long AUSTRALIAN_NATIONAL= 14L;
91
// constexpr long KRASSOVSKY         = 15L;
92
// constexpr long HOUGH              = 16L;
93
// constexpr long MERCURY1960        = 17L;
94
// constexpr long MODIFIED_MERCURY   = 18L;
95
// constexpr long SPHERE             = 19L;
96
97
/************************************************************************/
98
/*        Correspondence between GCTP and EPSG ellipsoid codes.         */
99
/************************************************************************/
100
101
constexpr int aoEllipsUSGS[] = {
102
    7008,  // Clarke, 1866 (NAD1927)
103
    7034,  // Clarke, 1880
104
    7004,  // Bessel, 1841
105
    0,     // FIXME: New International, 1967 --- skipped
106
    7022,  // International, 1924 (Hayford, 1909) XXX?
107
    7043,  // WGS, 1972
108
    7042,  // Everest, 1830
109
    7025,  // FIXME: WGS, 1966
110
    7019,  // GRS, 1980 (NAD1983)
111
    7001,  // Airy, 1830
112
    7018,  // Modified Everest
113
    7002,  // Modified Airy
114
    7030,  // WGS, 1984 (GPS)
115
    0,     // FIXME: Southeast Asia --- skipped
116
    7003,  // Australian National, 1965
117
    7024,  // Krassovsky, 1940
118
    7053,  // Hough
119
    0,     // FIXME: Mercury, 1960 --- skipped
120
    0,     // FIXME: Modified Mercury, 1968 --- skipped
121
    7047,  // Sphere, rad 6370997 m (normal sphere)
122
    7006,  // Bessel, 1841 (Namibia)
123
    7016,  // Everest (Sabah & Sarawak)
124
    7044,  // Everest, 1956
125
    7056,  // Everest, Malaysia 1969
126
    7018,  // Everest, Malay & Singapr 1948
127
    0,     // FIXME: Everest, Pakistan --- skipped
128
    7022,  // Hayford (International 1924) XXX?
129
    7020,  // Helmert 1906
130
    7021,  // Indonesian, 1974
131
    7036,  // South American, 1969
132
    0      // FIXME: WGS 60 --- skipped
133
};
134
135
0
#define NUMBER_OF_USGS_ELLIPSOIDS static_cast<int>(CPL_ARRAYSIZE(aoEllipsUSGS))
136
137
/************************************************************************/
138
/*                         OSRImportFromUSGS()                          */
139
/************************************************************************/
140
141
/**
142
 * \brief Import coordinate system from USGS projection definition.
143
 *
144
 * This function is the same as OGRSpatialReference::importFromUSGS().
145
 */
146
OGRErr OSRImportFromUSGS(OGRSpatialReferenceH hSRS, long iProjsys, long iZone,
147
                         double *padfPrjParams, long iDatum)
148
149
0
{
150
0
    VALIDATE_POINTER1(hSRS, "OSRImportFromUSGS", OGRERR_FAILURE);
151
152
0
    return OGRSpatialReference::FromHandle(hSRS)->importFromUSGS(
153
0
        iProjsys, iZone, padfPrjParams, iDatum);
154
0
}
155
156
static double OGRSpatialReferenceUSGSUnpackNoOp(double dfVal)
157
0
{
158
0
    return dfVal;
159
0
}
160
161
static double OGRSpatialReferenceUSGSUnpackRadian(double dfVal)
162
0
{
163
0
    return dfVal * 180.0 / M_PI;
164
0
}
165
166
/************************************************************************/
167
/*                           importFromUSGS()                           */
168
/************************************************************************/
169
170
/**
171
\brief Import coordinate system from USGS projection definition.
172
173
This method will import projection definition in style, used by USGS GCTP
174
software. GCTP operates on angles in packed DMS format (see
175
CPLDecToPackedDMS() function for details), so all angle values (latitudes,
176
longitudes, azimuths, etc.) specified in the padfPrjParams array should
177
be in the packed DMS format, unless bAnglesInPackedDMSFormat is set to FALSE.
178
 *
179
This function is the equivalent of the C function OSRImportFromUSGS().
180
Note that the bAnglesInPackedDMSFormat parameter is only present in the C++
181
method. The C function assumes bAnglesInPackedFormat = TRUE.
182
183
@param iProjSys Input projection system code, used in GCTP.
184
185
@param iZone Input zone for UTM and State Plane projection systems. For
186
Southern Hemisphere UTM use a negative zone code. iZone ignored for all
187
other projections.
188
189
@param padfPrjParams Array of 15 coordinate system parameters. These
190
parameters differs for different projections.
191
192
\verbatim
193
Projection Transformation Package Projection Parameters:
194
195
----------------------------------------------------------------------------
196
                        |                    Array Element
197
 Code & Projection Id   |---------------------------------------------------
198
                        |   0  |   1  |  2   |  3   |   4   |    5    |6 | 7
199
----------------------------------------------------------------------------
200
 0 Geographic           |      |      |      |      |       |         |  |
201
 1 U T M                |Lon/Z |Lat/Z |      |      |       |         |  |
202
 2 State Plane          |      |      |      |      |       |         |  |
203
 3 Albers Equal Area    |SMajor|SMinor|STDPR1|STDPR2|CentMer|OriginLat|FE|FN
204
 4 Lambert Conformal C  |SMajor|SMinor|STDPR1|STDPR2|CentMer|OriginLat|FE|FN
205
 5 Mercator             |SMajor|SMinor|      |      |CentMer|TrueScale|FE|FN
206
 6 Polar Stereographic  |SMajor|SMinor|      |      |LongPol|TrueScale|FE|FN
207
 7 Polyconic            |SMajor|SMinor|      |      |CentMer|OriginLat|FE|FN
208
 8 Equid. Conic A       |SMajor|SMinor|STDPAR|      |CentMer|OriginLat|FE|FN
209
   Equid. Conic B       |SMajor|SMinor|STDPR1|STDPR2|CentMer|OriginLat|FE|FN
210
 9 Transverse Mercator  |SMajor|SMinor|Factor|      |CentMer|OriginLat|FE|FN
211
10 Stereographic        |Sphere|      |      |      |CentLon|CenterLat|FE|FN
212
11 Lambert Azimuthal    |Sphere|      |      |      |CentLon|CenterLat|FE|FN
213
12 Azimuthal            |Sphere|      |      |      |CentLon|CenterLat|FE|FN
214
13 Gnomonic             |Sphere|      |      |      |CentLon|CenterLat|FE|FN
215
14 Orthographic         |Sphere|      |      |      |CentLon|CenterLat|FE|FN
216
15 Gen. Vert. Near Per  |Sphere|      |Height|      |CentLon|CenterLat|FE|FN
217
16 Sinusoidal           |Sphere|      |      |      |CentMer|         |FE|FN
218
17 Equirectangular      |Sphere|      |      |      |CentMer|TrueScale|FE|FN
219
18 Miller Cylindrical   |Sphere|      |      |      |CentMer|         |FE|FN
220
19 Van der Grinten      |Sphere|      |      |      |CentMer|OriginLat|FE|FN
221
20 Hotin Oblique Merc A |SMajor|SMinor|Factor|      |       |OriginLat|FE|FN
222
   Hotin Oblique Merc B |SMajor|SMinor|Factor|AziAng|AzmthPt|OriginLat|FE|FN
223
21 Robinson             |Sphere|      |      |      |CentMer|         |FE|FN
224
22 Space Oblique Merc A |SMajor|SMinor|      |IncAng|AscLong|         |FE|FN
225
   Space Oblique Merc B |SMajor|SMinor|Satnum|Path  |       |         |FE|FN
226
23 Alaska Conformal     |SMajor|SMinor|      |      |       |         |FE|FN
227
24 Interrupted Goode    |Sphere|      |      |      |       |         |  |
228
25 Mollweide            |Sphere|      |      |      |CentMer|         |FE|FN
229
26 Interrupt Mollweide  |Sphere|      |      |      |       |         |  |
230
27 Hammer               |Sphere|      |      |      |CentMer|         |FE|FN
231
28 Wagner IV            |Sphere|      |      |      |CentMer|         |FE|FN
232
29 Wagner VII           |Sphere|      |      |      |CentMer|         |FE|FN
233
30 Oblated Equal Area   |Sphere|      |Shapem|Shapen|CentLon|CenterLat|FE|FN
234
----------------------------------------------------------------------------
235
236
      ----------------------------------------------------
237
                              |      Array Element       |
238
        Code & Projection Id  |---------------------------
239
                              |  8  |  9 |  10 | 11 | 12 |
240
      ----------------------------------------------------
241
       0 Geographic           |     |    |     |    |    |
242
       1 U T M                |     |    |     |    |    |
243
       2 State Plane          |     |    |     |    |    |
244
       3 Albers Equal Area    |     |    |     |    |    |
245
       4 Lambert Conformal C  |     |    |     |    |    |
246
       5 Mercator             |     |    |     |    |    |
247
       6 Polar Stereographic  |     |    |     |    |    |
248
       7 Polyconic            |     |    |     |    |    |
249
       8 Equid. Conic A       |zero |    |     |    |    |
250
         Equid. Conic B       |one  |    |     |    |    |
251
       9 Transverse Mercator  |     |    |     |    |    |
252
      10 Stereographic        |     |    |     |    |    |
253
      11 Lambert Azimuthal    |     |    |     |    |    |
254
      12 Azimuthal            |     |    |     |    |    |
255
      13 Gnomonic             |     |    |     |    |    |
256
      14 Orthographic         |     |    |     |    |    |
257
      15 Gen. Vert. Near Per  |     |    |     |    |    |
258
      16 Sinusoidal           |     |    |     |    |    |
259
      17 Equirectangular      |     |    |     |    |    |
260
      18 Miller Cylindrical   |     |    |     |    |    |
261
      19 Van der Grinten      |     |    |     |    |    |
262
      20 Hotin Oblique Merc A |Long1|Lat1|Long2|Lat2|zero|
263
         Hotin Oblique Merc B |     |    |     |    |one |
264
      21 Robinson             |     |    |     |    |    |
265
      22 Space Oblique Merc A |PSRev|LRat|PFlag|    |zero|
266
         Space Oblique Merc B |     |    |     |    |one |
267
      23 Alaska Conformal     |     |    |     |    |    |
268
      24 Interrupted Goode    |     |    |     |    |    |
269
      25 Mollweide            |     |    |     |    |    |
270
      26 Interrupt Mollweide  |     |    |     |    |    |
271
      27 Hammer               |     |    |     |    |    |
272
      28 Wagner IV            |     |    |     |    |    |
273
      29 Wagner VII           |     |    |     |    |    |
274
      30 Oblated Equal Area   |Angle|    |     |    |    |
275
      ----------------------------------------------------
276
277
  where
278
279
   Lon/Z     Longitude of any point in the UTM zone or zero.  If zero,
280
             a zone code must be specified.
281
   Lat/Z     Latitude of any point in the UTM zone or zero.  If zero, a
282
             zone code must be specified.
283
   SMajor    Semi-major axis of ellipsoid.  If zero, Clarke 1866 in meters
284
             is assumed.
285
   SMinor    Eccentricity squared of the ellipsoid if less than zero,
286
             if zero, a spherical form is assumed, or if greater than
287
             zero, the semi-minor axis of ellipsoid.
288
   Sphere    Radius of reference sphere.  If zero, 6370997 meters is used.
289
   STDPAR    Latitude of the standard parallel
290
   STDPR1    Latitude of the first standard parallel
291
   STDPR2    Latitude of the second standard parallel
292
   CentMer   Longitude of the central meridian
293
   OriginLat Latitude of the projection origin
294
   FE        False easting in the same units as the semi-major axis
295
   FN        False northing in the same units as the semi-major axis
296
   TrueScale Latitude of true scale
297
   LongPol   Longitude down below pole of map
298
   Factor    Scale factor at central meridian (Transverse Mercator) or
299
             center of projection (Hotine Oblique Mercator)
300
   CentLon   Longitude of center of projection
301
   CenterLat Latitude of center of projection
302
   Height    Height of perspective point
303
   Long1     Longitude of first point on center line (Hotine Oblique
304
             Mercator, format A)
305
   Long2     Longitude of second point on center line (Hotine Oblique
306
             Mercator, format A)
307
   Lat1      Latitude of first point on center line (Hotine Oblique
308
             Mercator, format A)
309
   Lat2      Latitude of second point on center line (Hotine Oblique
310
             Mercator, format A)
311
   AziAng    Azimuth angle east of north of center line (Hotine Oblique
312
             Mercator, format B)
313
   AzmthPt   Longitude of point on central meridian where azimuth occurs
314
             (Hotine Oblique Mercator, format B)
315
   IncAng    Inclination of orbit at ascending node, counter-clockwise
316
             from equator (SOM, format A)
317
   AscLong   Longitude of ascending orbit at equator (SOM, format A)
318
   PSRev     Period of satellite revolution in minutes (SOM, format A)
319
   LRat      Landsat ratio to compensate for confusion at northern end
320
             of orbit (SOM, format A -- use 0.5201613)
321
   PFlag     End of path flag for Landsat:  0 = start of path,
322
             1 = end of path (SOM, format A)
323
   Satnum    Landsat Satellite Number (SOM, format B)
324
   Path      Landsat Path Number (Use WRS-1 for Landsat 1, 2 and 3 and
325
             WRS-2 for Landsat 4, 5 and 6.)  (SOM, format B)
326
   Shapem    Oblated Equal Area oval shape parameter m
327
   Shapen    Oblated Equal Area oval shape parameter n
328
   Angle     Oblated Equal Area oval rotation angle
329
330
Array elements 13 and 14 are set to zero. All array elements with blank
331
fields are set to zero too.
332
\endverbatim
333
334
@param iDatum Input spheroid.<p>
335
336
If the datum code is negative, the first two values in the parameter array
337
(param) are used to define the values as follows:
338
339
<ul>
340
341
<li> If padfPrjParams[0] is a non-zero value and padfPrjParams[1] is
342
greater than one, the semimajor axis is set to padfPrjParams[0] and
343
the semiminor axis is set to padfPrjParams[1].
344
345
<li> If padfPrjParams[0] is nonzero and padfPrjParams[1] is greater than
346
zero but less than or equal to one, the semimajor axis is set to
347
padfPrjParams[0] and the semiminor axis is computed from the eccentricity
348
squared value padfPrjParams[1]:<p>
349
350
semiminor = sqrt(1.0 - ES)semimajor<p>
351
352
where<p>
353
354
ES = eccentricity squared
355
356
<li> If padfPrjParams[0] is nonzero and padfPrjParams[1] is equal to zero,
357
the semimajor axis and semiminor axis are set to padfPrjParams[0].
358
359
<li> If padfPrjParams[0] equals zero and padfPrjParams[1] is greater than
360
zero, the default Clarke 1866 is used to assign values to the semimajor
361
axis and semiminor axis.
362
363
<li> If padfPrjParams[0] and padfPrjParams[1] equals zero, the semimajor
364
axis is set to 6370997.0 and the semiminor axis is set to zero.
365
366
</ul>
367
368
If a datum code is zero or greater, the semimajor and semiminor axis are
369
defined by the datum code as found in the following table:
370
371
Supported Datums are:
372
<ul>
373
<li>0: Clarke 1866 (default)
374
<li>1: Clarke 1880
375
<li>2: Bessel
376
<li>3: International 1967
377
<li>4: International 1909
378
<li>5: WGS 72
379
<li>6: Everest
380
<li>7: WGS 66
381
<li>8: GRS 1980/WGS 84
382
<li>9: Airy
383
<li>10: Modified Everest
384
<li>11: Modified Airy
385
<li>12: WGS 84
386
<li>13: Southeast Asia
387
<li>14: Australian National
388
<li>15: Krassovsky
389
<li>16: Hough
390
<li>17: Mercury 1960
391
<li>18: Modified Mercury 1968
392
<li>19: Sphere of Radius 6370997 meters
393
</ul>
394
395
@param nUSGSAngleFormat one of USGS_ANGLE_DECIMALDEGREES,
396
   USGS_ANGLE_PACKEDDMS, or USGS_ANGLE_RADIANS (default is
397
   USGS_ANGLE_PACKEDDMS).
398
399
@return OGRERR_NONE on success or an error code in case of failure.
400
 */
401
402
OGRErr OGRSpatialReference::importFromUSGS(long iProjSys, long iZone,
403
                                           double *padfPrjParams, long iDatum,
404
                                           int nUSGSAngleFormat)
405
406
0
{
407
0
    if (!padfPrjParams)
408
0
        return OGRERR_CORRUPT_DATA;
409
410
0
    double (*pfnUnpackAnglesFn)(double) = nullptr;
411
412
0
    if (nUSGSAngleFormat == USGS_ANGLE_DECIMALDEGREES)
413
0
        pfnUnpackAnglesFn = OGRSpatialReferenceUSGSUnpackNoOp;
414
0
    else if (nUSGSAngleFormat == USGS_ANGLE_RADIANS)
415
0
        pfnUnpackAnglesFn = OGRSpatialReferenceUSGSUnpackRadian;
416
0
    else
417
0
        pfnUnpackAnglesFn = CPLPackedDMSToDec;
418
419
    /* -------------------------------------------------------------------- */
420
    /*      Operate on the basis of the projection code.                    */
421
    /* -------------------------------------------------------------------- */
422
0
    switch (iProjSys)
423
0
    {
424
0
        case GEO:
425
0
            break;
426
427
0
        case UTM:
428
0
        {
429
0
            int bNorth = TRUE;
430
431
0
            if (!iZone)
432
0
            {
433
0
                if (padfPrjParams[2] != 0.0)
434
0
                {
435
0
                    iZone = static_cast<long>(padfPrjParams[2]);
436
0
                }
437
0
                else if (padfPrjParams[0] != 0.0 && padfPrjParams[1] != 0.0)
438
0
                {
439
0
                    const double dfUnpackedAngle =
440
0
                        pfnUnpackAnglesFn(padfPrjParams[0]);
441
0
                    iZone = static_cast<long>(
442
0
                        ((dfUnpackedAngle + 180.0) / 6.0) + 1.0);
443
0
                    if (dfUnpackedAngle < 0)
444
0
                        bNorth = FALSE;
445
0
                }
446
0
            }
447
448
0
            if (iZone < -60 || iZone > 60)
449
0
                return OGRERR_CORRUPT_DATA;
450
451
0
            if (iZone < 0)
452
0
            {
453
0
                iZone = -iZone;
454
0
                bNorth = FALSE;
455
0
            }
456
0
            SetUTM(static_cast<int>(iZone), bNorth);
457
0
        }
458
0
        break;
459
460
0
        case SPCS:
461
0
        {
462
0
            int bNAD83 = TRUE;
463
464
0
            if (iDatum == 0)
465
0
                bNAD83 = FALSE;
466
0
            else if (iDatum != 8)
467
0
                CPLError(CE_Warning, CPLE_AppDefined,
468
0
                         "Wrong datum for State Plane projection %d. "
469
0
                         "Should be 0 or 8.",
470
0
                         static_cast<int>(iDatum));
471
472
0
            SetStatePlane(static_cast<int>(iZone), bNAD83);
473
0
        }
474
0
        break;
475
476
0
        case ALBERS:
477
0
            SetACEA(pfnUnpackAnglesFn(padfPrjParams[2]),
478
0
                    pfnUnpackAnglesFn(padfPrjParams[3]),
479
0
                    pfnUnpackAnglesFn(padfPrjParams[5]),
480
0
                    pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
481
0
                    padfPrjParams[7]);
482
0
            break;
483
484
0
        case LAMCC:
485
0
            SetLCC(pfnUnpackAnglesFn(padfPrjParams[2]),
486
0
                   pfnUnpackAnglesFn(padfPrjParams[3]),
487
0
                   pfnUnpackAnglesFn(padfPrjParams[5]),
488
0
                   pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
489
0
                   padfPrjParams[7]);
490
0
            break;
491
492
0
        case MERCAT:
493
0
            SetMercator(pfnUnpackAnglesFn(padfPrjParams[5]),
494
0
                        pfnUnpackAnglesFn(padfPrjParams[4]), 1.0,
495
0
                        padfPrjParams[6], padfPrjParams[7]);
496
0
            break;
497
498
0
        case PS:
499
0
            SetPS(pfnUnpackAnglesFn(padfPrjParams[5]),
500
0
                  pfnUnpackAnglesFn(padfPrjParams[4]), 1.0, padfPrjParams[6],
501
0
                  padfPrjParams[7]);
502
503
0
            break;
504
505
0
        case POLYC:
506
0
            SetPolyconic(pfnUnpackAnglesFn(padfPrjParams[5]),
507
0
                         pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
508
0
                         padfPrjParams[7]);
509
0
            break;
510
511
0
        case EQUIDC:
512
0
            if (padfPrjParams[8] != 0.0)
513
0
            {
514
0
                SetEC(pfnUnpackAnglesFn(padfPrjParams[2]),
515
0
                      pfnUnpackAnglesFn(padfPrjParams[3]),
516
0
                      pfnUnpackAnglesFn(padfPrjParams[5]),
517
0
                      pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
518
0
                      padfPrjParams[7]);
519
0
            }
520
0
            else
521
0
            {
522
0
                SetEC(pfnUnpackAnglesFn(padfPrjParams[2]),
523
0
                      pfnUnpackAnglesFn(padfPrjParams[2]),
524
0
                      pfnUnpackAnglesFn(padfPrjParams[5]),
525
0
                      pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
526
0
                      padfPrjParams[7]);
527
0
            }
528
0
            break;
529
530
0
        case TM:
531
0
            SetTM(pfnUnpackAnglesFn(padfPrjParams[5]),
532
0
                  pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[2],
533
0
                  padfPrjParams[6], padfPrjParams[7]);
534
0
            break;
535
536
0
        case STEREO:
537
0
            SetStereographic(pfnUnpackAnglesFn(padfPrjParams[5]),
538
0
                             pfnUnpackAnglesFn(padfPrjParams[4]), 1.0,
539
0
                             padfPrjParams[6], padfPrjParams[7]);
540
0
            break;
541
542
0
        case LAMAZ:
543
0
            SetLAEA(pfnUnpackAnglesFn(padfPrjParams[5]),
544
0
                    pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
545
0
                    padfPrjParams[7]);
546
0
            break;
547
548
0
        case AZMEQD:
549
0
            SetAE(pfnUnpackAnglesFn(padfPrjParams[5]),
550
0
                  pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
551
0
                  padfPrjParams[7]);
552
0
            break;
553
554
0
        case GNOMON:
555
0
            SetGnomonic(pfnUnpackAnglesFn(padfPrjParams[5]),
556
0
                        pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
557
0
                        padfPrjParams[7]);
558
0
            break;
559
560
0
        case ORTHO:
561
0
            SetOrthographic(pfnUnpackAnglesFn(padfPrjParams[5]),
562
0
                            pfnUnpackAnglesFn(padfPrjParams[4]),
563
0
                            padfPrjParams[6], padfPrjParams[7]);
564
0
            break;
565
566
            // FIXME: GVNSP --- General Vertical Near-Side Perspective skipped.
567
568
0
        case SNSOID:
569
0
            SetSinusoidal(pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
570
0
                          padfPrjParams[7]);
571
0
            break;
572
573
0
        case EQRECT:
574
0
            SetEquirectangular2(0.0, pfnUnpackAnglesFn(padfPrjParams[4]),
575
0
                                pfnUnpackAnglesFn(padfPrjParams[5]),
576
0
                                padfPrjParams[6], padfPrjParams[7]);
577
0
            break;
578
579
0
        case MILLER:
580
0
            SetMC(pfnUnpackAnglesFn(padfPrjParams[5]),
581
0
                  pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
582
0
                  padfPrjParams[7]);
583
0
            break;
584
585
0
        case VGRINT:
586
0
            SetVDG(pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
587
0
                   padfPrjParams[7]);
588
0
            break;
589
590
0
        case HOM:
591
0
            if (padfPrjParams[12] != 0.0)
592
0
            {
593
0
                SetHOM(pfnUnpackAnglesFn(padfPrjParams[5]),
594
0
                       pfnUnpackAnglesFn(padfPrjParams[4]),
595
0
                       pfnUnpackAnglesFn(padfPrjParams[3]), 0.0,
596
0
                       padfPrjParams[2], padfPrjParams[6], padfPrjParams[7]);
597
0
            }
598
0
            else
599
0
            {
600
0
                SetHOM2PNO(pfnUnpackAnglesFn(padfPrjParams[5]),
601
0
                           pfnUnpackAnglesFn(padfPrjParams[9]),
602
0
                           pfnUnpackAnglesFn(padfPrjParams[8]),
603
0
                           pfnUnpackAnglesFn(padfPrjParams[11]),
604
0
                           pfnUnpackAnglesFn(padfPrjParams[10]),
605
0
                           padfPrjParams[2], padfPrjParams[6],
606
0
                           padfPrjParams[7]);
607
0
            }
608
0
            break;
609
610
0
        case ROBIN:
611
0
            SetRobinson(pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
612
0
                        padfPrjParams[7]);
613
0
            break;
614
615
            // FIXME: SOM --- Space Oblique Mercator skipped.
616
            // FIXME: ALASKA --- Alaska Conformal skipped.
617
            // FIXME: GOODE --- Interrupted Goode skipped.
618
619
0
        case MOLL:
620
0
            SetMollweide(pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
621
0
                         padfPrjParams[7]);
622
0
            break;
623
624
            // FIXME: IMOLL --- Interrupted Mollweide skipped.
625
            // FIXME: HAMMER --- Hammer skipped.
626
627
0
        case WAGIV:
628
0
            SetWagner(4, 0.0, padfPrjParams[6], padfPrjParams[7]);
629
0
            break;
630
631
0
        case WAGVII:
632
0
            SetWagner(7, 0.0, padfPrjParams[6], padfPrjParams[7]);
633
0
            break;
634
635
            // FIXME: OBEQA --- Oblated Equal Area skipped.
636
            // FIXME: ISINUS1 --- Integerized Sinusoidal Grid (the same as 99).
637
            // FIXME: CEA --- Cylindrical Equal Area skipped (Grid corners set
638
            // in meters for EASE grid).
639
            // FIXME: BCEA --- Cylindrical Equal Area skipped (Grid corners set
640
            // in DMS degs for EASE grid).
641
            // FIXME: ISINUS --- Integrized Sinusoidal skipped.
642
643
0
        default:
644
0
            CPLDebug("OSR_USGS", "Unsupported projection: %ld", iProjSys);
645
0
            SetLocalCS(
646
0
                CPLString().Printf("GCTP projection number %ld", iProjSys));
647
0
            break;
648
0
    }
649
650
    /* -------------------------------------------------------------------- */
651
    /*      Try to translate the datum/spheroid.                            */
652
    /* -------------------------------------------------------------------- */
653
654
0
    if (!IsLocal())
655
0
    {
656
0
        char *pszName = nullptr;
657
0
        double dfSemiMajor = 0.0;
658
0
        double dfInvFlattening = 0.0;
659
660
0
        if (iDatum < 0)  // Use specified ellipsoid parameters.
661
0
        {
662
0
            if (padfPrjParams[0] > 0.0)
663
0
            {
664
0
                if (padfPrjParams[1] > 1.0)
665
0
                {
666
0
                    dfInvFlattening = OSRCalcInvFlattening(padfPrjParams[0],
667
0
                                                           padfPrjParams[1]);
668
0
                }
669
0
                else if (padfPrjParams[1] > 0.0)
670
0
                {
671
0
                    dfInvFlattening =
672
0
                        1.0 / (1.0 - sqrt(1.0 - padfPrjParams[1]));
673
0
                }
674
0
                else
675
0
                {
676
0
                    dfInvFlattening = 0.0;
677
0
                }
678
679
0
                SetGeogCS("Unknown datum based upon the custom spheroid",
680
0
                          "Not specified (based on custom spheroid)",
681
0
                          "Custom spheroid", padfPrjParams[0], dfInvFlattening,
682
0
                          nullptr, 0, nullptr, 0);
683
0
            }
684
0
            else if (padfPrjParams[1] > 0.0)  // Clarke 1866.
685
0
            {
686
0
                if (OSRGetEllipsoidInfo(7008, &pszName, &dfSemiMajor,
687
0
                                        &dfInvFlattening) == OGRERR_NONE)
688
0
                {
689
0
                    SetGeogCS(
690
0
                        CPLString().Printf(
691
0
                            "Unknown datum based upon the %s ellipsoid",
692
0
                            pszName),
693
0
                        CPLString().Printf(
694
0
                            "Not specified (based on %s spheroid)", pszName),
695
0
                        pszName, dfSemiMajor, dfInvFlattening, nullptr, 0.0,
696
0
                        nullptr, 0.0);
697
0
                    SetAuthority("SPHEROID", "EPSG", 7008);
698
0
                }
699
0
            }
700
0
            else  // Sphere, rad 6370997 m
701
0
            {
702
0
                if (OSRGetEllipsoidInfo(7047, &pszName, &dfSemiMajor,
703
0
                                        &dfInvFlattening) == OGRERR_NONE)
704
0
                {
705
0
                    SetGeogCS(
706
0
                        CPLString().Printf(
707
0
                            "Unknown datum based upon the %s ellipsoid",
708
0
                            pszName),
709
0
                        CPLString().Printf(
710
0
                            "Not specified (based on %s spheroid)", pszName),
711
0
                        pszName, dfSemiMajor, dfInvFlattening, nullptr, 0.0,
712
0
                        nullptr, 0.0);
713
0
                    SetAuthority("SPHEROID", "EPSG", 7047);
714
0
                }
715
0
            }
716
0
        }
717
0
        else if (iDatum < NUMBER_OF_USGS_ELLIPSOIDS && aoEllipsUSGS[iDatum])
718
0
        {
719
0
            if (aoEllipsUSGS[iDatum] == 7030)  // WGS 84 ellipsoid
720
0
            {
721
                // Assume a WGS 84 datum
722
0
                SetWellKnownGeogCS("WGS84");
723
0
            }
724
0
            else if (OSRGetEllipsoidInfo(aoEllipsUSGS[iDatum], &pszName,
725
0
                                         &dfSemiMajor,
726
0
                                         &dfInvFlattening) == OGRERR_NONE)
727
0
            {
728
0
                SetGeogCS(
729
0
                    CPLString().Printf(
730
0
                        "Unknown datum based upon the %s ellipsoid", pszName),
731
0
                    CPLString().Printf("Not specified (based on %s spheroid)",
732
0
                                       pszName),
733
0
                    pszName, dfSemiMajor, dfInvFlattening, nullptr, 0.0,
734
0
                    nullptr, 0.0);
735
0
                SetAuthority("SPHEROID", "EPSG", aoEllipsUSGS[iDatum]);
736
0
            }
737
0
            else
738
0
            {
739
0
                CPLError(CE_Warning, CPLE_AppDefined,
740
0
                         "Failed to lookup datum code %d. "
741
0
                         "Falling back to use WGS84.",
742
0
                         static_cast<int>(iDatum));
743
0
                SetWellKnownGeogCS("WGS84");
744
0
            }
745
0
        }
746
0
        else
747
0
        {
748
0
            CPLError(CE_Warning, CPLE_AppDefined,
749
0
                     "Wrong datum code %d. Supported datums 0--%d only.  "
750
0
                     "Setting WGS84 as a fallback.",
751
0
                     static_cast<int>(iDatum), NUMBER_OF_USGS_ELLIPSOIDS);
752
0
            SetWellKnownGeogCS("WGS84");
753
0
        }
754
755
0
        CPLFree(pszName);
756
0
    }
757
758
    /* -------------------------------------------------------------------- */
759
    /*      Grid units translation                                          */
760
    /* -------------------------------------------------------------------- */
761
0
    if (IsLocal() || IsProjected())
762
0
        SetLinearUnits(SRS_UL_METER, 1.0);
763
764
0
    if (iDatum >= 0 && iDatum < NUMBER_OF_USGS_ELLIPSOIDS &&
765
0
        aoEllipsUSGS[iDatum] == 7030)
766
0
    {
767
0
        if (AutoIdentifyEPSG() == OGRERR_NONE)
768
0
        {
769
0
            const char *pszAuthName = GetAuthorityName();
770
0
            const char *pszAuthCode = GetAuthorityCode();
771
0
            if (pszAuthName && pszAuthCode && EQUAL(pszAuthName, "EPSG"))
772
0
                CPL_IGNORE_RET_VAL(importFromEPSG(atoi(pszAuthCode)));
773
0
        }
774
0
    }
775
776
0
    return OGRERR_NONE;
777
0
}
778
779
/************************************************************************/
780
/*                          OSRExportToUSGS()                           */
781
/************************************************************************/
782
/**
783
 * \brief Export coordinate system in USGS GCTP projection definition.
784
 *
785
 * This function is the same as OGRSpatialReference::exportToUSGS().
786
 */
787
788
OGRErr OSRExportToUSGS(OGRSpatialReferenceH hSRS, long *piProjSys, long *piZone,
789
                       double **ppadfPrjParams, long *piDatum)
790
791
0
{
792
0
    VALIDATE_POINTER1(hSRS, "OSRExportToUSGS", OGRERR_FAILURE);
793
794
0
    *ppadfPrjParams = nullptr;
795
796
0
    return OGRSpatialReference::FromHandle(hSRS)->exportToUSGS(
797
0
        piProjSys, piZone, ppadfPrjParams, piDatum);
798
0
}
799
800
/************************************************************************/
801
/*                            exportToUSGS()                            */
802
/************************************************************************/
803
804
/**
805
 * \brief Export coordinate system in USGS GCTP projection definition.
806
 *
807
 * This method is the equivalent of the C function OSRExportToUSGS().
808
 *
809
 * @param piProjSys Pointer to variable, where the projection system code will
810
 * be returned.
811
 *
812
 * @param piZone Pointer to variable, where the zone for UTM and State Plane
813
 * projection systems will be returned.
814
 *
815
 * @param ppadfPrjParams Pointer to which dynamically allocated array of
816
 * 15 projection parameters will be assigned. See importFromUSGS() for
817
 * the list of parameters. Caller responsible to free this array.
818
 *
819
 * @param piDatum Pointer to variable, where the datum code will
820
 * be returned.
821
 *
822
 * @return OGRERR_NONE on success or an error code on failure.
823
 */
824
825
OGRErr OGRSpatialReference::exportToUSGS(long *piProjSys, long *piZone,
826
                                         double **ppadfPrjParams,
827
                                         long *piDatum) const
828
829
0
{
830
0
    const char *pszProjection = GetAttrValue("PROJECTION");
831
832
    /* -------------------------------------------------------------------- */
833
    /*      Fill all projection parameters with zero.                       */
834
    /* -------------------------------------------------------------------- */
835
0
    *ppadfPrjParams = static_cast<double *>(CPLMalloc(15 * sizeof(double)));
836
0
    for (int i = 0; i < 15; i++)
837
0
        (*ppadfPrjParams)[i] = 0.0;
838
839
0
    *piZone = 0L;
840
841
    /* ==================================================================== */
842
    /*      Handle the projection definition.                               */
843
    /* ==================================================================== */
844
0
    if (IsLocal())
845
0
        *piProjSys = GEO;
846
847
0
    else if (pszProjection == nullptr)
848
0
    {
849
#ifdef DEBUG
850
        CPLDebug("OSR_USGS",
851
                 "Empty projection definition, considered as Geographic");
852
#endif
853
0
        *piProjSys = GEO;
854
0
    }
855
856
0
    else if (EQUAL(pszProjection, SRS_PT_ALBERS_CONIC_EQUAL_AREA))
857
0
    {
858
0
        *piProjSys = ALBERS;
859
0
        (*ppadfPrjParams)[2] =
860
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
861
0
        (*ppadfPrjParams)[3] =
862
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
863
0
        (*ppadfPrjParams)[4] =
864
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
865
0
        (*ppadfPrjParams)[5] =
866
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
867
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
868
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
869
0
    }
870
871
0
    else if (EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP))
872
0
    {
873
0
        *piProjSys = LAMCC;
874
0
        (*ppadfPrjParams)[2] =
875
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
876
0
        (*ppadfPrjParams)[3] =
877
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
878
0
        (*ppadfPrjParams)[4] =
879
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
880
0
        (*ppadfPrjParams)[5] =
881
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
882
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
883
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
884
0
    }
885
886
0
    else if (EQUAL(pszProjection, SRS_PT_MERCATOR_1SP))
887
0
    {
888
0
        *piProjSys = MERCAT;
889
0
        (*ppadfPrjParams)[4] =
890
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
891
0
        (*ppadfPrjParams)[5] =
892
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
893
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
894
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
895
0
    }
896
897
0
    else if (EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC))
898
0
    {
899
0
        *piProjSys = PS;
900
0
        (*ppadfPrjParams)[4] =
901
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
902
0
        (*ppadfPrjParams)[5] =
903
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
904
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
905
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
906
0
    }
907
908
0
    else if (EQUAL(pszProjection, SRS_PT_POLYCONIC))
909
0
    {
910
0
        *piProjSys = POLYC;
911
0
        (*ppadfPrjParams)[4] =
912
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
913
0
        (*ppadfPrjParams)[5] =
914
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
915
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
916
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
917
0
    }
918
919
0
    else if (EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC))
920
0
    {
921
0
        *piProjSys = EQUIDC;
922
0
        (*ppadfPrjParams)[2] =
923
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
924
0
        (*ppadfPrjParams)[3] =
925
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
926
0
        (*ppadfPrjParams)[4] =
927
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
928
0
        (*ppadfPrjParams)[5] =
929
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
930
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
931
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
932
0
        (*ppadfPrjParams)[8] = 1.0;
933
0
    }
934
935
0
    else if (EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR))
936
0
    {
937
0
        int bNorth;
938
939
0
        *piZone = GetUTMZone(&bNorth);
940
941
0
        if (*piZone != 0)
942
0
        {
943
0
            *piProjSys = UTM;
944
0
            if (!bNorth)
945
0
                *piZone = -*piZone;
946
0
        }
947
0
        else
948
0
        {
949
0
            *piProjSys = TM;
950
0
            (*ppadfPrjParams)[2] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
951
0
            (*ppadfPrjParams)[4] = CPLDecToPackedDMS(
952
0
                GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
953
0
            (*ppadfPrjParams)[5] = CPLDecToPackedDMS(
954
0
                GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
955
0
            (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
956
0
            (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
957
0
        }
958
0
    }
959
960
0
    else if (EQUAL(pszProjection, SRS_PT_STEREOGRAPHIC))
961
0
    {
962
0
        *piProjSys = STEREO;
963
0
        (*ppadfPrjParams)[4] =
964
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
965
0
        (*ppadfPrjParams)[5] =
966
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
967
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
968
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
969
0
    }
970
971
0
    else if (EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA))
972
0
    {
973
0
        *piProjSys = LAMAZ;
974
0
        (*ppadfPrjParams)[4] =
975
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
976
0
        (*ppadfPrjParams)[5] =
977
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
978
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
979
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
980
0
    }
981
982
0
    else if (EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT))
983
0
    {
984
0
        *piProjSys = AZMEQD;
985
0
        (*ppadfPrjParams)[4] =
986
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
987
0
        (*ppadfPrjParams)[5] =
988
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0));
989
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
990
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
991
0
    }
992
993
0
    else if (EQUAL(pszProjection, SRS_PT_GNOMONIC))
994
0
    {
995
0
        *piProjSys = GNOMON;
996
0
        (*ppadfPrjParams)[4] =
997
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
998
0
        (*ppadfPrjParams)[5] =
999
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
1000
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1001
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1002
0
    }
1003
1004
0
    else if (EQUAL(pszProjection, SRS_PT_ORTHOGRAPHIC))
1005
0
    {
1006
0
        *piProjSys = ORTHO;
1007
0
        (*ppadfPrjParams)[4] =
1008
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
1009
0
        (*ppadfPrjParams)[5] =
1010
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
1011
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1012
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1013
0
    }
1014
1015
0
    else if (EQUAL(pszProjection, SRS_PT_SINUSOIDAL))
1016
0
    {
1017
0
        *piProjSys = SNSOID;
1018
0
        (*ppadfPrjParams)[4] =
1019
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
1020
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1021
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1022
0
    }
1023
1024
0
    else if (EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR))
1025
0
    {
1026
0
        *piProjSys = EQRECT;
1027
0
        (*ppadfPrjParams)[4] =
1028
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
1029
0
        (*ppadfPrjParams)[5] =
1030
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
1031
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1032
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1033
0
    }
1034
1035
0
    else if (EQUAL(pszProjection, SRS_PT_MILLER_CYLINDRICAL))
1036
0
    {
1037
0
        *piProjSys = MILLER;
1038
0
        (*ppadfPrjParams)[4] =
1039
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
1040
0
        (*ppadfPrjParams)[5] =
1041
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0));
1042
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1043
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1044
0
    }
1045
1046
0
    else if (EQUAL(pszProjection, SRS_PT_VANDERGRINTEN))
1047
0
    {
1048
0
        *piProjSys = VGRINT;
1049
0
        (*ppadfPrjParams)[4] =
1050
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
1051
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1052
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1053
0
    }
1054
1055
0
    else if (EQUAL(pszProjection, SRS_PT_HOTINE_OBLIQUE_MERCATOR))
1056
0
    {
1057
0
        *piProjSys = HOM;
1058
0
        (*ppadfPrjParams)[2] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
1059
0
        (*ppadfPrjParams)[3] =
1060
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_AZIMUTH, 0.0));
1061
0
        (*ppadfPrjParams)[4] =
1062
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
1063
0
        (*ppadfPrjParams)[5] =
1064
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0));
1065
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1066
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1067
0
        (*ppadfPrjParams)[12] = 1.0;
1068
0
    }
1069
1070
0
    else if (EQUAL(pszProjection,
1071
0
                   SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN))
1072
0
    {
1073
0
        *piProjSys = HOM;
1074
0
        (*ppadfPrjParams)[2] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
1075
0
        (*ppadfPrjParams)[5] =
1076
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0));
1077
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1078
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1079
0
        (*ppadfPrjParams)[8] = CPLDecToPackedDMS(
1080
0
            GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0));
1081
0
        (*ppadfPrjParams)[9] =
1082
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0));
1083
0
        (*ppadfPrjParams)[10] = CPLDecToPackedDMS(
1084
0
            GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 0.0));
1085
0
        (*ppadfPrjParams)[11] =
1086
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_2, 0.0));
1087
0
        (*ppadfPrjParams)[12] = 0.0;
1088
0
    }
1089
1090
0
    else if (EQUAL(pszProjection, SRS_PT_ROBINSON))
1091
0
    {
1092
0
        *piProjSys = ROBIN;
1093
0
        (*ppadfPrjParams)[4] =
1094
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
1095
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1096
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1097
0
    }
1098
1099
0
    else if (EQUAL(pszProjection, SRS_PT_MOLLWEIDE))
1100
0
    {
1101
0
        *piProjSys = MOLL;
1102
0
        (*ppadfPrjParams)[4] =
1103
0
            CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
1104
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1105
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1106
0
    }
1107
1108
0
    else if (EQUAL(pszProjection, SRS_PT_WAGNER_IV))
1109
0
    {
1110
0
        *piProjSys = WAGIV;
1111
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1112
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1113
0
    }
1114
1115
0
    else if (EQUAL(pszProjection, SRS_PT_WAGNER_VII))
1116
0
    {
1117
0
        *piProjSys = WAGVII;
1118
0
        (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
1119
0
        (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
1120
0
    }
1121
    // Projection unsupported by GCTP.
1122
0
    else
1123
0
    {
1124
0
        CPLDebug("OSR_USGS",
1125
0
                 "Projection \"%s\" unsupported by USGS GCTP. "
1126
0
                 "Geographic system will be used.",
1127
0
                 pszProjection);
1128
0
        *piProjSys = GEO;
1129
0
    }
1130
1131
    /* -------------------------------------------------------------------- */
1132
    /*      Translate the datum.                                            */
1133
    /* -------------------------------------------------------------------- */
1134
0
    const char *pszDatum = GetAttrValue("DATUM");
1135
1136
0
    if (pszDatum)
1137
0
    {
1138
0
        if (EQUAL(pszDatum, SRS_DN_NAD27))
1139
0
        {
1140
0
            *piDatum = CLARKE1866;
1141
0
        }
1142
0
        else if (EQUAL(pszDatum, SRS_DN_NAD83))
1143
0
        {
1144
0
            *piDatum = GRS1980;
1145
0
        }
1146
0
        else if (EQUAL(pszDatum, SRS_DN_WGS84))
1147
0
        {
1148
0
            *piDatum = WGS84;
1149
0
        }
1150
        // If not found well known datum, translate ellipsoid.
1151
0
        else
1152
0
        {
1153
0
            const double dfSemiMajor = GetSemiMajor();
1154
0
            const double dfInvFlattening = GetInvFlattening();
1155
1156
#ifdef DEBUG
1157
            CPLDebug("OSR_USGS",
1158
                     "Datum \"%s\" unsupported by USGS GCTP. "
1159
                     "Try to translate ellipsoid definition.",
1160
                     pszDatum);
1161
#endif
1162
1163
0
            int i = 0;  // Used after for.
1164
0
            for (; i < NUMBER_OF_USGS_ELLIPSOIDS; i++)
1165
0
            {
1166
0
                double dfSM = 0.0;
1167
0
                double dfIF = 0.0;
1168
1169
0
                if (OSRGetEllipsoidInfo(aoEllipsUSGS[i], nullptr, &dfSM,
1170
0
                                        &dfIF) == OGRERR_NONE &&
1171
0
                    CPLIsEqual(dfSemiMajor, dfSM) &&
1172
0
                    CPLIsEqual(dfInvFlattening, dfIF))
1173
0
                {
1174
0
                    *piDatum = i;
1175
0
                    break;
1176
0
                }
1177
0
            }
1178
1179
0
            if (i == NUMBER_OF_USGS_ELLIPSOIDS)  // Didn't found matches; set
1180
0
            {                                    // custom ellipsoid parameters.
1181
#ifdef DEBUG
1182
                CPLDebug("OSR_USGS",
1183
                         "Ellipsoid \"%s\" unsupported by USGS GCTP. "
1184
                         "Custom ellipsoid definition will be used.",
1185
                         pszDatum);
1186
#endif
1187
0
                *piDatum = -1;
1188
0
                (*ppadfPrjParams)[0] = dfSemiMajor;
1189
0
                if (std::abs(dfInvFlattening) < 0.000000000001)
1190
0
                {
1191
0
                    (*ppadfPrjParams)[1] = dfSemiMajor;
1192
0
                }
1193
0
                else
1194
0
                {
1195
0
                    (*ppadfPrjParams)[1] =
1196
0
                        dfSemiMajor * (1.0 - 1.0 / dfInvFlattening);
1197
0
                }
1198
0
            }
1199
0
        }
1200
0
    }
1201
0
    else
1202
0
    {
1203
0
        *piDatum = -1;
1204
0
    }
1205
1206
0
    return OGRERR_NONE;
1207
0
}