LCOV - code coverage report
Current view: top level - ogr - ogr_srs_panorama.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 177 414 42.8 %
Date: 2024-11-21 22:18:42 Functions: 6 9 66.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  OGRSpatialReference translation to/from "Panorama" GIS
       5             :  *           georeferencing information (also know as GIS "Integration").
       6             :  * Author:   Andrey Kiselev, dron@ak4719.spb.edu
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2005, Andrey Kiselev <dron@ak4719.spb.edu>
      10             :  * Copyright (c) 2008-2012, Even Rouault <even dot rouault at spatialys.com>
      11             :  * Copyright (c) 2020-2022, Dmitry Baryshnikov <polimax@mail.ru>
      12             :  *
      13             :  * SPDX-License-Identifier: MIT
      14             :  ****************************************************************************/
      15             : 
      16             : #include "ogr_spatialref.h"
      17             : #include "cpl_conv.h"
      18             : #include "cpl_csv.h"
      19             : #include "ogr_p.h"
      20             : 
      21             : #include <cmath>
      22             : 
      23             : constexpr double TO_DEGREES = 180.0 / M_PI;
      24             : constexpr double TO_RADIANS = M_PI / 180.0;
      25             : constexpr int NONE_VAL = -1L;
      26             : 
      27             : // This function computes zone number from the central meridian parameter.
      28          13 : static int GetZoneNumberGK(double dfCenterLong)
      29             : {
      30          13 :     return static_cast<int>((dfCenterLong + 363.0) / 6.0 + 0.5) % 60;
      31             : }
      32             : 
      33          67 : static int GetZoneNumberUTM(double dfCenterLong)
      34             : {
      35          67 :     return static_cast<int>((dfCenterLong + 186.0) / 6.0);
      36             : }
      37             : 
      38         236 : static bool IsNone(long val)
      39             : {
      40         236 :     return val == -1L || val == 0L || val == 255L;
      41             : }
      42             : 
      43             : /************************************************************************/
      44             : /*  "Panorama" projection codes.                                        */
      45             : /************************************************************************/
      46             : 
      47             : constexpr long PAN_PROJ_TM = 1L;       // Gauss-Kruger (Transverse Mercator)
      48             : constexpr long PAN_PROJ_LCC = 2L;      // Lambert Conformal Conic 2SP
      49             : constexpr long PAN_PROJ_STEREO = 5L;   // Stereographic
      50             : constexpr long PAN_PROJ_AE = 6L;       // Azimuthal Equidistant (Postel)
      51             : constexpr long PAN_PROJ_MERCAT = 8L;   // Mercator
      52             : constexpr long PAN_PROJ_POLYC = 10L;   // Polyconic
      53             : constexpr long PAN_PROJ_PS = 13L;      // Polar Stereographic
      54             : constexpr long PAN_PROJ_GNOMON = 15L;  // Gnomonic
      55             : constexpr long PAN_PROJ_UTM = 17L;     // Universal Transverse Mercator (UTM)
      56             : constexpr long PAN_PROJ_WAG1 = 18L;    // Wagner I (Kavraisky VI)
      57             : constexpr long PAN_PROJ_MOLL = 19L;    // Mollweide
      58             : constexpr long PAN_PROJ_EC = 20L;      // Equidistant Conic
      59             : constexpr long PAN_PROJ_LAEA = 24L;    // Lambert Azimuthal Equal Area
      60             : constexpr long PAN_PROJ_EQC = 27L;     // Equirectangular
      61             : constexpr long PAN_PROJ_CEA = 28L;     // Cylindrical Equal Area (Lambert)
      62             : constexpr long PAN_PROJ_IMWP = 29L;  // International Map of the World Polyconic
      63             : constexpr long PAN_PROJ_SPHERE = 33L;  // Sphere
      64             : constexpr long PAN_PROJ_MILLER = 34L;  // Miller
      65             : constexpr long PAN_PROJ_PSEUDO_MERCATOR =
      66             :     35L;  // Popular Visualisation Pseudo Mercator
      67             : /************************************************************************/
      68             : /*  "Panorama" datum codes.                                             */
      69             : /************************************************************************/
      70             : 
      71             : constexpr long PAN_DATUM_PULKOVO42 = 1L;    // Pulkovo 1942
      72             : constexpr long PAN_DATUM_UTM = 2L;          // Universal Transverse Mercator
      73             : constexpr long PAN_DATUM_RECTANGULAR = 6L;  // WGS84
      74             : // constexpr long PAN_DATUM_WGS84 = 8L;        // WGS84
      75             : constexpr long PAN_DATUM_PULKOVO95 = 9L;  // Pulokovo 1995
      76             : constexpr long PAN_DATUM_GSK2011 = 10L;   // GSK 2011
      77             : 
      78             : /************************************************************************/
      79             : /*  "Panorama" ellipsoid codes.                                         */
      80             : /************************************************************************/
      81             : 
      82             : constexpr long PAN_ELLIPSOID_KRASSOVSKY = 1L;  // Krassovsky, 1940
      83             : // constexpr long PAN_ELLIPSOID_WGS72       = 2L;  // WGS, 1972
      84             : // constexpr long PAN_ELLIPSOID_INT1924     = 3L;  // International, 1924
      85             : // (Hayford, 1909) constexpr long PAN_ELLIPSOID_CLARCKE1880 = 4L;  // Clarke,
      86             : // 1880 constexpr long PAN_ELLIPSOID_CLARCKE1866 = 5L;  // Clarke, 1866
      87             : // (NAD1927) constexpr long PAN_ELLIPSOID_EVEREST1830 = 6L;  // Everest, 1830
      88             : // constexpr long PAN_ELLIPSOID_BESSEL1841  = 7L;  // Bessel, 1841
      89             : // constexpr long PAN_ELLIPSOID_AIRY1830    = 8L;  // Airy, 1830
      90             : constexpr long PAN_ELLIPSOID_WGS84 = 9L;          // WGS, 1984 (GPS)
      91             : constexpr long PAN_ELLIPSOID_WGS84_SPHERE = 45L;  // WGS, 1984 (Sphere)
      92             : constexpr long PAN_ELLIPSOID_GSK2011 = 46L;       // GSK 2011
      93             : constexpr long PAN_ELLIPSOID_PZ90 = 47L;          // PZ-90
      94             : 
      95             : /************************************************************************/
      96             : /*  Correspondence between "Panorama" datum and EPSG GeogCS codes.             */
      97             : /************************************************************************/
      98             : 
      99             : constexpr int aoDatums[] = {
     100             :     0,     // 0.  Undefined (also may be 255 or -1)
     101             :     4284,  // 1.  Pulkovo, 1942
     102             :     4326,  // 2.  WGS, 1984,
     103             :     4277,  // 3.  OSGB 1936 (British National Grid)
     104             :     0,     // 4.  Local spatial reference
     105             :     0,     // 5.  SK 63
     106             :     0,     // 6.  Rectangular conditional spatial reference
     107             :     0,     // 7.  Geodesic coordinates in radians
     108             :     0,     // 8.  Geodesic coordinates in degrees
     109             :     4200,  // 9.  Pulkovo, 1995
     110             :     7683   // 10. GSK 2011
     111             : };
     112             : 
     113             : constexpr int NUMBER_OF_DATUMS = static_cast<int>(CPL_ARRAYSIZE(aoDatums));
     114             : 
     115             : /************************************************************************/
     116             : /*  Correspondence between "Panorama" and EPSG ellipsoid codes.         */
     117             : /************************************************************************/
     118             : 
     119             : constexpr int aoPanoramaEllips[] = {
     120             :     0,     // 0. Undefined
     121             :     7024,  // 1. Krassovsky, 1940
     122             :     7043,  // 2. WGS, 1972
     123             :     7022,  // 3. International, 1924 (Hayford, 1909)
     124             :     7034,  // 4. Clarke, 1880
     125             :     7008,  // 5. Clarke, 1866 (NAD1927)
     126             :     7015,  // 6. Everest, 1830
     127             :     7004,  // 7. Bessel, 1841
     128             :     7001,  // 8. Airy, 1830
     129             :     7030,  // 9. WGS, 1984 (GPS)
     130             :     7054,  // 10. PZ-90.02 // http://epsg.io/7054-ellipsoid
     131             :     7019,  // 11. GRS, 1980 (NAD1983)
     132             :     0,     // 12. IERS 1996 (6378136.49 298.25645)
     133             :     7022,  // 13. International, 1924 (Hayford, 1909) XXX?
     134             :     7036,  // 14. South American, 1969
     135             :     7021,  // 15. Indonesian, 1974
     136             :     7020,  // 16. Helmert 1906
     137             :     0,     // 17. FIXME: Fisher 1960 - https://epsg.io/37002
     138             :     0,     // 18. FIXME: Fisher 1968 - https://epsg.io/37003
     139             :     0,     // 19. FIXME: Haff 1960 - (6378270.0 297.0)
     140             :     7042,  // 20. Everest, 1830
     141             :     7003,  // 21. Australian National, 1965
     142             :     1024,  // 22. CGCS2000 http://epsg.io/1024-ellipsoid
     143             :     7002,  // 23. Airy Modified 1849 http://epsg.io/7002-ellipsoid
     144             :     7005,  // 24. Bessel Modified
     145             :     7046,  // 25. Bessel Namibia
     146             :     7046,  // 26. Bessel Namibia (GLM)
     147             :     7013,  // 27. Clarke 1880 (Arc)
     148             :     7014,  // 28. Clarke 1880 (SGA 1922)
     149             :     7042,  // 29. Everest (1830 Definition)
     150             :     7018,  // 30. Everest 1830 Modified
     151             :     7056,  // 31. Everest 1830 (RSO 1969)
     152             :     7045,  // 32. Everest 1830 (1975 Definition)
     153             :     7025,  // 33. NWL 9D
     154             :     7027,  // 34. Plessis 1817
     155             :     7028,  // 35. Struve 1860
     156             :     7029,  // 36. War Office
     157             :     7031,  // 37. GEM 10C
     158             :     7032,  // 38. OSU86F
     159             :     7033,  // 39. OSU91A
     160             :     7036,  // 40. GRS 1967
     161             :     7041,  // 41. Average Terrestrial System 1977
     162             :     7049,  // 42. IAG 1975
     163             :     7050,  // 43. GRS 1967 Modified
     164             :     7051,  // 44. Danish 1876
     165             :     7048,  // 45. GRS 1980 Authalic Sphere
     166             :     1025,  // 46. GSK 2011
     167             :     7054   // 47. PZ-90
     168             : };
     169             : 
     170             : constexpr int NUMBER_OF_PANORAM_ELLIPSOIDS =
     171             :     static_cast<int>(CPL_ARRAYSIZE(aoPanoramaEllips));
     172             : 
     173             : /************************************************************************/
     174             : /*  Correspondence between "Panorama" and EPSG vertical CS.             */
     175             : /************************************************************************/
     176             : 
     177             : constexpr int aoVCS[] = {
     178             :     0,     //0, 255, -1 - Undefined
     179             :     8357,  //1 Baltic 1957 height
     180             :     5711,  //2 AHD height
     181             :     5195,  //3 Trieste height
     182             :     5710,  //4 Ostend height - zero normal
     183             :     5710,  //5 Ostend height - null point de shosse
     184             :     0,     //6 Channel height (GB)
     185             :     5732,  //7 Belfast height
     186             :     5731,  //8 Malin Head height
     187             :     0,     //9 Dublib bay height
     188             :     5716,  //10 Piraeus height
     189             :     5733,  //11 DNN height
     190             :     8089,  //12 ISH2004 height
     191             :     5782,  //13 Alicante height
     192             :     0,     //14 Canary islands
     193             :     5214,  //15 Genoa height
     194             :     5709,  //16 NAP height
     195             :     5776,  //17 NN54 height
     196             :     0,     //18 North Norway
     197             :     5780,  //19 Cascais height
     198             :     5717,  //20 N60 height
     199             :     5613,  //21 RH2000 height
     200             :     0,     //22 France, Marseilles height
     201             :     5775,  //23 Antalya height
     202             :     5702,  //24 NGVD29 height (ftUS)
     203             :     5705,  //25 Baltic 1977 height
     204             :     0,     //26 Pacific Ocean (Ohotsk sea level)
     205             :     5714   //27 MSL height
     206             : };
     207             : 
     208             : constexpr int NUMBER_OF_VERTICALCS = static_cast<int>(CPL_ARRAYSIZE(aoVCS));
     209             : 
     210             : /************************************************************************/
     211             : /*                        OSRImportFromPanorama()                       */
     212             : /************************************************************************/
     213             : 
     214             : /** Import coordinate system from "Panorama" GIS projection definition.
     215             :  *
     216             :  * See OGRSpatialReference::importFromPanorama()
     217             :  */
     218             : 
     219           0 : OGRErr OSRImportFromPanorama(OGRSpatialReferenceH hSRS, long iProjSys,
     220             :                              long iDatum, long iEllips, double *padfPrjParams)
     221             : 
     222             : {
     223           0 :     VALIDATE_POINTER1(hSRS, "OSRImportFromPanorama", OGRERR_FAILURE);
     224             : 
     225           0 :     return reinterpret_cast<OGRSpatialReference *>(hSRS)->importFromPanorama(
     226           0 :         iProjSys, iDatum, iEllips, padfPrjParams);
     227             : }
     228             : 
     229             : /************************************************************************/
     230             : /*                          importFromPanorama()                        */
     231             : /************************************************************************/
     232             : 
     233             : /**
     234             :  * Import coordinate system from "Panorama" GIS projection definition.
     235             :  *
     236             :  * This method will import projection definition in style, used by
     237             :  * "Panorama" GIS.
     238             :  *
     239             :  * This function is the equivalent of the C function OSRImportFromPanorama().
     240             :  *
     241             :  * @param iProjSys Input projection system code, used in GIS "Panorama".
     242             :  *
     243             :  * Supported Projections are:
     244             :  * <ul>
     245             :  * <li>1:  Gauss-Kruger (Transverse Mercator)</li>
     246             :  * <li>2:  Lambert Conformal Conic 2SP</li>
     247             :  * <li>5:  Stereographic</li>
     248             :  * <li>6:  Azimuthal Equidistant (Postel)</li>
     249             :  * <li>8:  Mercator</li>
     250             :  * <li>10: Polyconic</li>
     251             :  * <li>13: Polar Stereographic</li>
     252             :  * <li>15: Gnomonic</li>
     253             :  * <li>17: Universal Transverse Mercator (UTM)</li>
     254             :  * <li>18: Wagner I (Kavraisky VI)</li>
     255             :  * <li>19: Mollweide</li>
     256             :  * <li>20: Equidistant Conic</li>
     257             :  * <li>24: Lambert Azimuthal Equal Area</li>
     258             :  * <li>27: Equirectangular</li>
     259             :  * <li>28: Cylindrical Equal Area (Lambert)</li>
     260             :  * <li>29: International Map of the World Polyconic</li>
     261             :  * </ul>
     262             :  *
     263             :  * @param iDatum Input coordinate system.
     264             :  *
     265             :  * Supported Datums are:
     266             :  * <ul>
     267             :  * <li>1:  Pulkovo, 1942</li>
     268             :  * <li>2:  WGS, 1984</li>
     269             :  * <li>3:  OSGB 1936 (British National Grid)</li>
     270             :  * <li>9:  Pulkovo, 1995</li>
     271             :  * <li>10: GSK 2011</li>
     272             :  * </ul>
     273             :  *
     274             :  * @param iEllips Input spheroid.
     275             :  *
     276             :  * Supported Spheroids are:
     277             :  * <ul>
     278             :  * <li>1:  Krassovsky, 1940</li>
     279             :  * <li>2:  WGS, 1972</li>
     280             :  * <li>3:  International, 1924 (Hayford, 1909)</li>
     281             :  * <li>4:  Clarke, 1880</li>
     282             :  * <li>5:  Clarke, 1866 (NAD1927)</li>
     283             :  * <li>6:  Everest, 1830</li>
     284             :  * <li>7:  Bessel, 1841</li>
     285             :  * <li>8:  Airy, 1830</li>
     286             :  * <li>9:  WGS, 1984 (GPS)</li>
     287             :  * <li>10: PZ-90.02</li>
     288             :  * <li>11: GRS, 1980 (NAD1983)</li>
     289             :  * <li>12: IERS 1996 (6378136.49 298.25645)</li>
     290             :  * <li>13: International, 1924 (Hayford, 1909)</li>
     291             :  * <li>14: South American, 1969</li>
     292             :  * <li>15: Indonesian, 1974</li>
     293             :  * <li>16: Helmert 1906</li>
     294             :  * <li>17: Fisher 1960</li>
     295             :  * <li>18: Fisher 1968</li>
     296             :  * <li>19. Haff 1960 - (6378270.0 297.0)</li>
     297             :  * <li>20: Everest, 1830</li>
     298             :  * <li>21: Australian National, 1965</li>
     299             :  * <li>22: CGCS2000</li>
     300             :  * <li>23: Airy Modified 1849</li>
     301             :  * <li>24: Bessel Modified</li>
     302             :  * <li>25: Bessel Namibia</li>
     303             :  * <li>26: Bessel Namibia (GLM)</li>
     304             :  * <li>27: Clarke 1880 (Arc)</li>
     305             :  * <li>28: Clarke 1880 (SGA 1922)</li>
     306             :  * <li>29: Everest (1830 Definition)</li>
     307             :  * <li>30: Everest 1830 Modified</li>
     308             :  * <li>31: Everest 1830 (RSO 1969)</li>
     309             :  * <li>32: Everest 1830 (1975 Definition)</li>
     310             :  * <li>33: NWL 9D</li>
     311             :  * <li>34: Plessis 1817</li>
     312             :  * <li>35: Struve 1860</li>
     313             :  * <li>36: War Office</li>
     314             :  * <li>37: GEM 10C</li>
     315             :  * <li>38: OSU86F</li>
     316             :  * <li>39: OSU91A</li>
     317             :  * <li>40: GRS 1967</li>
     318             :  * <li>41: Average Terrestrial System 1977</li>
     319             :  * <li>42: IAG 1975</li>
     320             :  * <li>43: GRS 1967 Modified</li>
     321             :  * <li>44: Danish 1876</li>
     322             :  * <li>45: GRS 1980 Authalic Sphere</li>
     323             :  * <li>46: GSK 2011</li>
     324             :  * <li>47: PZ-90</li>
     325             :  * </ul>
     326             :  *
     327             :  * @param padfPrjParams Array of 8 coordinate system parameters:
     328             :  *
     329             :  * <ul>
     330             :  * <li>[0]  Latitude of the first standard parallel (radians)</li>
     331             :  * <li>[1]  Latitude of the second standard parallel (radians)</li>
     332             :  * <li>[2]  Latitude of center of projection (radians)</li>
     333             :  * <li>[3]  Longitude of center of projection (radians)</li>
     334             :  * <li>[4]  Scaling factor</li>
     335             :  * <li>[5]  False Easting</li>
     336             :  * <li>[6]  False Northing</li>
     337             :  * <li>[7]  Zone number</li>
     338             :  * </ul>
     339             :  *
     340             :  * @param bNorth If northern hemisphere true, else false. Defaults to true.
     341             :  *
     342             :  * Particular projection uses different parameters, unused ones may be set to
     343             :  * zero. If NULL supplied instead of array pointer default values will be used
     344             :  * (i.e., zeroes).
     345             :  *
     346             :  * @return OGRERR_NONE on success or an error code in case of failure.
     347             :  */
     348             : 
     349         101 : OGRErr OGRSpatialReference::importFromPanorama(long iProjSys, long iDatum,
     350             :                                                long iEllips,
     351             :                                                double *padfPrjParams,
     352             :                                                bool bNorth)
     353             : 
     354             : {
     355         101 :     Clear();
     356             : 
     357             :     /* -------------------------------------------------------------------- */
     358             :     /*      Use safe defaults if projection parameters are not supplied.    */
     359             :     /* -------------------------------------------------------------------- */
     360         101 :     double adfPrjParams[8] = {0.0};
     361         101 :     if (padfPrjParams != nullptr)
     362             :     {
     363          99 :         std::copy(padfPrjParams, padfPrjParams + 8, adfPrjParams);
     364             :     }
     365             : 
     366         101 :     CPLDebug("OSR_Panorama",
     367             :              "importFromPanorama: proj %ld, datum %ld, ellips %ld, params [%f, "
     368             :              "%f, %f, %f, %f, %f, %f, %f], north %d",
     369             :              iProjSys, iDatum, iEllips, adfPrjParams[0], adfPrjParams[1],
     370             :              adfPrjParams[2], adfPrjParams[3], adfPrjParams[4], adfPrjParams[5],
     371             :              adfPrjParams[6], adfPrjParams[7], bNorth);
     372             : 
     373             :     // Check some zonal projections
     374         230 :     if ((IsNone(iEllips) || iEllips == PAN_ELLIPSOID_KRASSOVSKY) &&
     375         230 :         (IsNone(iDatum) || iDatum == PAN_DATUM_PULKOVO42) &&
     376             :         iProjSys == PAN_PROJ_TM)  // Pulkovo 1942 / Gauss-Kruger
     377             :     {
     378          12 :         int nZone = adfPrjParams[7] == 0.0
     379          12 :                         ? GetZoneNumberGK(TO_DEGREES * adfPrjParams[3])
     380           2 :                         : static_cast<int>(adfPrjParams[7]);
     381             : 
     382          12 :         if (nZone > 1 && nZone < 33)
     383             :         {
     384          12 :             return importFromEPSG(28400 + nZone);
     385             :         }
     386             :     }
     387         178 :     if ((IsNone(iEllips) || iEllips == PAN_ELLIPSOID_KRASSOVSKY) &&
     388         178 :         iDatum == PAN_DATUM_PULKOVO95 &&
     389             :         iProjSys == PAN_PROJ_TM)  // Pulkovo 1995 / Gauss-Kruger
     390             :     {
     391           0 :         int nZone = adfPrjParams[7] == 0.0
     392           0 :                         ? GetZoneNumberGK(TO_DEGREES * adfPrjParams[3])
     393           0 :                         : static_cast<int>(adfPrjParams[7]);
     394             : 
     395           0 :         if (nZone > 3 && nZone < 33)
     396             :         {
     397           0 :             return importFromEPSG(20000 + nZone);
     398             :         }
     399             :     }
     400          89 :     if (iEllips == PAN_ELLIPSOID_WGS84 && iDatum == PAN_DATUM_UTM &&
     401             :         iProjSys == PAN_PROJ_UTM)  // WGS84 / UTM
     402             :     {
     403           4 :         const int nZone = adfPrjParams[7] == 0.0
     404           4 :                               ? GetZoneNumberUTM(TO_DEGREES * adfPrjParams[3])
     405           0 :                               : static_cast<int>(adfPrjParams[7]);
     406             :         int nEPSG;
     407           4 :         if (bNorth)
     408             :         {
     409           2 :             nEPSG = 32600 + nZone;
     410             :         }
     411             :         else
     412             :         {
     413           2 :             nEPSG = 32700 + nZone;
     414             :         }
     415           4 :         return importFromEPSG(nEPSG);
     416             :     }
     417             : 
     418             :     /* -------------------------------------------------------------------- */
     419             :     /*      Operate on the basis of the projection code.                    */
     420             :     /* -------------------------------------------------------------------- */
     421          85 :     switch (iProjSys)
     422             :     {
     423           0 :         case -1L:
     424             :         case 255L:
     425           0 :             break;
     426             : 
     427          13 :         case PAN_PROJ_SPHERE:
     428          13 :             if (iEllips == PAN_ELLIPSOID_WGS84)
     429             :             {
     430          13 :                 return SetWellKnownGeogCS("EPSG:4326");
     431             :             }
     432           0 :             break;
     433             : 
     434          63 :         case PAN_PROJ_UTM:
     435             :         {
     436             :             const int nZone =
     437          63 :                 adfPrjParams[7] == 0.0
     438          63 :                     ? GetZoneNumberUTM(TO_DEGREES * adfPrjParams[3])
     439           0 :                     : static_cast<int>(adfPrjParams[7]);
     440             : 
     441          63 :             SetUTM(nZone, bNorth);
     442             :         }
     443          63 :         break;
     444             : 
     445           0 :         case PAN_PROJ_WAG1:
     446           0 :             SetWagner(1, 0.0, adfPrjParams[5], adfPrjParams[6]);
     447           0 :             break;
     448             : 
     449           0 :         case PAN_PROJ_MERCAT:
     450           0 :             SetMercator(TO_DEGREES * adfPrjParams[0],
     451           0 :                         TO_DEGREES * adfPrjParams[3], adfPrjParams[4],
     452             :                         adfPrjParams[5], adfPrjParams[6]);
     453           0 :             break;
     454             : 
     455           0 :         case PAN_PROJ_PS:
     456           0 :             SetPS(TO_DEGREES * adfPrjParams[2], TO_DEGREES * adfPrjParams[3],
     457             :                   adfPrjParams[4], adfPrjParams[5], adfPrjParams[6]);
     458           0 :             break;
     459             : 
     460           0 :         case PAN_PROJ_POLYC:
     461           0 :             SetPolyconic(TO_DEGREES * adfPrjParams[2],
     462           0 :                          TO_DEGREES * adfPrjParams[3], adfPrjParams[5],
     463             :                          adfPrjParams[6]);
     464           0 :             break;
     465             : 
     466           0 :         case PAN_PROJ_EC:
     467           0 :             SetEC(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[1],
     468           0 :                   TO_DEGREES * adfPrjParams[2], TO_DEGREES * adfPrjParams[3],
     469             :                   adfPrjParams[5], adfPrjParams[6]);
     470           0 :             break;
     471             : 
     472           0 :         case PAN_PROJ_LCC:
     473           0 :             SetLCC(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[1],
     474           0 :                    TO_DEGREES * adfPrjParams[2], TO_DEGREES * adfPrjParams[3],
     475             :                    adfPrjParams[5], adfPrjParams[6]);
     476           0 :             break;
     477             : 
     478           6 :         case PAN_PROJ_TM:
     479             :         {
     480             :             // XXX: we need zone number to compute false easting
     481             :             // parameter, because usually it is not contained in the
     482             :             // "Panorama" projection definition.
     483             :             // FIXME: what to do with negative values?
     484           6 :             int nZone = 0;
     485           6 :             double dfCenterLong = 0.0;
     486             : 
     487           6 :             if (adfPrjParams[7] == 0.0)
     488             :             {
     489           0 :                 dfCenterLong = TO_DEGREES * adfPrjParams[3];
     490           0 :                 nZone = GetZoneNumberGK(dfCenterLong);
     491             :             }
     492             :             else
     493             :             {
     494           6 :                 nZone = static_cast<int>(adfPrjParams[7]);
     495           6 :                 dfCenterLong = 6.0 * nZone - 3.0;
     496             :             }
     497             : 
     498           6 :             adfPrjParams[5] = nZone * 1000000.0 + 500000.0;
     499           6 :             adfPrjParams[4] = 1.0;
     500           6 :             SetTM(TO_DEGREES * adfPrjParams[2], dfCenterLong, adfPrjParams[4],
     501             :                   adfPrjParams[5], adfPrjParams[6]);
     502             :         }
     503           6 :         break;
     504             : 
     505           0 :         case PAN_PROJ_STEREO:
     506           0 :             SetStereographic(TO_DEGREES * adfPrjParams[2],
     507           0 :                              TO_DEGREES * adfPrjParams[3], adfPrjParams[4],
     508             :                              adfPrjParams[5], adfPrjParams[6]);
     509           0 :             break;
     510             : 
     511           0 :         case PAN_PROJ_AE:
     512           0 :             SetAE(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[3],
     513             :                   adfPrjParams[5], adfPrjParams[6]);
     514           0 :             break;
     515             : 
     516           0 :         case PAN_PROJ_GNOMON:
     517           0 :             SetGnomonic(TO_DEGREES * adfPrjParams[2],
     518           0 :                         TO_DEGREES * adfPrjParams[3], adfPrjParams[5],
     519             :                         adfPrjParams[6]);
     520           0 :             break;
     521             : 
     522           0 :         case PAN_PROJ_MOLL:
     523           0 :             SetMollweide(TO_DEGREES * adfPrjParams[3], adfPrjParams[5],
     524             :                          adfPrjParams[6]);
     525           0 :             break;
     526             : 
     527           0 :         case PAN_PROJ_LAEA:
     528           0 :             SetLAEA(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[3],
     529             :                     adfPrjParams[5], adfPrjParams[6]);
     530           0 :             break;
     531             : 
     532           0 :         case PAN_PROJ_EQC:
     533           0 :             SetEquirectangular(TO_DEGREES * adfPrjParams[0],
     534           0 :                                TO_DEGREES * adfPrjParams[3], adfPrjParams[5],
     535             :                                adfPrjParams[6]);
     536           0 :             break;
     537             : 
     538           0 :         case PAN_PROJ_CEA:
     539           0 :             SetCEA(TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[3],
     540             :                    adfPrjParams[5], adfPrjParams[6]);
     541           0 :             break;
     542             : 
     543           0 :         case PAN_PROJ_IMWP:
     544           0 :             SetIWMPolyconic(
     545           0 :                 TO_DEGREES * adfPrjParams[0], TO_DEGREES * adfPrjParams[1],
     546           0 :                 TO_DEGREES * adfPrjParams[3], adfPrjParams[5], adfPrjParams[6]);
     547           0 :             break;
     548             : 
     549           0 :         case PAN_PROJ_MILLER:
     550           0 :             SetMC(TO_DEGREES * adfPrjParams[5], TO_DEGREES * adfPrjParams[4],
     551             :                   adfPrjParams[6], adfPrjParams[7]);
     552           0 :             break;
     553             : 
     554           2 :         case PAN_PROJ_PSEUDO_MERCATOR:
     555             :         {
     556           2 :             int nEPSG = 0;
     557           2 :             if (iEllips == PAN_ELLIPSOID_WGS84_SPHERE)
     558             :             {
     559           1 :                 nEPSG = 3857;
     560             :             }
     561           1 :             else if (iEllips == PAN_ELLIPSOID_WGS84)
     562             :             {
     563           1 :                 nEPSG = 3395;
     564             :             }
     565           2 :             if (nEPSG > 0)
     566             :             {
     567           2 :                 return importFromEPSG(nEPSG);
     568             :             }
     569             :         }
     570           0 :         break;
     571             : 
     572           1 :         default:
     573           1 :             CPLDebug("OSR_Panorama", "Unsupported projection: %ld", iProjSys);
     574           2 :             SetLocalCS(CPLString().Printf("\"Panorama\" projection number %ld",
     575           1 :                                           iProjSys));
     576           1 :             break;
     577             :     }
     578             : 
     579             :     /* -------------------------------------------------------------------- */
     580             :     /*      Try to translate the datum/spheroid.                            */
     581             :     /* -------------------------------------------------------------------- */
     582             : 
     583          70 :     if (!IsLocal())
     584             :     {
     585          69 :         if (iEllips == PAN_ELLIPSOID_GSK2011 || iDatum == PAN_DATUM_GSK2011)
     586             :         {
     587           0 :             OGRSpatialReference oGCS;
     588           0 :             oGCS.importFromEPSG(7683);
     589           0 :             CopyGeogCSFrom(&oGCS);
     590             :         }
     591          69 :         else if (iEllips == PAN_ELLIPSOID_PZ90)
     592             :         {
     593           0 :             OGRSpatialReference oGCS;
     594           0 :             oGCS.importFromEPSG(7679);
     595           0 :             CopyGeogCSFrom(&oGCS);
     596             :         }
     597          69 :         else if (iDatum == PAN_DATUM_PULKOVO95)
     598             :         {
     599           0 :             OGRSpatialReference oGCS;
     600           0 :             oGCS.importFromEPSG(4200);
     601           0 :             CopyGeogCSFrom(&oGCS);
     602             :         }
     603          69 :         else if (iDatum > 0 && iDatum < NUMBER_OF_DATUMS && aoDatums[iDatum])
     604             :         {
     605          44 :             OGRSpatialReference oGCS;
     606          22 :             oGCS.importFromEPSG(aoDatums[iDatum]);
     607          44 :             CopyGeogCSFrom(&oGCS);
     608             :         }
     609          47 :         else if (iEllips > 0 && iEllips < NUMBER_OF_PANORAM_ELLIPSOIDS &&
     610          30 :                  aoPanoramaEllips[iEllips])
     611             :         {
     612          30 :             char *pszName = nullptr;
     613          30 :             double dfSemiMajor = 0.0;
     614          30 :             double dfInvFlattening = 0.0;
     615             : 
     616          30 :             if (OSRGetEllipsoidInfo(aoPanoramaEllips[iEllips], &pszName,
     617             :                                     &dfSemiMajor,
     618          30 :                                     &dfInvFlattening) == OGRERR_NONE)
     619             :             {
     620          30 :                 SetGeogCS(
     621          60 :                     CPLString().Printf(
     622          30 :                         "Unknown datum based upon the %s ellipsoid", pszName),
     623          60 :                     CPLString().Printf("Not specified (based on %s spheroid)",
     624          30 :                                        pszName),
     625             :                     pszName, dfSemiMajor, dfInvFlattening, nullptr, 0.0,
     626             :                     nullptr, 0.0);
     627          30 :                 SetAuthority("SPHEROID", "EPSG", aoPanoramaEllips[iEllips]);
     628             :             }
     629             :             else
     630             :             {
     631           0 :                 CPLError(CE_Warning, CPLE_AppDefined,
     632             :                          "Failed to lookup ellipsoid code %ld. "
     633             :                          "Falling back to use Pulkovo 42.",
     634             :                          iEllips);
     635           0 :                 SetWellKnownGeogCS("EPSG:4284");
     636             :             }
     637             : 
     638          30 :             CPLFree(pszName);
     639             :         }
     640             :         else
     641             :         {
     642          17 :             CPLError(CE_Warning, CPLE_AppDefined,
     643             :                      "Wrong datum code %ld. Supported datums are 1 - %d "
     644             :                      "only.  Falling back to use Pulkovo 42.",
     645             :                      iDatum, NUMBER_OF_DATUMS - 1);
     646          17 :             SetWellKnownGeogCS("EPSG:4284");
     647             :         }
     648             :     }
     649             : 
     650             :     /* -------------------------------------------------------------------- */
     651             :     /*      Grid units translation                                          */
     652             :     /* -------------------------------------------------------------------- */
     653          70 :     if (IsLocal() || IsProjected())
     654             :     {
     655          70 :         SetLinearUnits(SRS_UL_METER, 1.0);
     656             :     }
     657             : 
     658          70 :     return OGRERR_NONE;
     659             : }
     660             : 
     661             : /**
     662             :  * Import vertical coordinate system from "Panorama" GIS projection definition.
     663             :  *
     664             :  * @param iVCS Input vertical coordinate system ID.
     665             :  *
     666             :  * Supported VCS are:
     667             :  * <ul>
     668             :  * <li>1:  Baltic 1977 height (EPSG:5705)</li>
     669             :  * <li>2:  AHD height (EPSG:5711)</li>
     670             :  * <li>4:  Ostend height (EPSG:5710)</li>
     671             :  * <li>5:  Ostend height (EPSG:5710)</li>
     672             :  * <li>7:  Belfast height (EPSG: 5732)</li>
     673             :  * <li>8:  Malin Head height (EPSG: 5731)</li>
     674             :  * <li>10: Piraeus height (EPSG:5716)</li>
     675             :  * <li>11: DNN height (EPSG:5733)</li>
     676             :  * <li>12: ISH2004 height (EPSG:8089)</li>
     677             :  * <li>13: Alicante height (EPSG:5782)</li>
     678             :  * <li>15: Genoa height (EPSG:5214)</li>
     679             :  * <li>16: NAP height (EPSG:5709)</li>
     680             :  * <li>17: NN54 height (EPSG:5776)</li>
     681             :  * <li>19: Cascais height (EPSG:5780)</li>
     682             :  * <li>20: N60 height (EPSG:5717)</li>
     683             :  * <li>21: RH2000 height (EPSG:5613)</li>
     684             :  * <li>23: Antalya height (EPSG:5775)</li>
     685             :  * <li>24: NGVD29 height (ftUS) (EPSG:5702)</li>
     686             :  * <li>25: Baltic 1977 height (EPSG:5705)</li>
     687             :  * <li>27: MSL height (EPSG:5714)</li>
     688             :  * </ul>
     689             :  */
     690           0 : OGRErr OGRSpatialReference::importVertCSFromPanorama(int iVCS)
     691             : {
     692           0 :     if (iVCS < 0 || iVCS >= NUMBER_OF_VERTICALCS)
     693             :     {
     694           0 :         return OGRERR_CORRUPT_DATA;
     695             :     }
     696             : 
     697           0 :     const int nEPSG = aoVCS[iVCS];
     698             : 
     699           0 :     if (nEPSG == 0)
     700             :     {
     701           0 :         CPLError(CE_Warning, CPLE_NotSupported,
     702             :                  "Vertical coordinate system (Panorama index %d) not supported",
     703             :                  iVCS);
     704           0 :         return OGRERR_UNSUPPORTED_SRS;
     705             :     }
     706             : 
     707           0 :     OGRSpatialReference sr;
     708           0 :     sr.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     709           0 :     OGRErr eImportFromEPSGErr = sr.importFromEPSG(nEPSG);
     710           0 :     if (eImportFromEPSGErr != OGRERR_NONE)
     711             :     {
     712           0 :         CPLError(CE_Warning, CPLE_None,
     713             :                  "Vertical coordinate system (Panorama index %d, EPSG %d) "
     714             :                  "import from EPSG error",
     715             :                  iVCS, nEPSG);
     716           0 :         return OGRERR_UNSUPPORTED_SRS;
     717             :     }
     718             : 
     719           0 :     if (sr.IsVertical() != 1)
     720             :     {
     721           0 :         CPLError(CE_Warning, CPLE_None,
     722             :                  "Coordinate system (Panorama index %d, EPSG %d) "
     723             :                  "is not Vertical",
     724             :                  iVCS, nEPSG);
     725           0 :         return OGRERR_UNSUPPORTED_SRS;
     726             :     }
     727             : 
     728             :     OGRErr eSetVertCSErr =
     729           0 :         SetVertCS(sr.GetAttrValue("VERT_CS"), sr.GetAttrValue("VERT_DATUM"));
     730           0 :     if (eSetVertCSErr != OGRERR_NONE)
     731             :     {
     732           0 :         CPLError(CE_Warning, CPLE_None,
     733             :                  "Vertical coordinate system (Panorama index %d, EPSG %d) "
     734             :                  "set error",
     735             :                  iVCS, nEPSG);
     736           0 :         return eSetVertCSErr;
     737             :     }
     738           0 :     return OGRERR_NONE;
     739             : }
     740             : 
     741             : /**
     742             :  * Export vertical coordinate system to "Panorama" GIS projection definition.
     743             :  */
     744          53 : OGRErr OGRSpatialReference::exportVertCSToPanorama(int *piVert) const
     745             : {
     746          53 :     auto pszVertCSName = GetAttrValue("COMPD_CS|VERT_CS");
     747          53 :     if (pszVertCSName != nullptr)
     748             :     {
     749           1 :         auto pszValue = GetAuthorityCode("COMPD_CS|VERT_CS");
     750           1 :         if (pszValue != nullptr)
     751             :         {
     752           0 :             auto nEPSG = atoi(pszValue);
     753           0 :             if (nEPSG > 0)
     754             :             {
     755           0 :                 for (int i = 0; i < NUMBER_OF_VERTICALCS; i++)
     756             :                 {
     757           0 :                     if (aoVCS[i] == nEPSG)
     758             :                     {
     759           0 :                         *piVert = i;
     760           0 :                         return OGRERR_NONE;
     761             :                     }
     762             :                 }
     763             :             }
     764             :         }
     765             :         else  // Try to get Panorama ID from pszVertCSName
     766             :         {
     767          26 :             for (int i = 0; i < NUMBER_OF_VERTICALCS; i++)
     768             :             {
     769          26 :                 if (aoVCS[i] > 0)
     770             :                 {
     771          20 :                     OGRSpatialReference oTmpSRS;
     772          20 :                     oTmpSRS.importFromEPSG(aoVCS[i]);
     773          20 :                     if (EQUAL(pszVertCSName, oTmpSRS.GetAttrValue("VERT_CS")))
     774             :                     {
     775             : 
     776           1 :                         *piVert = i;
     777           1 :                         return OGRERR_NONE;
     778             :                     }
     779             :                 }
     780             :             }
     781             :         }
     782             :     }
     783          52 :     CPLDebug("OSR_Panorama",
     784             :              "Vertical coordinate system not supported by Panorama");
     785          52 :     return OGRERR_UNSUPPORTED_SRS;
     786             : }
     787             : 
     788             : /************************************************************************/
     789             : /*                      OSRExportToPanorama()                           */
     790             : /************************************************************************/
     791             : 
     792             : /** Export coordinate system in "Panorama" GIS projection definition.
     793             :  *
     794             :  * See OGRSpatialReference::exportToPanorama()
     795             :  */
     796             : 
     797           0 : OGRErr OSRExportToPanorama(OGRSpatialReferenceH hSRS, long *piProjSys,
     798             :                            long *piDatum, long *piEllips, long *piZone,
     799             :                            double *padfPrjParams)
     800             : 
     801             : {
     802           0 :     VALIDATE_POINTER1(hSRS, "OSRExportToPanorama", OGRERR_FAILURE);
     803           0 :     VALIDATE_POINTER1(piProjSys, "OSRExportToPanorama", OGRERR_FAILURE);
     804           0 :     VALIDATE_POINTER1(piDatum, "OSRExportToPanorama", OGRERR_FAILURE);
     805           0 :     VALIDATE_POINTER1(piEllips, "OSRExportToPanorama", OGRERR_FAILURE);
     806           0 :     VALIDATE_POINTER1(padfPrjParams, "OSRExportToPanorama", OGRERR_FAILURE);
     807             : 
     808           0 :     return reinterpret_cast<OGRSpatialReference *>(hSRS)->exportToPanorama(
     809           0 :         piProjSys, piDatum, piEllips, piZone, padfPrjParams);
     810             : }
     811             : 
     812             : /************************************************************************/
     813             : /*                           exportToPanorama()                         */
     814             : /************************************************************************/
     815             : 
     816             : /**
     817             :  * Export coordinate system in "Panorama" GIS projection definition.
     818             :  *
     819             :  * This method is the equivalent of the C function OSRExportToPanorama().
     820             :  *
     821             :  * @param piProjSys Pointer to variable, where the projection system code will
     822             :  * be returned.
     823             :  *
     824             :  * @param piDatum Pointer to variable, where the coordinate system code will
     825             :  * be returned.
     826             :  *
     827             :  * @param piEllips Pointer to variable, where the spheroid code will be
     828             :  * returned.
     829             :  *
     830             :  * @param piZone Pointer to variable, where the zone for UTM projection
     831             :  * system will be returned.
     832             :  *
     833             :  * @param padfPrjParams an existing 7 double buffer into which the
     834             :  * projection parameters will be placed. See importFromPanorama()
     835             :  * for the list of parameters.
     836             :  *
     837             :  * @return OGRERR_NONE on success or an error code on failure.
     838             :  */
     839             : 
     840          56 : OGRErr OGRSpatialReference::exportToPanorama(long *piProjSys, long *piDatum,
     841             :                                              long *piEllips, long *piZone,
     842             :                                              double *padfPrjParams) const
     843             : 
     844             : {
     845          56 :     CPLAssert(padfPrjParams);
     846             : 
     847          56 :     const char *pszProjection = GetAttrValue("PROJECTION");
     848          56 :     int nEPSG = 0;
     849          56 :     auto pszEPSG = GetAuthorityCode("PROJCS");
     850          56 :     if (pszEPSG == nullptr)
     851             :     {
     852          50 :         pszEPSG = GetAuthorityCode("GEOGCS");
     853             :     }
     854          56 :     if (pszEPSG != nullptr)
     855             :     {
     856          32 :         nEPSG = atoi(pszEPSG);
     857             :     }
     858             : 
     859             :     /* -------------------------------------------------------------------- */
     860             :     /*      Fill all projection parameters with zero.                       */
     861             :     /* -------------------------------------------------------------------- */
     862          56 :     *piDatum = 0L;
     863          56 :     *piEllips = 0L;
     864          56 :     *piZone = 0L;
     865         448 :     for (int i = 0; i < 7; i++)
     866         392 :         padfPrjParams[i] = 0.0;
     867             : 
     868             :     /* ==================================================================== */
     869             :     /*      Handle the projection definition.                               */
     870             :     /* ==================================================================== */
     871          56 :     if (IsLocal())
     872             :     {
     873           0 :         *piProjSys = NONE_VAL;
     874             :     }
     875          56 :     else if (IsGeographic() || IsGeocentric())
     876             :     {
     877          22 :         *piProjSys = PAN_PROJ_SPHERE;
     878             :     }
     879             :     // Check well known EPSG codes
     880          34 :     else if (nEPSG == 3857)
     881             :     {
     882           0 :         *piProjSys = PAN_PROJ_PSEUDO_MERCATOR;
     883           0 :         *piDatum = PAN_DATUM_RECTANGULAR;
     884           0 :         *piEllips = PAN_ELLIPSOID_WGS84_SPHERE;
     885           0 :         return OGRERR_NONE;
     886             :     }
     887          34 :     else if (pszProjection == nullptr)
     888             :     {
     889             : #ifdef DEBUG
     890           0 :         CPLDebug("OSR_Panorama",
     891             :                  "Empty projection definition, considered as Geographic");
     892             : #endif
     893           0 :         *piProjSys = NONE_VAL;
     894             :     }
     895          34 :     else if (EQUAL(pszProjection, SRS_PT_MERCATOR_1SP))
     896             :     {
     897           0 :         *piProjSys = PAN_PROJ_MERCAT;
     898           0 :         padfPrjParams[3] =
     899           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     900           0 :         padfPrjParams[0] =
     901           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     902           0 :         padfPrjParams[4] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
     903           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     904           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     905             :     }
     906          34 :     else if (EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC))
     907             :     {
     908           0 :         *piProjSys = PAN_PROJ_PS;
     909           0 :         padfPrjParams[3] =
     910           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     911           0 :         padfPrjParams[2] =
     912           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     913           0 :         padfPrjParams[4] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
     914           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     915           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     916             :     }
     917          34 :     else if (EQUAL(pszProjection, SRS_PT_POLYCONIC))
     918             :     {
     919           0 :         *piProjSys = PAN_PROJ_POLYC;
     920           0 :         padfPrjParams[3] =
     921           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     922           0 :         padfPrjParams[2] =
     923           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     924           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     925           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     926             :     }
     927          34 :     else if (EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC))
     928             :     {
     929           0 :         *piProjSys = PAN_PROJ_EC;
     930           0 :         padfPrjParams[0] =
     931           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);
     932           0 :         padfPrjParams[1] =
     933           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0);
     934           0 :         padfPrjParams[3] =
     935           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     936           0 :         padfPrjParams[2] =
     937           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     938           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     939           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     940             :     }
     941          34 :     else if (EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP))
     942             :     {
     943           0 :         *piProjSys = PAN_PROJ_LCC;
     944           0 :         padfPrjParams[0] =
     945           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);
     946           0 :         padfPrjParams[1] =
     947           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0);
     948           0 :         padfPrjParams[3] =
     949           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     950           0 :         padfPrjParams[2] =
     951           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     952           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     953           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     954             :     }
     955          34 :     else if (EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR))
     956             :     {
     957          33 :         int bNorth = FALSE;
     958             : 
     959          33 :         *piZone = GetUTMZone(&bNorth);
     960             : 
     961          33 :         auto dfCenterLong = GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     962          33 :         padfPrjParams[3] = TO_RADIANS * dfCenterLong;
     963          33 :         padfPrjParams[2] =
     964          33 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     965          33 :         padfPrjParams[4] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
     966          33 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     967          33 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     968             : 
     969          33 :         if (*piZone != 0)
     970             :         {
     971          30 :             *piProjSys = PAN_PROJ_UTM;
     972          30 :             if (!bNorth)
     973           0 :                 *piZone = -*piZone;
     974             :         }
     975             :         else
     976             :         {
     977           3 :             *piProjSys = PAN_PROJ_TM;
     978           3 :             auto nZone = GetZoneNumberGK(dfCenterLong);
     979           3 :             *piZone = nZone;
     980             :         }
     981             :     }
     982           1 :     else if (EQUAL(pszProjection, SRS_PT_WAGNER_I))
     983             :     {
     984           0 :         *piProjSys = PAN_PROJ_WAG1;
     985           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     986           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     987             :     }
     988           1 :     else if (EQUAL(pszProjection, SRS_PT_STEREOGRAPHIC))
     989             :     {
     990           0 :         *piProjSys = PAN_PROJ_STEREO;
     991           0 :         padfPrjParams[3] =
     992           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     993           0 :         padfPrjParams[2] =
     994           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
     995           0 :         padfPrjParams[4] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
     996           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
     997           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
     998             :     }
     999           1 :     else if (EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT))
    1000             :     {
    1001           0 :         *piProjSys = PAN_PROJ_AE;
    1002           0 :         padfPrjParams[3] =
    1003           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0);
    1004           0 :         padfPrjParams[0] =
    1005           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0);
    1006           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1007           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1008             :     }
    1009           1 :     else if (EQUAL(pszProjection, SRS_PT_GNOMONIC))
    1010             :     {
    1011           0 :         *piProjSys = PAN_PROJ_GNOMON;
    1012           0 :         padfPrjParams[3] =
    1013           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1014           0 :         padfPrjParams[2] =
    1015           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
    1016           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1017           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1018             :     }
    1019           1 :     else if (EQUAL(pszProjection, SRS_PT_MOLLWEIDE))
    1020             :     {
    1021           0 :         *piProjSys = PAN_PROJ_MOLL;
    1022           0 :         padfPrjParams[3] =
    1023           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1024           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1025           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1026             :     }
    1027           1 :     else if (EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA))
    1028             :     {
    1029           0 :         *piProjSys = PAN_PROJ_LAEA;
    1030           0 :         padfPrjParams[3] =
    1031           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1032           0 :         padfPrjParams[0] =
    1033           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
    1034           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1035           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1036             :     }
    1037           1 :     else if (EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR))
    1038             :     {
    1039           0 :         *piProjSys = PAN_PROJ_EQC;
    1040           0 :         padfPrjParams[3] =
    1041           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1042           0 :         padfPrjParams[0] =
    1043           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
    1044           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1045           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1046             :     }
    1047           1 :     else if (EQUAL(pszProjection, SRS_PT_CYLINDRICAL_EQUAL_AREA))
    1048             :     {
    1049           0 :         *piProjSys = PAN_PROJ_CEA;
    1050           0 :         padfPrjParams[3] =
    1051           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1052           0 :         padfPrjParams[2] =
    1053           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);
    1054           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1055           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1056             :     }
    1057           1 :     else if (EQUAL(pszProjection, SRS_PT_IMW_POLYCONIC))
    1058             :     {
    1059           0 :         *piProjSys = PAN_PROJ_IMWP;
    1060           0 :         padfPrjParams[3] =
    1061           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
    1062           0 :         padfPrjParams[0] =
    1063           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT, 0.0);
    1064           0 :         padfPrjParams[1] =
    1065           0 :             TO_RADIANS * GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT, 0.0);
    1066           0 :         padfPrjParams[5] = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
    1067           0 :         padfPrjParams[6] = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
    1068             :     }
    1069             :     // Projection unsupported by "Panorama" GIS
    1070             :     else
    1071             :     {
    1072           1 :         CPLDebug("OSR_Panorama",
    1073             :                  "Projection \"%s\" unsupported by \"Panorama\" GIS. "
    1074             :                  "Geographic system will be used.",
    1075             :                  pszProjection);
    1076           1 :         *piProjSys = NONE_VAL;
    1077             :     }
    1078             : 
    1079             :     /* -------------------------------------------------------------------- */
    1080             :     /*      Translate the datum.                                            */
    1081             :     /* -------------------------------------------------------------------- */
    1082          56 :     const char *pszDatum = GetAttrValue("DATUM");
    1083             : 
    1084          56 :     if (pszDatum == nullptr)
    1085             :     {
    1086           0 :         *piDatum = NONE_VAL;
    1087           0 :         *piEllips = NONE_VAL;
    1088             :     }
    1089          56 :     else if (EQUAL(pszDatum, "Pulkovo_1942"))
    1090             :     {
    1091          22 :         *piDatum = PAN_DATUM_PULKOVO42;
    1092          22 :         *piEllips = PAN_ELLIPSOID_KRASSOVSKY;
    1093             :     }
    1094          34 :     else if (EQUAL(pszDatum, "Pulkovo_1995"))
    1095             :     {
    1096           0 :         *piDatum = PAN_DATUM_PULKOVO95;
    1097           0 :         *piEllips = PAN_ELLIPSOID_KRASSOVSKY;
    1098             :     }
    1099          34 :     else if (EQUAL(pszDatum, SRS_DN_WGS84))
    1100             :     {
    1101          24 :         *piDatum = PAN_DATUM_RECTANGULAR;  // PAN_DATUM_WGS84;
    1102          24 :         *piEllips = PAN_ELLIPSOID_WGS84;
    1103             :     }
    1104             : 
    1105             :     // If not found well known datum, translate ellipsoid.
    1106             :     else
    1107             :     {
    1108          10 :         const double dfSemiMajor = GetSemiMajor();
    1109          10 :         const double dfInvFlattening = GetInvFlattening();
    1110             : 
    1111             : #ifdef DEBUG
    1112          10 :         CPLDebug("OSR_Panorama",
    1113             :                  "Datum \"%s\" unsupported by \"Panorama\" GIS. "
    1114             :                  "Trying to translate an ellipsoid definition.",
    1115             :                  pszDatum);
    1116             : #endif
    1117             : 
    1118          10 :         int i = 0;  // Used after for.
    1119          60 :         for (; i < NUMBER_OF_PANORAM_ELLIPSOIDS; i++)
    1120             :         {
    1121          60 :             if (aoPanoramaEllips[i])
    1122             :             {
    1123          50 :                 double dfSM = 0.0;
    1124          50 :                 double dfIF = 1.0;
    1125             : 
    1126          50 :                 if (OSRGetEllipsoidInfo(aoPanoramaEllips[i], nullptr, &dfSM,
    1127          50 :                                         &dfIF) == OGRERR_NONE &&
    1128          60 :                     std::abs(dfSemiMajor - dfSM) < 1e-10 * dfSemiMajor &&
    1129          10 :                     std::abs(dfInvFlattening - dfIF) < 1e-10 * dfInvFlattening)
    1130             :                 {
    1131          10 :                     *piEllips = i;
    1132          10 :                     break;
    1133             :                 }
    1134             :             }
    1135             :         }
    1136             : 
    1137          10 :         if (i == NUMBER_OF_PANORAM_ELLIPSOIDS)  // Didn't found matches.
    1138             :         {
    1139             : #ifdef DEBUG
    1140           0 :             CPLDebug("OSR_Panorama",
    1141             :                      R"(Ellipsoid "%s" unsupported by "Panorama" GIS.)",
    1142             :                      pszDatum);
    1143             : #endif
    1144           0 :             *piDatum = NONE_VAL;
    1145           0 :             *piEllips = NONE_VAL;
    1146             :         }
    1147             :     }
    1148             : 
    1149          56 :     return OGRERR_NONE;
    1150             : }

Generated by: LCOV version 1.14