LCOV - code coverage report
Current view: top level - frmts/wcs - gmlcoverage.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 59 77 76.6 %
Date: 2024-11-21 22:18:42 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  Generic support for GML Coverage descriptions.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2006, Frank Warmerdam <warmerdam@pobox.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_port.h"
      14             : #include "gdal_priv.h"
      15             : 
      16             : #include <cstdlib>
      17             : #include <cstring>
      18             : 
      19             : #include "cpl_conv.h"
      20             : #include "cpl_error.h"
      21             : #include "cpl_minixml.h"
      22             : #include "cpl_string.h"
      23             : #include "ogr_api.h"
      24             : #include "ogr_core.h"
      25             : #include "ogr_geometry.h"
      26             : #include "ogr_spatialref.h"
      27             : #include "gmlcoverage.h"
      28             : 
      29             : /************************************************************************/
      30             : /*                        ParseGMLCoverageDesc()                        */
      31             : /************************************************************************/
      32             : 
      33          15 : CPLErr WCSParseGMLCoverage(CPLXMLNode *psXML, int *pnXSize, int *pnYSize,
      34             :                            double *padfGeoTransform, char **ppszProjection)
      35             : 
      36             : {
      37          15 :     CPLStripXMLNamespace(psXML, nullptr, TRUE);
      38             : 
      39             :     /* -------------------------------------------------------------------- */
      40             :     /*      Isolate RectifiedGrid.  Eventually we will need to support      */
      41             :     /*      other georeferencing objects.                                   */
      42             :     /* -------------------------------------------------------------------- */
      43          15 :     CPLXMLNode *psRG = CPLSearchXMLNode(psXML, "=RectifiedGrid");
      44          15 :     CPLXMLNode *psOriginPoint = nullptr;
      45          15 :     const char *pszOffset1 = nullptr;
      46          15 :     const char *pszOffset2 = nullptr;
      47             : 
      48          15 :     if (psRG != nullptr)
      49             :     {
      50          15 :         psOriginPoint = CPLGetXMLNode(psRG, "origin.Point");
      51          15 :         if (psOriginPoint == nullptr)
      52          15 :             psOriginPoint = CPLGetXMLNode(psRG, "origin");
      53             : 
      54          15 :         CPLXMLNode *psOffset1 = CPLGetXMLNode(psRG, "offsetVector");
      55          15 :         if (psOffset1 != nullptr)
      56             :         {
      57          15 :             pszOffset1 = CPLGetXMLValue(psOffset1, "", nullptr);
      58             :             pszOffset2 =
      59          15 :                 CPLGetXMLValue(psOffset1->psNext, "=offsetVector", nullptr);
      60             :         }
      61             :     }
      62             : 
      63             :     /* -------------------------------------------------------------------- */
      64             :     /*      If we are missing any of the origin or 2 offsets then give up.  */
      65             :     /* -------------------------------------------------------------------- */
      66          15 :     if (psRG == nullptr || psOriginPoint == nullptr || pszOffset1 == nullptr ||
      67             :         pszOffset2 == nullptr)
      68             :     {
      69           0 :         CPLError(CE_Failure, CPLE_AppDefined,
      70             :                  "Unable to find GML RectifiedGrid, origin or offset vectors");
      71           0 :         return CE_Failure;
      72             :     }
      73             : 
      74             :     /* -------------------------------------------------------------------- */
      75             :     /*      Search for the GridEnvelope and derive the raster size.         */
      76             :     /* -------------------------------------------------------------------- */
      77             :     char **papszLow =
      78          15 :         CSLTokenizeString(CPLGetXMLValue(psRG, "limits.GridEnvelope.low", ""));
      79             :     char **papszHigh =
      80          15 :         CSLTokenizeString(CPLGetXMLValue(psRG, "limits.GridEnvelope.high", ""));
      81             : 
      82          15 :     if (CSLCount(papszLow) < 2 || CSLCount(papszHigh) < 2)
      83             :     {
      84           0 :         CPLError(CE_Failure, CPLE_AppDefined,
      85             :                  "Unable to find or parse GridEnvelope.low/high.");
      86           0 :         CSLDestroy(papszLow);
      87           0 :         CSLDestroy(papszHigh);
      88           0 :         return CE_Failure;
      89             :     }
      90             : 
      91          15 :     if (pnXSize != nullptr)
      92          15 :         *pnXSize = atoi(papszHigh[0]) - atoi(papszLow[0]) + 1;
      93          15 :     if (pnYSize != nullptr)
      94          15 :         *pnYSize = atoi(papszHigh[1]) - atoi(papszLow[1]) + 1;
      95             : 
      96          15 :     CSLDestroy(papszLow);
      97          15 :     CSLDestroy(papszHigh);
      98             : 
      99             :     /* -------------------------------------------------------------------- */
     100             :     /*      Extract origin location.                                        */
     101             :     /* -------------------------------------------------------------------- */
     102          15 :     OGRPoint *poOriginGeometry = nullptr;
     103           0 :     std::unique_ptr<OGRGeometry> poGeom;
     104          15 :     const char *pszSRSName = nullptr;
     105             : 
     106             :     {
     107          15 :         bool bOldWrap = false;
     108             : 
     109             :         // Old coverages (i.e. WCS) just have <pos> under <origin>, so we
     110             :         // may need to temporarily force <origin> to <Point>.
     111          15 :         if (psOriginPoint->eType == CXT_Element &&
     112          15 :             EQUAL(psOriginPoint->pszValue, "origin"))
     113             :         {
     114          15 :             strcpy(psOriginPoint->pszValue, "Point");
     115          15 :             bOldWrap = true;
     116             :         }
     117          15 :         poGeom.reset(
     118             :             OGRGeometry::FromHandle(OGR_G_CreateFromGMLTree(psOriginPoint)));
     119             : 
     120          30 :         if (poGeom != nullptr &&
     121          15 :             wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
     122             :         {
     123          15 :             poOriginGeometry = poGeom->toPoint();
     124             :         }
     125             : 
     126          15 :         if (bOldWrap)
     127          15 :             strcpy(psOriginPoint->pszValue, "origin");
     128             : 
     129             :         // SRS?
     130          15 :         pszSRSName = CPLGetXMLValue(psOriginPoint, "srsName", nullptr);
     131             :     }
     132             : 
     133             :     /* -------------------------------------------------------------------- */
     134             :     /*      Extract offset(s)                                               */
     135             :     /* -------------------------------------------------------------------- */
     136          15 :     bool bSuccess = false;
     137             : 
     138             :     char **papszOffset1Tokens =
     139          15 :         CSLTokenizeStringComplex(pszOffset1, " ,", FALSE, FALSE);
     140             :     char **papszOffset2Tokens =
     141          15 :         CSLTokenizeStringComplex(pszOffset2, " ,", FALSE, FALSE);
     142             : 
     143          15 :     if (CSLCount(papszOffset1Tokens) >= 2 &&
     144          15 :         CSLCount(papszOffset2Tokens) >= 2 && poOriginGeometry != nullptr)
     145             :     {
     146          15 :         padfGeoTransform[0] = poOriginGeometry->getX();
     147          15 :         padfGeoTransform[1] = CPLAtof(papszOffset1Tokens[0]);
     148          15 :         padfGeoTransform[2] = CPLAtof(papszOffset1Tokens[1]);
     149          15 :         padfGeoTransform[3] = poOriginGeometry->getY();
     150          15 :         padfGeoTransform[4] = CPLAtof(papszOffset2Tokens[0]);
     151          15 :         padfGeoTransform[5] = CPLAtof(papszOffset2Tokens[1]);
     152             : 
     153             :         // offset from center of pixel.
     154          15 :         padfGeoTransform[0] -= padfGeoTransform[1] * 0.5;
     155          15 :         padfGeoTransform[0] -= padfGeoTransform[2] * 0.5;
     156          15 :         padfGeoTransform[3] -= padfGeoTransform[4] * 0.5;
     157          15 :         padfGeoTransform[3] -= padfGeoTransform[5] * 0.5;
     158             : 
     159          15 :         bSuccess = true;
     160             :     }
     161             : 
     162          15 :     CSLDestroy(papszOffset1Tokens);
     163          15 :     CSLDestroy(papszOffset2Tokens);
     164             : 
     165             :     /* -------------------------------------------------------------------- */
     166             :     /*      If we have gotten a geotransform, then try to interpret the     */
     167             :     /*      srsName.                                                        */
     168             :     /* -------------------------------------------------------------------- */
     169          15 :     if (bSuccess && pszSRSName != nullptr &&
     170           0 :         (*ppszProjection == nullptr || strlen(*ppszProjection) == 0))
     171             :     {
     172           0 :         if (STARTS_WITH_CI(pszSRSName, "epsg:"))
     173             :         {
     174           0 :             OGRSpatialReference oSRS;
     175           0 :             if (oSRS.SetFromUserInput(pszSRSName) == OGRERR_NONE)
     176           0 :                 oSRS.exportToWkt(ppszProjection);
     177             :         }
     178           0 :         else if (STARTS_WITH_CI(pszSRSName, "urn:ogc:def:crs:"))
     179             :         {
     180           0 :             OGRSpatialReference oSRS;
     181           0 :             if (oSRS.importFromURN(pszSRSName) == OGRERR_NONE)
     182           0 :                 oSRS.exportToWkt(ppszProjection);
     183             :         }
     184             :         else
     185           0 :             *ppszProjection = CPLStrdup(pszSRSName);
     186             :     }
     187             : 
     188          15 :     if (*ppszProjection)
     189           0 :         CPLDebug("GDALJP2Metadata", "Got projection from GML box: %s",
     190             :                  *ppszProjection);
     191             : 
     192          15 :     return CE_None;
     193             : }

Generated by: LCOV version 1.14