LCOV - code coverage report
Current view: top level - ogr - ogr_srs_usgs.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 129 462 27.9 %
Date: 2024-11-21 22:18:42 Functions: 5 6 83.3 %

          Line data    Source code
       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             : #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           2 : OGRErr OSRImportFromUSGS(OGRSpatialReferenceH hSRS, long iProjsys, long iZone,
     147             :                          double *padfPrjParams, long iDatum)
     148             : 
     149             : {
     150           2 :     VALIDATE_POINTER1(hSRS, "OSRImportFromUSGS", OGRERR_FAILURE);
     151             : 
     152           2 :     return OGRSpatialReference::FromHandle(hSRS)->importFromUSGS(
     153           2 :         iProjsys, iZone, padfPrjParams, iDatum);
     154             : }
     155             : 
     156           8 : static double OGRSpatialReferenceUSGSUnpackNoOp(double dfVal)
     157             : {
     158           8 :     return dfVal;
     159             : }
     160             : 
     161           0 : static double OGRSpatialReferenceUSGSUnpackRadian(double dfVal)
     162             : {
     163           0 :     return dfVal * 180.0 / M_PI;
     164             : }
     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          24 : OGRErr OGRSpatialReference::importFromUSGS(long iProjSys, long iZone,
     403             :                                            double *padfPrjParams, long iDatum,
     404             :                                            int nUSGSAngleFormat)
     405             : 
     406             : {
     407          24 :     if (!padfPrjParams)
     408           0 :         return OGRERR_CORRUPT_DATA;
     409             : 
     410          24 :     double (*pfnUnpackAnglesFn)(double) = nullptr;
     411             : 
     412          24 :     if (nUSGSAngleFormat == USGS_ANGLE_DECIMALDEGREES)
     413           6 :         pfnUnpackAnglesFn = OGRSpatialReferenceUSGSUnpackNoOp;
     414          18 :     else if (nUSGSAngleFormat == USGS_ANGLE_RADIANS)
     415           0 :         pfnUnpackAnglesFn = OGRSpatialReferenceUSGSUnpackRadian;
     416             :     else
     417          18 :         pfnUnpackAnglesFn = CPLPackedDMSToDec;
     418             : 
     419             :     /* -------------------------------------------------------------------- */
     420             :     /*      Operate on the basis of the projection code.                    */
     421             :     /* -------------------------------------------------------------------- */
     422          24 :     switch (iProjSys)
     423             :     {
     424           2 :         case GEO:
     425           2 :             break;
     426             : 
     427           9 :         case UTM:
     428             :         {
     429           9 :             int bNorth = TRUE;
     430             : 
     431           9 :             if (!iZone)
     432             :             {
     433           2 :                 if (padfPrjParams[2] != 0.0)
     434             :                 {
     435           2 :                     iZone = static_cast<long>(padfPrjParams[2]);
     436             :                 }
     437           0 :                 else if (padfPrjParams[0] != 0.0 && padfPrjParams[1] != 0.0)
     438             :                 {
     439             :                     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             :                 }
     446             :             }
     447             : 
     448           9 :             if (iZone < -60 || iZone > 60)
     449           0 :                 return OGRERR_CORRUPT_DATA;
     450             : 
     451           9 :             if (iZone < 0)
     452             :             {
     453           0 :                 iZone = -iZone;
     454           0 :                 bNorth = FALSE;
     455             :             }
     456           9 :             SetUTM(static_cast<int>(iZone), bNorth);
     457             :         }
     458           9 :         break;
     459             : 
     460           0 :         case SPCS:
     461             :         {
     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             :                          "Wrong datum for State Plane projection %d. "
     469             :                          "Should be 0 or 8.",
     470             :                          static_cast<int>(iDatum));
     471             : 
     472           0 :             SetStatePlane(static_cast<int>(iZone), bNAD83);
     473             :         }
     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           2 :         case LAMCC:
     485           2 :             SetLCC(pfnUnpackAnglesFn(padfPrjParams[2]),
     486           2 :                    pfnUnpackAnglesFn(padfPrjParams[3]),
     487           2 :                    pfnUnpackAnglesFn(padfPrjParams[5]),
     488           2 :                    pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
     489           2 :                    padfPrjParams[7]);
     490           2 :             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           1 :         case EQUIDC:
     512           1 :             if (padfPrjParams[8] != 0.0)
     513             :             {
     514           1 :                 SetEC(pfnUnpackAnglesFn(padfPrjParams[2]),
     515           1 :                       pfnUnpackAnglesFn(padfPrjParams[3]),
     516           1 :                       pfnUnpackAnglesFn(padfPrjParams[5]),
     517           1 :                       pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
     518           1 :                       padfPrjParams[7]);
     519             :             }
     520             :             else
     521             :             {
     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             :             }
     528           1 :             break;
     529             : 
     530           6 :         case TM:
     531           6 :             SetTM(pfnUnpackAnglesFn(padfPrjParams[5]),
     532           6 :                   pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[2],
     533           6 :                   padfPrjParams[6], padfPrjParams[7]);
     534           6 :             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           2 :         case SNSOID:
     569           2 :             SetSinusoidal(pfnUnpackAnglesFn(padfPrjParams[4]), padfPrjParams[6],
     570           2 :                           padfPrjParams[7]);
     571           2 :             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             :             {
     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             :             }
     598             :             else
     599             :             {
     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             :             }
     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           2 :         default:
     644           2 :             CPLDebug("OSR_USGS", "Unsupported projection: %ld", iProjSys);
     645           2 :             SetLocalCS(
     646           4 :                 CPLString().Printf("GCTP projection number %ld", iProjSys));
     647           2 :             break;
     648             :     }
     649             : 
     650             :     /* -------------------------------------------------------------------- */
     651             :     /*      Try to translate the datum/spheroid.                            */
     652             :     /* -------------------------------------------------------------------- */
     653             : 
     654          24 :     if (!IsLocal())
     655             :     {
     656          22 :         char *pszName = nullptr;
     657          22 :         double dfSemiMajor = 0.0;
     658          22 :         double dfInvFlattening = 0.0;
     659             : 
     660          22 :         if (iDatum < 0)  // Use specified ellipsoid parameters.
     661             :         {
     662           2 :             if (padfPrjParams[0] > 0.0)
     663             :             {
     664           2 :                 if (padfPrjParams[1] > 1.0)
     665             :                 {
     666           0 :                     dfInvFlattening = OSRCalcInvFlattening(padfPrjParams[0],
     667           0 :                                                            padfPrjParams[1]);
     668             :                 }
     669           2 :                 else if (padfPrjParams[1] > 0.0)
     670             :                 {
     671           0 :                     dfInvFlattening =
     672           0 :                         1.0 / (1.0 - sqrt(1.0 - padfPrjParams[1]));
     673             :                 }
     674             :                 else
     675             :                 {
     676           2 :                     dfInvFlattening = 0.0;
     677             :                 }
     678             : 
     679           2 :                 SetGeogCS("Unknown datum based upon the custom spheroid",
     680             :                           "Not specified (based on custom spheroid)",
     681             :                           "Custom spheroid", padfPrjParams[0], dfInvFlattening,
     682             :                           nullptr, 0, nullptr, 0);
     683             :             }
     684           0 :             else if (padfPrjParams[1] > 0.0)  // Clarke 1866.
     685             :             {
     686           0 :                 if (OSRGetEllipsoidInfo(7008, &pszName, &dfSemiMajor,
     687           0 :                                         &dfInvFlattening) == OGRERR_NONE)
     688             :                 {
     689           0 :                     SetGeogCS(
     690           0 :                         CPLString().Printf(
     691             :                             "Unknown datum based upon the %s ellipsoid",
     692           0 :                             pszName),
     693           0 :                         CPLString().Printf(
     694           0 :                             "Not specified (based on %s spheroid)", pszName),
     695             :                         pszName, dfSemiMajor, dfInvFlattening, nullptr, 0.0,
     696             :                         nullptr, 0.0);
     697           0 :                     SetAuthority("SPHEROID", "EPSG", 7008);
     698             :                 }
     699             :             }
     700             :             else  // Sphere, rad 6370997 m
     701             :             {
     702           0 :                 if (OSRGetEllipsoidInfo(7047, &pszName, &dfSemiMajor,
     703           0 :                                         &dfInvFlattening) == OGRERR_NONE)
     704             :                 {
     705           0 :                     SetGeogCS(
     706           0 :                         CPLString().Printf(
     707             :                             "Unknown datum based upon the %s ellipsoid",
     708           0 :                             pszName),
     709           0 :                         CPLString().Printf(
     710           0 :                             "Not specified (based on %s spheroid)", pszName),
     711             :                         pszName, dfSemiMajor, dfInvFlattening, nullptr, 0.0,
     712             :                         nullptr, 0.0);
     713           0 :                     SetAuthority("SPHEROID", "EPSG", 7047);
     714             :                 }
     715             :             }
     716             :         }
     717          20 :         else if (iDatum < NUMBER_OF_USGS_ELLIPSOIDS && aoEllipsUSGS[iDatum])
     718             :         {
     719          20 :             if (aoEllipsUSGS[iDatum] == 7030)  // WGS 84 ellipsoid
     720             :             {
     721             :                 // Assume a WGS 84 datum
     722          16 :                 SetWellKnownGeogCS("WGS84");
     723             :             }
     724           4 :             else if (OSRGetEllipsoidInfo(aoEllipsUSGS[iDatum], &pszName,
     725             :                                          &dfSemiMajor,
     726           4 :                                          &dfInvFlattening) == OGRERR_NONE)
     727             :             {
     728           4 :                 SetGeogCS(
     729           8 :                     CPLString().Printf(
     730           4 :                         "Unknown datum based upon the %s ellipsoid", pszName),
     731           8 :                     CPLString().Printf("Not specified (based on %s spheroid)",
     732           4 :                                        pszName),
     733             :                     pszName, dfSemiMajor, dfInvFlattening, nullptr, 0.0,
     734             :                     nullptr, 0.0);
     735           4 :                 SetAuthority("SPHEROID", "EPSG", aoEllipsUSGS[iDatum]);
     736             :             }
     737             :             else
     738             :             {
     739           0 :                 CPLError(CE_Warning, CPLE_AppDefined,
     740             :                          "Failed to lookup datum code %d. "
     741             :                          "Falling back to use WGS84.",
     742             :                          static_cast<int>(iDatum));
     743           0 :                 SetWellKnownGeogCS("WGS84");
     744             :             }
     745             :         }
     746             :         else
     747             :         {
     748           0 :             CPLError(CE_Warning, CPLE_AppDefined,
     749             :                      "Wrong datum code %d. Supported datums 0--%d only.  "
     750             :                      "Setting WGS84 as a fallback.",
     751             :                      static_cast<int>(iDatum), NUMBER_OF_USGS_ELLIPSOIDS);
     752           0 :             SetWellKnownGeogCS("WGS84");
     753             :         }
     754             : 
     755          22 :         CPLFree(pszName);
     756             :     }
     757             : 
     758             :     /* -------------------------------------------------------------------- */
     759             :     /*      Grid units translation                                          */
     760             :     /* -------------------------------------------------------------------- */
     761          24 :     if (IsLocal() || IsProjected())
     762          22 :         SetLinearUnits(SRS_UL_METER, 1.0);
     763             : 
     764          24 :     if (iDatum >= 0 && iDatum < NUMBER_OF_USGS_ELLIPSOIDS &&
     765          22 :         aoEllipsUSGS[iDatum] == 7030)
     766             :     {
     767          16 :         if (AutoIdentifyEPSG() == OGRERR_NONE)
     768             :         {
     769          10 :             const char *pszAuthName = GetAuthorityName(nullptr);
     770          10 :             const char *pszAuthCode = GetAuthorityCode(nullptr);
     771          10 :             if (pszAuthName && pszAuthCode && EQUAL(pszAuthName, "EPSG"))
     772          10 :                 CPL_IGNORE_RET_VAL(importFromEPSG(atoi(pszAuthCode)));
     773             :         }
     774             :     }
     775             : 
     776          24 :     return OGRERR_NONE;
     777             : }
     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           2 : OGRErr OSRExportToUSGS(OGRSpatialReferenceH hSRS, long *piProjSys, long *piZone,
     789             :                        double **ppadfPrjParams, long *piDatum)
     790             : 
     791             : {
     792           2 :     VALIDATE_POINTER1(hSRS, "OSRExportToUSGS", OGRERR_FAILURE);
     793             : 
     794           2 :     *ppadfPrjParams = nullptr;
     795             : 
     796           2 :     return OGRSpatialReference::FromHandle(hSRS)->exportToUSGS(
     797           2 :         piProjSys, piZone, ppadfPrjParams, piDatum);
     798             : }
     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           2 : OGRErr OGRSpatialReference::exportToUSGS(long *piProjSys, long *piZone,
     826             :                                          double **ppadfPrjParams,
     827             :                                          long *piDatum) const
     828             : 
     829             : {
     830           2 :     const char *pszProjection = GetAttrValue("PROJECTION");
     831             : 
     832             :     /* -------------------------------------------------------------------- */
     833             :     /*      Fill all projection parameters with zero.                       */
     834             :     /* -------------------------------------------------------------------- */
     835           2 :     *ppadfPrjParams = static_cast<double *>(CPLMalloc(15 * sizeof(double)));
     836          32 :     for (int i = 0; i < 15; i++)
     837          30 :         (*ppadfPrjParams)[i] = 0.0;
     838             : 
     839           2 :     *piZone = 0L;
     840             : 
     841             :     /* ==================================================================== */
     842             :     /*      Handle the projection definition.                               */
     843             :     /* ==================================================================== */
     844           2 :     if (IsLocal())
     845           0 :         *piProjSys = GEO;
     846             : 
     847           2 :     else if (pszProjection == nullptr)
     848             :     {
     849             : #ifdef DEBUG
     850           0 :         CPLDebug("OSR_USGS",
     851             :                  "Empty projection definition, considered as Geographic");
     852             : #endif
     853           0 :         *piProjSys = GEO;
     854             :     }
     855             : 
     856           2 :     else if (EQUAL(pszProjection, SRS_PT_ALBERS_CONIC_EQUAL_AREA))
     857             :     {
     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             :     }
     870             : 
     871           2 :     else if (EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP))
     872             :     {
     873           1 :         *piProjSys = LAMCC;
     874           2 :         (*ppadfPrjParams)[2] =
     875           1 :             CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
     876           2 :         (*ppadfPrjParams)[3] =
     877           1 :             CPLDecToPackedDMS(GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
     878           2 :         (*ppadfPrjParams)[4] =
     879           1 :             CPLDecToPackedDMS(GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     880           2 :         (*ppadfPrjParams)[5] =
     881           1 :             CPLDecToPackedDMS(GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
     882           1 :         (*ppadfPrjParams)[6] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     883           1 :         (*ppadfPrjParams)[7] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     884             :     }
     885             : 
     886           1 :     else if (EQUAL(pszProjection, SRS_PT_MERCATOR_1SP))
     887             :     {
     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             :     }
     896             : 
     897           1 :     else if (EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC))
     898             :     {
     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             :     }
     907             : 
     908           1 :     else if (EQUAL(pszProjection, SRS_PT_POLYCONIC))
     909             :     {
     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             :     }
     918             : 
     919           1 :     else if (EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC))
     920             :     {
     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             :     }
     934             : 
     935           1 :     else if (EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR))
     936             :     {
     937             :         int bNorth;
     938             : 
     939           1 :         *piZone = GetUTMZone(&bNorth);
     940             : 
     941           1 :         if (*piZone != 0)
     942             :         {
     943           1 :             *piProjSys = UTM;
     944           1 :             if (!bNorth)
     945           0 :                 *piZone = -*piZone;
     946             :         }
     947             :         else
     948             :         {
     949           0 :             *piProjSys = TM;
     950           0 :             (*ppadfPrjParams)[2] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
     951           0 :             (*ppadfPrjParams)[4] = CPLDecToPackedDMS(
     952             :                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
     953           0 :             (*ppadfPrjParams)[5] = CPLDecToPackedDMS(
     954             :                 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             :         }
     958             :     }
     959             : 
     960           0 :     else if (EQUAL(pszProjection, SRS_PT_STEREOGRAPHIC))
     961             :     {
     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             :     }
     970             : 
     971           0 :     else if (EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA))
     972             :     {
     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             :     }
     981             : 
     982           0 :     else if (EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT))
     983             :     {
     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             :     }
     992             : 
     993           0 :     else if (EQUAL(pszProjection, SRS_PT_GNOMONIC))
     994             :     {
     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             :     }
    1003             : 
    1004           0 :     else if (EQUAL(pszProjection, SRS_PT_ORTHOGRAPHIC))
    1005             :     {
    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             :     }
    1014             : 
    1015           0 :     else if (EQUAL(pszProjection, SRS_PT_SINUSOIDAL))
    1016             :     {
    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             :     }
    1023             : 
    1024           0 :     else if (EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR))
    1025             :     {
    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             :     }
    1034             : 
    1035           0 :     else if (EQUAL(pszProjection, SRS_PT_MILLER_CYLINDRICAL))
    1036             :     {
    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             :     }
    1045             : 
    1046           0 :     else if (EQUAL(pszProjection, SRS_PT_VANDERGRINTEN))
    1047             :     {
    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             :     }
    1054             : 
    1055           0 :     else if (EQUAL(pszProjection, SRS_PT_HOTINE_OBLIQUE_MERCATOR))
    1056             :     {
    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             :     }
    1069             : 
    1070           0 :     else if (EQUAL(pszProjection,
    1071             :                    SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN))
    1072             :     {
    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             :             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             :             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             :     }
    1089             : 
    1090           0 :     else if (EQUAL(pszProjection, SRS_PT_ROBINSON))
    1091             :     {
    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             :     }
    1098             : 
    1099           0 :     else if (EQUAL(pszProjection, SRS_PT_MOLLWEIDE))
    1100             :     {
    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             :     }
    1107             : 
    1108           0 :     else if (EQUAL(pszProjection, SRS_PT_WAGNER_IV))
    1109             :     {
    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             :     }
    1114             : 
    1115           0 :     else if (EQUAL(pszProjection, SRS_PT_WAGNER_VII))
    1116             :     {
    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             :     }
    1121             :     // Projection unsupported by GCTP.
    1122             :     else
    1123             :     {
    1124           0 :         CPLDebug("OSR_USGS",
    1125             :                  "Projection \"%s\" unsupported by USGS GCTP. "
    1126             :                  "Geographic system will be used.",
    1127             :                  pszProjection);
    1128           0 :         *piProjSys = GEO;
    1129             :     }
    1130             : 
    1131             :     /* -------------------------------------------------------------------- */
    1132             :     /*      Translate the datum.                                            */
    1133             :     /* -------------------------------------------------------------------- */
    1134           2 :     const char *pszDatum = GetAttrValue("DATUM");
    1135             : 
    1136           2 :     if (pszDatum)
    1137             :     {
    1138           2 :         if (EQUAL(pszDatum, SRS_DN_NAD27))
    1139             :         {
    1140           1 :             *piDatum = CLARKE1866;
    1141             :         }
    1142           1 :         else if (EQUAL(pszDatum, SRS_DN_NAD83))
    1143             :         {
    1144           0 :             *piDatum = GRS1980;
    1145             :         }
    1146           1 :         else if (EQUAL(pszDatum, SRS_DN_WGS84))
    1147             :         {
    1148           1 :             *piDatum = WGS84;
    1149             :         }
    1150             :         // If not found well known datum, translate ellipsoid.
    1151             :         else
    1152             :         {
    1153           0 :             const double dfSemiMajor = GetSemiMajor();
    1154           0 :             const double dfInvFlattening = GetInvFlattening();
    1155             : 
    1156             : #ifdef DEBUG
    1157           0 :             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             :             {
    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             :                 {
    1174           0 :                     *piDatum = i;
    1175           0 :                     break;
    1176             :                 }
    1177             :             }
    1178             : 
    1179           0 :             if (i == NUMBER_OF_USGS_ELLIPSOIDS)  // Didn't found matches; set
    1180             :             {                                    // custom ellipsoid parameters.
    1181             : #ifdef DEBUG
    1182           0 :                 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             :                 {
    1191           0 :                     (*ppadfPrjParams)[1] = dfSemiMajor;
    1192             :                 }
    1193             :                 else
    1194             :                 {
    1195           0 :                     (*ppadfPrjParams)[1] =
    1196           0 :                         dfSemiMajor * (1.0 - 1.0 / dfInvFlattening);
    1197             :                 }
    1198             :             }
    1199             :         }
    1200             :     }
    1201             :     else
    1202             :     {
    1203           0 :         *piDatum = -1;
    1204             :     }
    1205             : 
    1206           2 :     return OGRERR_NONE;
    1207             : }

Generated by: LCOV version 1.14