LCOV - code coverage report
Current view: top level - ogr - ogr_srs_erm.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 99 121 81.8 %
Date: 2024-11-21 22:18:42 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implement ERMapper projection conversions.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2007, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2008-2011, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "ogr_srs_api.h"
      16             : 
      17             : #include <cmath>
      18             : #include <cstdio>
      19             : #include <cstdlib>
      20             : #include <cstring>
      21             : 
      22             : #include "cpl_conv.h"
      23             : #include "cpl_error.h"
      24             : #include "ogr_core.h"
      25             : #include "ogr_spatialref.h"
      26             : 
      27             : /************************************************************************/
      28             : /*                         OSRImportFromERM()                           */
      29             : /************************************************************************/
      30             : 
      31             : /**
      32             :  * \brief Create OGR WKT from ERMapper projection definitions.
      33             :  *
      34             :  * This function is the same as OGRSpatialReference::importFromERM().
      35             :  */
      36             : 
      37           7 : OGRErr OSRImportFromERM(OGRSpatialReferenceH hSRS, const char *pszProj,
      38             :                         const char *pszDatum, const char *pszUnits)
      39             : 
      40             : {
      41           7 :     VALIDATE_POINTER1(hSRS, "OSRImportFromERM", OGRERR_FAILURE);
      42             : 
      43           7 :     return reinterpret_cast<OGRSpatialReference *>(hSRS)->importFromERM(
      44           7 :         pszProj, pszDatum, pszUnits);
      45             : }
      46             : 
      47             : /************************************************************************/
      48             : /*                           importFromERM()                            */
      49             : /************************************************************************/
      50             : 
      51             : /**
      52             :  * Create OGR WKT from ERMapper projection definitions.
      53             :  *
      54             :  * Generates an OGRSpatialReference definition from an ERMapper datum
      55             :  * and projection name.  Based on the ecw_cs.wkt dictionary file from
      56             :  * gdal/data.
      57             :  *
      58             :  * @param pszProj the projection name, such as "NUTM11" or "GEOGRAPHIC".
      59             :  * @param pszDatum the datum name, such as "NAD83".
      60             :  * @param pszUnits the linear units "FEET" or "METERS".
      61             :  *
      62             :  * @return OGRERR_NONE on success or OGRERR_UNSUPPORTED_SRS if not found.
      63             :  */
      64             : 
      65          82 : OGRErr OGRSpatialReference::importFromERM(const char *pszProj,
      66             :                                           const char *pszDatum,
      67             :                                           const char *pszUnits)
      68             : 
      69             : {
      70          82 :     Clear();
      71             : 
      72             :     /* -------------------------------------------------------------------- */
      73             :     /*      do we have projection and datum?                                */
      74             :     /* -------------------------------------------------------------------- */
      75          82 :     if (EQUAL(pszProj, "RAW"))
      76          45 :         return OGRERR_NONE;
      77             : 
      78             :     /* -------------------------------------------------------------------- */
      79             :     /*      Do we have an EPSG coordinate system?                           */
      80             :     /* -------------------------------------------------------------------- */
      81             : 
      82          37 :     if (STARTS_WITH_CI(pszProj, "EPSG:"))
      83           3 :         return importFromEPSG(atoi(pszProj + 5));
      84             : 
      85          34 :     if (STARTS_WITH_CI(pszDatum, "EPSG:"))
      86           0 :         return importFromEPSG(atoi(pszDatum + 5));
      87             : 
      88          68 :     CPLString osGEOGCS = lookupInDict("ecw_cs.wkt", pszDatum);
      89          34 :     if (osGEOGCS.empty())
      90           2 :         return OGRERR_UNSUPPORTED_SRS;
      91             : 
      92             :     /* -------------------------------------------------------------------- */
      93             :     /*      Set projection if we have it.                                   */
      94             :     /* -------------------------------------------------------------------- */
      95          32 :     if (!EQUAL(pszProj, "GEODETIC"))
      96             :     {
      97          50 :         CPLString osProjWKT = lookupInDict("ecw_cs.wkt", pszProj);
      98          25 :         if (osProjWKT.empty() || osProjWKT.back() != ']')
      99           0 :             return OGRERR_UNSUPPORTED_SRS;
     100             : 
     101          25 :         if (osProjWKT.find("LOCAL_CS[") == 0)
     102             :         {
     103           0 :             return importFromWkt(osProjWKT);
     104             :         }
     105             : 
     106             :         // Remove trailing ]
     107          25 :         osProjWKT.pop_back();
     108             : 
     109             :         // Remove any UNIT
     110          25 :         auto nPos = osProjWKT.find(",UNIT");
     111          25 :         if (nPos != std::string::npos)
     112             :         {
     113          18 :             osProjWKT.resize(nPos);
     114             :         }
     115             : 
     116             :         // Insert GEOGCS
     117          25 :         nPos = osProjWKT.find(",PROJECTION");
     118          25 :         if (nPos == std::string::npos)
     119           0 :             return OGRERR_UNSUPPORTED_SRS;
     120             : 
     121             :         osProjWKT =
     122          25 :             osProjWKT.substr(0, nPos) + ',' + osGEOGCS + osProjWKT.substr(nPos);
     123             : 
     124          25 :         if (EQUAL(pszUnits, "FEET"))
     125           5 :             osProjWKT += ",UNIT[\"Foot_US\",0.3048006096012192]]";
     126             :         else
     127          20 :             osProjWKT += ",UNIT[\"Metre\",1.0]]";
     128             : 
     129          25 :         return importFromWkt(osProjWKT);
     130             :     }
     131             :     else
     132             :     {
     133           7 :         return importFromWkt(osGEOGCS);
     134             :     }
     135             : }
     136             : 
     137             : /************************************************************************/
     138             : /*                          OSRExportToERM()                            */
     139             : /************************************************************************/
     140             : /**
     141             :  * \brief Convert coordinate system to ERMapper format.
     142             :  *
     143             :  * This function is the same as OGRSpatialReference::exportToERM().
     144             :  */
     145           1 : OGRErr OSRExportToERM(OGRSpatialReferenceH hSRS, char *pszProj, char *pszDatum,
     146             :                       char *pszUnits)
     147             : 
     148             : {
     149           1 :     VALIDATE_POINTER1(hSRS, "OSRExportToERM", OGRERR_FAILURE);
     150             : 
     151           1 :     return reinterpret_cast<OGRSpatialReference *>(hSRS)->exportToERM(
     152           1 :         pszProj, pszDatum, pszUnits);
     153             : }
     154             : 
     155             : /************************************************************************/
     156             : /*                            exportToERM()                             */
     157             : /************************************************************************/
     158             : 
     159             : /**
     160             :  * Convert coordinate system to ERMapper format.
     161             :  *
     162             :  * @param pszProj 32 character buffer to receive projection name.
     163             :  * @param pszDatum 32 character buffer to receive datum name.
     164             :  * @param pszUnits 32 character buffer to receive units name.
     165             :  *
     166             :  * @return OGRERR_NONE on success, OGRERR_SRS_UNSUPPORTED if not translation is
     167             :  * found, or OGRERR_FAILURE on other failures.
     168             :  */
     169             : 
     170          52 : OGRErr OGRSpatialReference::exportToERM(char *pszProj, char *pszDatum,
     171             :                                         char *pszUnits)
     172             : 
     173             : {
     174          52 :     const int BUFFER_SIZE = 32;
     175          52 :     strcpy(pszProj, "RAW");
     176          52 :     strcpy(pszDatum, "RAW");
     177          52 :     strcpy(pszUnits, "METERS");
     178             : 
     179          52 :     if (!IsProjected() && !IsGeographic())
     180           0 :         return OGRERR_UNSUPPORTED_SRS;
     181             : 
     182             :     /* -------------------------------------------------------------------- */
     183             :     /*      Try to find the EPSG code.                                      */
     184             :     /* -------------------------------------------------------------------- */
     185          52 :     int nEPSGCode = 0;
     186             : 
     187          52 :     if (IsProjected())
     188             :     {
     189           6 :         const char *pszAuthName = GetAuthorityName("PROJCS");
     190             : 
     191           6 :         if (pszAuthName != nullptr && EQUAL(pszAuthName, "epsg"))
     192             :         {
     193           2 :             nEPSGCode = atoi(GetAuthorityCode("PROJCS"));
     194             :         }
     195             :     }
     196          46 :     else if (IsGeographic())
     197             :     {
     198          46 :         const char *pszAuthName = GetAuthorityName("GEOGCS");
     199             : 
     200          46 :         if (pszAuthName != nullptr && EQUAL(pszAuthName, "epsg"))
     201             :         {
     202           2 :             nEPSGCode = atoi(GetAuthorityCode("GEOGCS"));
     203             :         }
     204             :     }
     205             : 
     206             :     /* -------------------------------------------------------------------- */
     207             :     /*      Is our GEOGCS name already defined in ecw_cs.wkt?               */
     208             :     /* -------------------------------------------------------------------- */
     209          52 :     const char *pszWKTDatum = GetAttrValue("DATUM");
     210             : 
     211         104 :     if (pszWKTDatum != nullptr &&
     212         104 :         !lookupInDict("ecw_cs.wkt", pszWKTDatum).empty())
     213             :     {
     214           0 :         strncpy(pszDatum, pszWKTDatum, BUFFER_SIZE);
     215           0 :         pszDatum[BUFFER_SIZE - 1] = '\0';
     216             :     }
     217             : 
     218             :     /* -------------------------------------------------------------------- */
     219             :     /*      Is this a "well known" geographic coordinate system?            */
     220             :     /* -------------------------------------------------------------------- */
     221          52 :     if (EQUAL(pszDatum, "RAW"))
     222             :     {
     223          52 :         int nEPSGGCSCode = GetEPSGGeogCS();
     224             : 
     225          52 :         if (nEPSGGCSCode == 4326)
     226           4 :             strcpy(pszDatum, "WGS84");
     227             : 
     228          48 :         else if (nEPSGGCSCode == 4322)
     229           0 :             strcpy(pszDatum, "WGS72DOD");
     230             : 
     231          48 :         else if (nEPSGGCSCode == 4267)
     232           2 :             strcpy(pszDatum, "NAD27");
     233             : 
     234          46 :         else if (nEPSGGCSCode == 4269)
     235           0 :             strcpy(pszDatum, "NAD83");
     236             : 
     237          46 :         else if (nEPSGGCSCode == 4277)
     238           0 :             strcpy(pszDatum, "OSGB36");
     239             : 
     240          46 :         else if (nEPSGGCSCode == 4278)
     241           0 :             strcpy(pszDatum, "OSGB78");
     242             : 
     243          46 :         else if (nEPSGGCSCode == 4201)
     244           0 :             strcpy(pszDatum, "ADINDAN");
     245             : 
     246          46 :         else if (nEPSGGCSCode == 4202)
     247           0 :             strcpy(pszDatum, "AGD66");
     248             : 
     249          46 :         else if (nEPSGGCSCode == 4203)
     250           0 :             strcpy(pszDatum, "AGD84");
     251             : 
     252          46 :         else if (nEPSGGCSCode == 4209)
     253           0 :             strcpy(pszDatum, "ARC1950");
     254             : 
     255          46 :         else if (nEPSGGCSCode == 4210)
     256           0 :             strcpy(pszDatum, "ARC1960");
     257             : 
     258          46 :         else if (nEPSGGCSCode == 4275)
     259           0 :             strcpy(pszDatum, "NTF");
     260             : 
     261          46 :         else if (nEPSGGCSCode == 4283)
     262           0 :             strcpy(pszDatum, "GDA94");
     263             : 
     264          46 :         else if (nEPSGGCSCode == 4284)
     265           0 :             strcpy(pszDatum, "PULKOVO");
     266             : 
     267          46 :         else if (nEPSGGCSCode == 7844)
     268           1 :             strcpy(pszDatum, "GDA2020");
     269             :     }
     270             : 
     271             :     /* -------------------------------------------------------------------- */
     272             :     /*      Are we working with a geographic (geodetic) coordinate system?  */
     273             :     /* -------------------------------------------------------------------- */
     274             : 
     275          52 :     if (IsGeographic())
     276             :     {
     277          46 :         if (EQUAL(pszDatum, "RAW"))
     278          44 :             return OGRERR_UNSUPPORTED_SRS;
     279             :         else
     280             :         {
     281           2 :             strcpy(pszProj, "GEODETIC");
     282           2 :             return OGRERR_NONE;
     283             :         }
     284             :     }
     285             : 
     286             :     /* -------------------------------------------------------------------- */
     287             :     /*      Is this a UTM projection?                                       */
     288             :     /* -------------------------------------------------------------------- */
     289           6 :     int bNorth = FALSE;
     290           6 :     int nZone = 0;
     291             : 
     292           6 :     nZone = GetUTMZone(&bNorth);
     293           6 :     if (nZone > 0)
     294             :     {
     295           4 :         if ((EQUAL(pszDatum, "GDA94") || EQUAL(pszDatum, "GDA2020")) &&
     296           1 :             !bNorth && nZone >= 48 && nZone <= 58)
     297             :         {
     298           1 :             snprintf(pszProj, BUFFER_SIZE, "MGA%02d", nZone);
     299             :         }
     300             :         else
     301             :         {
     302           3 :             if (bNorth)
     303           3 :                 snprintf(pszProj, BUFFER_SIZE, "NUTM%02d", nZone);
     304             :             else
     305           0 :                 snprintf(pszProj, BUFFER_SIZE, "SUTM%02d", nZone);
     306             :         }
     307             :     }
     308             : 
     309             :     /* -------------------------------------------------------------------- */
     310             :     /*      Is our PROJCS name already defined in ecw_cs.wkt?               */
     311             :     /* -------------------------------------------------------------------- */
     312             :     else
     313             :     {
     314           2 :         const char *pszPROJCS = GetAttrValue("PROJCS");
     315             : 
     316           4 :         if (pszPROJCS != nullptr &&
     317           4 :             lookupInDict("ecw_cs.wkt", pszPROJCS).find("PROJCS") == 0)
     318             :         {
     319           1 :             strncpy(pszProj, pszPROJCS, BUFFER_SIZE);
     320           1 :             pszProj[BUFFER_SIZE - 1] = '\0';
     321             :         }
     322             :     }
     323             : 
     324             :     /* -------------------------------------------------------------------- */
     325             :     /*      If we have not translated it yet, but we have an EPSG code      */
     326             :     /*      then use EPSG:n notation.                                       */
     327             :     /* -------------------------------------------------------------------- */
     328           6 :     if ((EQUAL(pszDatum, "RAW") || EQUAL(pszProj, "RAW")) && nEPSGCode != 0)
     329             :     {
     330           0 :         snprintf(pszProj, BUFFER_SIZE, "EPSG:%d", nEPSGCode);
     331           0 :         snprintf(pszDatum, BUFFER_SIZE, "EPSG:%d", nEPSGCode);
     332             :     }
     333             : 
     334             :     /* -------------------------------------------------------------------- */
     335             :     /*      Handle the units.                                               */
     336             :     /* -------------------------------------------------------------------- */
     337           6 :     const double dfUnits = GetLinearUnits();
     338             : 
     339           6 :     if (fabs(dfUnits - 0.3048) < 0.0001)
     340           1 :         strcpy(pszUnits, "FEET");
     341             :     else
     342           5 :         strcpy(pszUnits, "METERS");
     343             : 
     344           6 :     if (EQUAL(pszProj, "RAW"))
     345           1 :         return OGRERR_UNSUPPORTED_SRS;
     346             : 
     347           5 :     return OGRERR_NONE;
     348             : }

Generated by: LCOV version 1.14