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-05-03 15:49:35 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "cpl_port.h"
      31             : #include "ogr_srs_api.h"
      32             : 
      33             : #include <cmath>
      34             : #include <cstdio>
      35             : #include <cstdlib>
      36             : #include <cstring>
      37             : 
      38             : #include "cpl_conv.h"
      39             : #include "cpl_error.h"
      40             : #include "ogr_core.h"
      41             : #include "ogr_spatialref.h"
      42             : 
      43             : /************************************************************************/
      44             : /*                         OSRImportFromERM()                           */
      45             : /************************************************************************/
      46             : 
      47             : /**
      48             :  * \brief Create OGR WKT from ERMapper projection definitions.
      49             :  *
      50             :  * This function is the same as OGRSpatialReference::importFromERM().
      51             :  */
      52             : 
      53           7 : OGRErr OSRImportFromERM(OGRSpatialReferenceH hSRS, const char *pszProj,
      54             :                         const char *pszDatum, const char *pszUnits)
      55             : 
      56             : {
      57           7 :     VALIDATE_POINTER1(hSRS, "OSRImportFromERM", OGRERR_FAILURE);
      58             : 
      59           7 :     return reinterpret_cast<OGRSpatialReference *>(hSRS)->importFromERM(
      60           7 :         pszProj, pszDatum, pszUnits);
      61             : }
      62             : 
      63             : /************************************************************************/
      64             : /*                           importFromERM()                            */
      65             : /************************************************************************/
      66             : 
      67             : /**
      68             :  * Create OGR WKT from ERMapper projection definitions.
      69             :  *
      70             :  * Generates an OGRSpatialReference definition from an ERMapper datum
      71             :  * and projection name.  Based on the ecw_cs.wkt dictionary file from
      72             :  * gdal/data.
      73             :  *
      74             :  * @param pszProj the projection name, such as "NUTM11" or "GEOGRAPHIC".
      75             :  * @param pszDatum the datum name, such as "NAD83".
      76             :  * @param pszUnits the linear units "FEET" or "METERS".
      77             :  *
      78             :  * @return OGRERR_NONE on success or OGRERR_UNSUPPORTED_SRS if not found.
      79             :  */
      80             : 
      81          82 : OGRErr OGRSpatialReference::importFromERM(const char *pszProj,
      82             :                                           const char *pszDatum,
      83             :                                           const char *pszUnits)
      84             : 
      85             : {
      86          82 :     Clear();
      87             : 
      88             :     /* -------------------------------------------------------------------- */
      89             :     /*      do we have projection and datum?                                */
      90             :     /* -------------------------------------------------------------------- */
      91          82 :     if (EQUAL(pszProj, "RAW"))
      92          45 :         return OGRERR_NONE;
      93             : 
      94             :     /* -------------------------------------------------------------------- */
      95             :     /*      Do we have an EPSG coordinate system?                           */
      96             :     /* -------------------------------------------------------------------- */
      97             : 
      98          37 :     if (STARTS_WITH_CI(pszProj, "EPSG:"))
      99           3 :         return importFromEPSG(atoi(pszProj + 5));
     100             : 
     101          34 :     if (STARTS_WITH_CI(pszDatum, "EPSG:"))
     102           0 :         return importFromEPSG(atoi(pszDatum + 5));
     103             : 
     104          68 :     CPLString osGEOGCS = lookupInDict("ecw_cs.wkt", pszDatum);
     105          34 :     if (osGEOGCS.empty())
     106           2 :         return OGRERR_UNSUPPORTED_SRS;
     107             : 
     108             :     /* -------------------------------------------------------------------- */
     109             :     /*      Set projection if we have it.                                   */
     110             :     /* -------------------------------------------------------------------- */
     111          32 :     if (!EQUAL(pszProj, "GEODETIC"))
     112             :     {
     113          50 :         CPLString osProjWKT = lookupInDict("ecw_cs.wkt", pszProj);
     114          25 :         if (osProjWKT.empty() || osProjWKT.back() != ']')
     115           0 :             return OGRERR_UNSUPPORTED_SRS;
     116             : 
     117          25 :         if (osProjWKT.find("LOCAL_CS[") == 0)
     118             :         {
     119           0 :             return importFromWkt(osProjWKT);
     120             :         }
     121             : 
     122             :         // Remove trailing ]
     123          25 :         osProjWKT.resize(osProjWKT.size() - 1);
     124             : 
     125             :         // Remove any UNIT
     126          25 :         auto nPos = osProjWKT.find(",UNIT");
     127          25 :         if (nPos != std::string::npos)
     128             :         {
     129          18 :             osProjWKT.resize(nPos);
     130             :         }
     131             : 
     132             :         // Insert GEOGCS
     133          25 :         nPos = osProjWKT.find(",PROJECTION");
     134          25 :         if (nPos == std::string::npos)
     135           0 :             return OGRERR_UNSUPPORTED_SRS;
     136             : 
     137             :         osProjWKT =
     138          25 :             osProjWKT.substr(0, nPos) + ',' + osGEOGCS + osProjWKT.substr(nPos);
     139             : 
     140          25 :         if (EQUAL(pszUnits, "FEET"))
     141           5 :             osProjWKT += ",UNIT[\"Foot_US\",0.3048006096012192]]";
     142             :         else
     143          20 :             osProjWKT += ",UNIT[\"Metre\",1.0]]";
     144             : 
     145          25 :         return importFromWkt(osProjWKT);
     146             :     }
     147             :     else
     148             :     {
     149           7 :         return importFromWkt(osGEOGCS);
     150             :     }
     151             : }
     152             : 
     153             : /************************************************************************/
     154             : /*                          OSRExportToERM()                            */
     155             : /************************************************************************/
     156             : /**
     157             :  * \brief Convert coordinate system to ERMapper format.
     158             :  *
     159             :  * This function is the same as OGRSpatialReference::exportToERM().
     160             :  */
     161           1 : OGRErr OSRExportToERM(OGRSpatialReferenceH hSRS, char *pszProj, char *pszDatum,
     162             :                       char *pszUnits)
     163             : 
     164             : {
     165           1 :     VALIDATE_POINTER1(hSRS, "OSRExportToERM", OGRERR_FAILURE);
     166             : 
     167           1 :     return reinterpret_cast<OGRSpatialReference *>(hSRS)->exportToERM(
     168           1 :         pszProj, pszDatum, pszUnits);
     169             : }
     170             : 
     171             : /************************************************************************/
     172             : /*                            exportToERM()                             */
     173             : /************************************************************************/
     174             : 
     175             : /**
     176             :  * Convert coordinate system to ERMapper format.
     177             :  *
     178             :  * @param pszProj 32 character buffer to receive projection name.
     179             :  * @param pszDatum 32 character buffer to receive datum name.
     180             :  * @param pszUnits 32 character buffer to receive units name.
     181             :  *
     182             :  * @return OGRERR_NONE on success, OGRERR_SRS_UNSUPPORTED if not translation is
     183             :  * found, or OGRERR_FAILURE on other failures.
     184             :  */
     185             : 
     186          52 : OGRErr OGRSpatialReference::exportToERM(char *pszProj, char *pszDatum,
     187             :                                         char *pszUnits)
     188             : 
     189             : {
     190          52 :     const int BUFFER_SIZE = 32;
     191          52 :     strcpy(pszProj, "RAW");
     192          52 :     strcpy(pszDatum, "RAW");
     193          52 :     strcpy(pszUnits, "METERS");
     194             : 
     195          52 :     if (!IsProjected() && !IsGeographic())
     196           0 :         return OGRERR_UNSUPPORTED_SRS;
     197             : 
     198             :     /* -------------------------------------------------------------------- */
     199             :     /*      Try to find the EPSG code.                                      */
     200             :     /* -------------------------------------------------------------------- */
     201          52 :     int nEPSGCode = 0;
     202             : 
     203          52 :     if (IsProjected())
     204             :     {
     205           6 :         const char *pszAuthName = GetAuthorityName("PROJCS");
     206             : 
     207           6 :         if (pszAuthName != nullptr && EQUAL(pszAuthName, "epsg"))
     208             :         {
     209           2 :             nEPSGCode = atoi(GetAuthorityCode("PROJCS"));
     210             :         }
     211             :     }
     212          46 :     else if (IsGeographic())
     213             :     {
     214          46 :         const char *pszAuthName = GetAuthorityName("GEOGCS");
     215             : 
     216          46 :         if (pszAuthName != nullptr && EQUAL(pszAuthName, "epsg"))
     217             :         {
     218           2 :             nEPSGCode = atoi(GetAuthorityCode("GEOGCS"));
     219             :         }
     220             :     }
     221             : 
     222             :     /* -------------------------------------------------------------------- */
     223             :     /*      Is our GEOGCS name already defined in ecw_cs.wkt?               */
     224             :     /* -------------------------------------------------------------------- */
     225          52 :     const char *pszWKTDatum = GetAttrValue("DATUM");
     226             : 
     227         104 :     if (pszWKTDatum != nullptr &&
     228         104 :         !lookupInDict("ecw_cs.wkt", pszWKTDatum).empty())
     229             :     {
     230           0 :         strncpy(pszDatum, pszWKTDatum, BUFFER_SIZE);
     231           0 :         pszDatum[BUFFER_SIZE - 1] = '\0';
     232             :     }
     233             : 
     234             :     /* -------------------------------------------------------------------- */
     235             :     /*      Is this a "well known" geographic coordinate system?            */
     236             :     /* -------------------------------------------------------------------- */
     237          52 :     if (EQUAL(pszDatum, "RAW"))
     238             :     {
     239          52 :         int nEPSGGCSCode = GetEPSGGeogCS();
     240             : 
     241          52 :         if (nEPSGGCSCode == 4326)
     242           4 :             strcpy(pszDatum, "WGS84");
     243             : 
     244          48 :         else if (nEPSGGCSCode == 4322)
     245           0 :             strcpy(pszDatum, "WGS72DOD");
     246             : 
     247          48 :         else if (nEPSGGCSCode == 4267)
     248           2 :             strcpy(pszDatum, "NAD27");
     249             : 
     250          46 :         else if (nEPSGGCSCode == 4269)
     251           0 :             strcpy(pszDatum, "NAD83");
     252             : 
     253          46 :         else if (nEPSGGCSCode == 4277)
     254           0 :             strcpy(pszDatum, "OSGB36");
     255             : 
     256          46 :         else if (nEPSGGCSCode == 4278)
     257           0 :             strcpy(pszDatum, "OSGB78");
     258             : 
     259          46 :         else if (nEPSGGCSCode == 4201)
     260           0 :             strcpy(pszDatum, "ADINDAN");
     261             : 
     262          46 :         else if (nEPSGGCSCode == 4202)
     263           0 :             strcpy(pszDatum, "AGD66");
     264             : 
     265          46 :         else if (nEPSGGCSCode == 4203)
     266           0 :             strcpy(pszDatum, "AGD84");
     267             : 
     268          46 :         else if (nEPSGGCSCode == 4209)
     269           0 :             strcpy(pszDatum, "ARC1950");
     270             : 
     271          46 :         else if (nEPSGGCSCode == 4210)
     272           0 :             strcpy(pszDatum, "ARC1960");
     273             : 
     274          46 :         else if (nEPSGGCSCode == 4275)
     275           0 :             strcpy(pszDatum, "NTF");
     276             : 
     277          46 :         else if (nEPSGGCSCode == 4283)
     278           0 :             strcpy(pszDatum, "GDA94");
     279             : 
     280          46 :         else if (nEPSGGCSCode == 4284)
     281           0 :             strcpy(pszDatum, "PULKOVO");
     282             : 
     283          46 :         else if (nEPSGGCSCode == 7844)
     284           1 :             strcpy(pszDatum, "GDA2020");
     285             :     }
     286             : 
     287             :     /* -------------------------------------------------------------------- */
     288             :     /*      Are we working with a geographic (geodetic) coordinate system?  */
     289             :     /* -------------------------------------------------------------------- */
     290             : 
     291          52 :     if (IsGeographic())
     292             :     {
     293          46 :         if (EQUAL(pszDatum, "RAW"))
     294          44 :             return OGRERR_UNSUPPORTED_SRS;
     295             :         else
     296             :         {
     297           2 :             strcpy(pszProj, "GEODETIC");
     298           2 :             return OGRERR_NONE;
     299             :         }
     300             :     }
     301             : 
     302             :     /* -------------------------------------------------------------------- */
     303             :     /*      Is this a UTM projection?                                       */
     304             :     /* -------------------------------------------------------------------- */
     305           6 :     int bNorth = FALSE;
     306           6 :     int nZone = 0;
     307             : 
     308           6 :     nZone = GetUTMZone(&bNorth);
     309           6 :     if (nZone > 0)
     310             :     {
     311           4 :         if ((EQUAL(pszDatum, "GDA94") || EQUAL(pszDatum, "GDA2020")) &&
     312           1 :             !bNorth && nZone >= 48 && nZone <= 58)
     313             :         {
     314           1 :             snprintf(pszProj, BUFFER_SIZE, "MGA%02d", nZone);
     315             :         }
     316             :         else
     317             :         {
     318           3 :             if (bNorth)
     319           3 :                 snprintf(pszProj, BUFFER_SIZE, "NUTM%02d", nZone);
     320             :             else
     321           0 :                 snprintf(pszProj, BUFFER_SIZE, "SUTM%02d", nZone);
     322             :         }
     323             :     }
     324             : 
     325             :     /* -------------------------------------------------------------------- */
     326             :     /*      Is our PROJCS name already defined in ecw_cs.wkt?               */
     327             :     /* -------------------------------------------------------------------- */
     328             :     else
     329             :     {
     330           2 :         const char *pszPROJCS = GetAttrValue("PROJCS");
     331             : 
     332           4 :         if (pszPROJCS != nullptr &&
     333           4 :             lookupInDict("ecw_cs.wkt", pszPROJCS).find("PROJCS") == 0)
     334             :         {
     335           1 :             strncpy(pszProj, pszPROJCS, BUFFER_SIZE);
     336           1 :             pszProj[BUFFER_SIZE - 1] = '\0';
     337             :         }
     338             :     }
     339             : 
     340             :     /* -------------------------------------------------------------------- */
     341             :     /*      If we have not translated it yet, but we have an EPSG code      */
     342             :     /*      then use EPSG:n notation.                                       */
     343             :     /* -------------------------------------------------------------------- */
     344           6 :     if ((EQUAL(pszDatum, "RAW") || EQUAL(pszProj, "RAW")) && nEPSGCode != 0)
     345             :     {
     346           0 :         snprintf(pszProj, BUFFER_SIZE, "EPSG:%d", nEPSGCode);
     347           0 :         snprintf(pszDatum, BUFFER_SIZE, "EPSG:%d", nEPSGCode);
     348             :     }
     349             : 
     350             :     /* -------------------------------------------------------------------- */
     351             :     /*      Handle the units.                                               */
     352             :     /* -------------------------------------------------------------------- */
     353           6 :     const double dfUnits = GetLinearUnits();
     354             : 
     355           6 :     if (fabs(dfUnits - 0.3048) < 0.0001)
     356           1 :         strcpy(pszUnits, "FEET");
     357             :     else
     358           5 :         strcpy(pszUnits, "METERS");
     359             : 
     360           6 :     if (EQUAL(pszProj, "RAW"))
     361           1 :         return OGRERR_UNSUPPORTED_SRS;
     362             : 
     363           5 :     return OGRERR_NONE;
     364             : }

Generated by: LCOV version 1.14