LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/wasp - ogrwaspdatasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 111 147 75.5 %
Date: 2024-05-06 22:33:47 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  WAsP Translator
       4             :  * Purpose:  Implements OGRWAsPDataSource class
       5             :  * Author:   Vincent Mora, vincent dot mora at oslandia dot com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2014, Oslandia <info at oslandia dot com>
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "ogrwasp.h"
      30             : #include "cpl_conv.h"
      31             : #include "cpl_string.h"
      32             : 
      33             : #include <cassert>
      34             : #include <sstream>
      35             : 
      36             : /************************************************************************/
      37             : /*                          OGRWAsPDataSource()                          */
      38             : /************************************************************************/
      39             : 
      40          42 : OGRWAsPDataSource::OGRWAsPDataSource(const char *pszName, VSILFILE *hFileHandle)
      41          42 :     : sFilename(pszName), hFile(hFileHandle)
      42             : {
      43          42 : }
      44             : 
      45             : /************************************************************************/
      46             : /*                         ~OGRWAsPDataSource()                          */
      47             : /************************************************************************/
      48             : 
      49          84 : OGRWAsPDataSource::~OGRWAsPDataSource()
      50             : 
      51             : {
      52          42 :     oLayer.reset();    /* we write to file int layer dtor */
      53          42 :     VSIFCloseL(hFile); /* nothing smart can be done here in case of error */
      54          84 : }
      55             : 
      56             : /************************************************************************/
      57             : /*                           TestCapability()                           */
      58             : /************************************************************************/
      59             : 
      60          32 : int OGRWAsPDataSource::TestCapability(const char *pszCap)
      61             : 
      62             : {
      63          32 :     if (EQUAL(pszCap, ODsCCreateLayer) && oLayer.get() == nullptr)
      64          16 :         return true;
      65          16 :     else if (EQUAL(pszCap, ODsCZGeometries))
      66           0 :         return true;
      67             : 
      68          16 :     return false;
      69             : }
      70             : 
      71             : /************************************************************************/
      72             : /*                              GetLayerByName()                        */
      73             : /************************************************************************/
      74             : 
      75           2 : OGRLayer *OGRWAsPDataSource::GetLayerByName(const char *pszName)
      76             : 
      77             : {
      78           2 :     return (oLayer.get() && EQUAL(pszName, oLayer->GetName())) ? oLayer.get()
      79           2 :                                                                : nullptr;
      80             : }
      81             : 
      82             : /************************************************************************/
      83             : /*                              Load()                                  */
      84             : /************************************************************************/
      85             : 
      86           9 : OGRErr OGRWAsPDataSource::Load(bool bSilent)
      87             : 
      88             : {
      89             :     /* if we don't have a layer, we read from file */
      90           9 :     if (oLayer.get())
      91             :     {
      92           0 :         if (!bSilent)
      93           0 :             CPLError(CE_Failure, CPLE_NotSupported, "layer already loaded");
      94           0 :         return OGRERR_FAILURE;
      95             :     }
      96             :     /* Parse the first line of the file in case it is a spatial ref*/
      97           9 :     const char *pszLine = CPLReadLine2L(hFile, 1024, nullptr);
      98           9 :     if (!pszLine)
      99             :     {
     100           0 :         if (!bSilent)
     101           0 :             CPLError(CE_Failure, CPLE_FileIO, "empty file");
     102           0 :         return OGRERR_FAILURE;
     103             :     }
     104          18 :     CPLString sLine(pszLine);
     105           9 :     sLine = sLine.substr(0, sLine.find("|"));
     106           9 :     OGRSpatialReference *poSpatialRef = new OGRSpatialReference;
     107           9 :     poSpatialRef->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     108           9 :     if (poSpatialRef->importFromProj4(sLine.c_str()) != OGRERR_NONE)
     109             :     {
     110           8 :         if (!bSilent)
     111           0 :             CPLError(CE_Warning, CPLE_FileIO, "cannot find spatial reference");
     112           8 :         delete poSpatialRef;
     113           8 :         poSpatialRef = nullptr;
     114             :     }
     115             : 
     116             :     /* TODO Parse those line since they define a coordinate transformation */
     117           9 :     CPLReadLineL(hFile);
     118           9 :     CPLReadLineL(hFile);
     119           9 :     CPLReadLineL(hFile);
     120             : 
     121          18 :     oLayer.reset(new OGRWAsPLayer(this, CPLGetBasename(sFilename.c_str()),
     122           9 :                                   hFile, poSpatialRef));
     123           9 :     if (poSpatialRef)
     124           1 :         poSpatialRef->Release();
     125             : 
     126           9 :     const vsi_l_offset iOffset = VSIFTellL(hFile);
     127           9 :     pszLine = CPLReadLineL(hFile);
     128           9 :     if (!pszLine)
     129             :     {
     130           6 :         if (!bSilent)
     131           0 :             CPLError(CE_Failure, CPLE_FileIO, "no feature in file");
     132           6 :         oLayer.reset();
     133           6 :         return OGRERR_FAILURE;
     134             :     }
     135             : 
     136           3 :     double dfValues[4] = {0};
     137           3 :     int iNumValues = 0;
     138             :     {
     139           6 :         std::istringstream iss(pszLine);
     140           9 :         while (iNumValues < 4 && (iss >> dfValues[iNumValues]))
     141             :         {
     142           6 :             ++iNumValues;
     143             :         }
     144             : 
     145           3 :         if (iNumValues < 2)
     146             :         {
     147           0 :             if (!bSilent && iNumValues)
     148           0 :                 CPLError(CE_Failure, CPLE_FileIO, "no enough values");
     149           0 :             else if (!bSilent)
     150           0 :                 CPLError(CE_Failure, CPLE_FileIO, "no feature in file");
     151             : 
     152           0 :             oLayer.reset();
     153           0 :             return OGRERR_FAILURE;
     154             :         }
     155             :     }
     156             : 
     157           3 :     if (iNumValues == 3 || iNumValues == 4)
     158             :     {
     159           0 :         OGRFieldDefn left("z_left", OFTReal);
     160           0 :         OGRFieldDefn right("z_right", OFTReal);
     161           0 :         oLayer->CreateField(&left);
     162           0 :         oLayer->CreateField(&right);
     163             :     }
     164           3 :     if (iNumValues == 2 || iNumValues == 4)
     165             :     {
     166           6 :         OGRFieldDefn height("elevation", OFTReal);
     167           3 :         oLayer->CreateField(&height);
     168             :     }
     169             : 
     170           3 :     VSIFSeekL(hFile, iOffset, SEEK_SET);
     171           3 :     return OGRERR_NONE;
     172             : }
     173             : 
     174             : /************************************************************************/
     175             : /*                              GetLayer()                              */
     176             : /************************************************************************/
     177             : 
     178           1 : OGRLayer *OGRWAsPDataSource::GetLayer(int iLayer)
     179             : 
     180             : {
     181           1 :     return (iLayer == 0) ? oLayer.get() : nullptr;
     182             : }
     183             : 
     184             : /************************************************************************/
     185             : /*                             ICreateLayer()                           */
     186             : /************************************************************************/
     187             : 
     188             : OGRLayer *
     189          40 : OGRWAsPDataSource::ICreateLayer(const char *pszName,
     190             :                                 const OGRGeomFieldDefn *poGeomFieldDefn,
     191             :                                 CSLConstList papszOptions)
     192             : 
     193             : {
     194          40 :     const auto eGType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
     195             :     const auto poSpatialRef =
     196          40 :         poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
     197             : 
     198          40 :     if (eGType != wkbLineString && eGType != wkbLineString25D &&
     199          26 :         eGType != wkbMultiLineString && eGType != wkbMultiLineString25D &&
     200          19 :         eGType != wkbPolygon && eGType != wkbPolygon25D &&
     201          11 :         eGType != wkbMultiPolygon && eGType != wkbMultiPolygon25D)
     202             :     {
     203           8 :         CPLError(CE_Failure, CPLE_NotSupported, "unsupported geometry type %s",
     204             :                  OGRGeometryTypeToName(eGType));
     205           8 :         return nullptr;
     206             :     }
     207             : 
     208          32 :     if (!OGRGeometryFactory::haveGEOS() &&
     209           0 :         (eGType == wkbPolygon || eGType == wkbPolygon25D ||
     210           0 :          eGType == wkbMultiPolygon || eGType == wkbMultiPolygon25D))
     211             :     {
     212           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     213             :                  "unsupported geometry type %s without GEOS support",
     214             :                  OGRGeometryTypeToName(eGType));
     215           0 :         return nullptr;
     216             :     }
     217             : 
     218          32 :     if (oLayer.get())
     219             :     {
     220           8 :         CPLError(CE_Failure, CPLE_NotSupported,
     221             :                  "this data source does not support more than one layer");
     222           8 :         return nullptr;
     223             :     }
     224             : 
     225          48 :     CPLString sFirstField, sSecondField, sGeomField;
     226             : 
     227          24 :     const char *pszFields = CSLFetchNameValue(papszOptions, "WASP_FIELDS");
     228          48 :     const CPLString sFields(pszFields ? pszFields : "");
     229          24 :     if (!sFields.empty())
     230             :     {
     231             :         /* parse the comma separated list of fields */
     232           3 :         const size_t iComma = sFields.find(',');
     233           3 :         if (std::string::npos != iComma)
     234             :         {
     235           1 :             sFirstField = sFields.substr(0, iComma);
     236           1 :             sSecondField = sFields.substr(iComma + 1);
     237             :         }
     238             :         else
     239             :         {
     240           2 :             sFirstField = sFields;
     241             :         }
     242             :     }
     243             : 
     244             :     const char *pszGeomField =
     245          24 :         CSLFetchNameValue(papszOptions, "WASP_GEOM_FIELD");
     246          24 :     sGeomField = CPLString(pszGeomField ? pszGeomField : "");
     247             : 
     248             :     const bool bMerge =
     249          24 :         CPLTestBool(CSLFetchNameValueDef(papszOptions, "WASP_MERGE", "YES"));
     250             : 
     251          24 :     std::unique_ptr<double> pdfTolerance;
     252             :     {
     253             :         const char *pszToler =
     254          24 :             CSLFetchNameValue(papszOptions, "WASP_TOLERANCE");
     255             : 
     256          24 :         if (pszToler)
     257             :         {
     258           1 :             if (!OGRGeometryFactory::haveGEOS())
     259             :             {
     260           0 :                 CPLError(
     261             :                     CE_Warning, CPLE_IllegalArg,
     262             :                     "GEOS support not enabled, ignoring option WASP_TOLERANCE");
     263             :             }
     264             :             else
     265             :             {
     266           1 :                 pdfTolerance.reset(new double);
     267           1 :                 if (!(std::istringstream(pszToler) >> *pdfTolerance))
     268             :                 {
     269           0 :                     CPLError(CE_Failure, CPLE_IllegalArg,
     270             :                              "cannot set tolerance from %s", pszToler);
     271           0 :                     return nullptr;
     272             :                 }
     273             :             }
     274             :         }
     275             :     }
     276             : 
     277          24 :     std::unique_ptr<double> pdfAdjacentPointTolerance;
     278             :     {
     279             :         const char *pszAdjToler =
     280          24 :             CSLFetchNameValue(papszOptions, "WASP_ADJ_TOLER");
     281          24 :         if (pszAdjToler)
     282             :         {
     283           0 :             pdfAdjacentPointTolerance.reset(new double);
     284           0 :             if (!(std::istringstream(pszAdjToler) >>
     285           0 :                   *pdfAdjacentPointTolerance))
     286             :             {
     287           0 :                 CPLError(CE_Failure, CPLE_IllegalArg,
     288             :                          "cannot set tolerance from %s", pszAdjToler);
     289           0 :                 return nullptr;
     290             :             }
     291             :         }
     292             :     }
     293             : 
     294          24 :     std::unique_ptr<double> pdfPointToCircleRadius;
     295             :     {
     296             :         const char *pszPtToCircRad =
     297          24 :             CSLFetchNameValue(papszOptions, "WASP_POINT_TO_CIRCLE_RADIUS");
     298          24 :         if (pszPtToCircRad)
     299             :         {
     300           0 :             pdfPointToCircleRadius.reset(new double);
     301           0 :             if (!(std::istringstream(pszPtToCircRad) >>
     302           0 :                   *pdfPointToCircleRadius))
     303             :             {
     304           0 :                 CPLError(CE_Failure, CPLE_IllegalArg,
     305             :                          "cannot set tolerance from %s", pszPtToCircRad);
     306           0 :                 return nullptr;
     307             :             }
     308             :         }
     309             :     }
     310             : 
     311          24 :     OGRSpatialReference *poSRSClone = nullptr;
     312          24 :     if (poSpatialRef)
     313             :     {
     314           3 :         poSRSClone = poSpatialRef->Clone();
     315           3 :         poSRSClone->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     316             :     }
     317          24 :     oLayer.reset(new OGRWAsPLayer(
     318          24 :         this, CPLGetBasename(pszName), hFile, poSRSClone, sFirstField,
     319          24 :         sSecondField, sGeomField, bMerge, pdfTolerance.release(),
     320          24 :         pdfAdjacentPointTolerance.release(), pdfPointToCircleRadius.release()));
     321          24 :     if (poSRSClone)
     322           3 :         poSRSClone->Release();
     323             : 
     324          24 :     char *ppszWktSpatialRef = nullptr;
     325          27 :     if (poSpatialRef &&
     326           3 :         poSpatialRef->exportToProj4(&ppszWktSpatialRef) == OGRERR_NONE)
     327             :     {
     328           3 :         VSIFPrintfL(hFile, "%s\n", ppszWktSpatialRef);
     329             :     }
     330             :     else
     331             :     {
     332          21 :         VSIFPrintfL(hFile, "no spatial ref sys\n");
     333             :     }
     334          24 :     CPLFree(ppszWktSpatialRef);
     335             : 
     336          24 :     VSIFPrintfL(hFile, "  0.0 0.0 0.0 0.0\n");
     337          24 :     VSIFPrintfL(hFile, "  1.0 0.0 1.0 0.0\n");
     338          24 :     VSIFPrintfL(hFile, "  1.0 0.0\n");
     339          24 :     return oLayer.get();
     340             : }

Generated by: LCOV version 1.14