LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/wasp - ogrwaspdatasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 112 148 75.7 %
Date: 2025-01-18 12:42:00 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             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "ogrwasp.h"
      14             : #include "cpl_conv.h"
      15             : #include "cpl_string.h"
      16             : 
      17             : #include <cassert>
      18             : #include <sstream>
      19             : 
      20             : /************************************************************************/
      21             : /*                          OGRWAsPDataSource()                          */
      22             : /************************************************************************/
      23             : 
      24          42 : OGRWAsPDataSource::OGRWAsPDataSource(const char *pszName, VSILFILE *hFileHandle)
      25          42 :     : sFilename(pszName), hFile(hFileHandle)
      26             : {
      27          42 : }
      28             : 
      29             : /************************************************************************/
      30             : /*                         ~OGRWAsPDataSource()                          */
      31             : /************************************************************************/
      32             : 
      33          84 : OGRWAsPDataSource::~OGRWAsPDataSource()
      34             : 
      35             : {
      36          42 :     oLayer.reset();    /* we write to file int layer dtor */
      37          42 :     VSIFCloseL(hFile); /* nothing smart can be done here in case of error */
      38          84 : }
      39             : 
      40             : /************************************************************************/
      41             : /*                           TestCapability()                           */
      42             : /************************************************************************/
      43             : 
      44          32 : int OGRWAsPDataSource::TestCapability(const char *pszCap)
      45             : 
      46             : {
      47          32 :     if (EQUAL(pszCap, ODsCCreateLayer) && oLayer.get() == nullptr)
      48          16 :         return true;
      49          16 :     else if (EQUAL(pszCap, ODsCZGeometries))
      50           0 :         return true;
      51             : 
      52          16 :     return false;
      53             : }
      54             : 
      55             : /************************************************************************/
      56             : /*                              GetLayerByName()                        */
      57             : /************************************************************************/
      58             : 
      59           2 : OGRLayer *OGRWAsPDataSource::GetLayerByName(const char *pszName)
      60             : 
      61             : {
      62           2 :     return (oLayer.get() && EQUAL(pszName, oLayer->GetName())) ? oLayer.get()
      63           2 :                                                                : nullptr;
      64             : }
      65             : 
      66             : /************************************************************************/
      67             : /*                              Load()                                  */
      68             : /************************************************************************/
      69             : 
      70           9 : OGRErr OGRWAsPDataSource::Load(bool bSilent)
      71             : 
      72             : {
      73             :     /* if we don't have a layer, we read from file */
      74           9 :     if (oLayer.get())
      75             :     {
      76           0 :         if (!bSilent)
      77           0 :             CPLError(CE_Failure, CPLE_NotSupported, "layer already loaded");
      78           0 :         return OGRERR_FAILURE;
      79             :     }
      80             :     /* Parse the first line of the file in case it is a spatial ref*/
      81           9 :     const char *pszLine = CPLReadLine2L(hFile, 1024, nullptr);
      82           9 :     if (!pszLine)
      83             :     {
      84           0 :         if (!bSilent)
      85           0 :             CPLError(CE_Failure, CPLE_FileIO, "empty file");
      86           0 :         return OGRERR_FAILURE;
      87             :     }
      88          18 :     CPLString sLine(pszLine);
      89           9 :     sLine = sLine.substr(0, sLine.find("|"));
      90           9 :     OGRSpatialReference *poSpatialRef = new OGRSpatialReference;
      91           9 :     poSpatialRef->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
      92           9 :     if (poSpatialRef->importFromProj4(sLine.c_str()) != OGRERR_NONE)
      93             :     {
      94           8 :         if (!bSilent)
      95           0 :             CPLError(CE_Warning, CPLE_FileIO, "cannot find spatial reference");
      96           8 :         delete poSpatialRef;
      97           8 :         poSpatialRef = nullptr;
      98             :     }
      99             : 
     100             :     /* TODO Parse those line since they define a coordinate transformation */
     101           9 :     CPLReadLineL(hFile);
     102           9 :     CPLReadLineL(hFile);
     103           9 :     CPLReadLineL(hFile);
     104             : 
     105           9 :     oLayer.reset(new OGRWAsPLayer(this,
     106          18 :                                   CPLGetBasenameSafe(sFilename.c_str()).c_str(),
     107           9 :                                   hFile, poSpatialRef));
     108           9 :     if (poSpatialRef)
     109           1 :         poSpatialRef->Release();
     110             : 
     111           9 :     const vsi_l_offset iOffset = VSIFTellL(hFile);
     112           9 :     pszLine = CPLReadLineL(hFile);
     113           9 :     if (!pszLine)
     114             :     {
     115           6 :         if (!bSilent)
     116           0 :             CPLError(CE_Failure, CPLE_FileIO, "no feature in file");
     117           6 :         oLayer.reset();
     118           6 :         return OGRERR_FAILURE;
     119             :     }
     120             : 
     121           3 :     double dfValues[4] = {0};
     122           3 :     int iNumValues = 0;
     123             :     {
     124           6 :         std::istringstream iss(pszLine);
     125           9 :         while (iNumValues < 4 && (iss >> dfValues[iNumValues]))
     126             :         {
     127           6 :             ++iNumValues;
     128             :         }
     129             : 
     130           3 :         if (iNumValues < 2)
     131             :         {
     132           0 :             if (!bSilent && iNumValues)
     133           0 :                 CPLError(CE_Failure, CPLE_FileIO, "no enough values");
     134           0 :             else if (!bSilent)
     135           0 :                 CPLError(CE_Failure, CPLE_FileIO, "no feature in file");
     136             : 
     137           0 :             oLayer.reset();
     138           0 :             return OGRERR_FAILURE;
     139             :         }
     140             :     }
     141             : 
     142           3 :     if (iNumValues == 3 || iNumValues == 4)
     143             :     {
     144           0 :         OGRFieldDefn left("z_left", OFTReal);
     145           0 :         OGRFieldDefn right("z_right", OFTReal);
     146           0 :         oLayer->CreateField(&left);
     147           0 :         oLayer->CreateField(&right);
     148             :     }
     149           3 :     if (iNumValues == 2 || iNumValues == 4)
     150             :     {
     151           6 :         OGRFieldDefn height("elevation", OFTReal);
     152           3 :         oLayer->CreateField(&height);
     153             :     }
     154             : 
     155           3 :     VSIFSeekL(hFile, iOffset, SEEK_SET);
     156           3 :     return OGRERR_NONE;
     157             : }
     158             : 
     159             : /************************************************************************/
     160             : /*                              GetLayer()                              */
     161             : /************************************************************************/
     162             : 
     163           1 : OGRLayer *OGRWAsPDataSource::GetLayer(int iLayer)
     164             : 
     165             : {
     166           1 :     return (iLayer == 0) ? oLayer.get() : nullptr;
     167             : }
     168             : 
     169             : /************************************************************************/
     170             : /*                             ICreateLayer()                           */
     171             : /************************************************************************/
     172             : 
     173             : OGRLayer *
     174          40 : OGRWAsPDataSource::ICreateLayer(const char *pszName,
     175             :                                 const OGRGeomFieldDefn *poGeomFieldDefn,
     176             :                                 CSLConstList papszOptions)
     177             : 
     178             : {
     179          40 :     const auto eGType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
     180             :     const auto poSpatialRef =
     181          40 :         poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
     182             : 
     183          40 :     if (eGType != wkbLineString && eGType != wkbLineString25D &&
     184          26 :         eGType != wkbMultiLineString && eGType != wkbMultiLineString25D &&
     185          19 :         eGType != wkbPolygon && eGType != wkbPolygon25D &&
     186          11 :         eGType != wkbMultiPolygon && eGType != wkbMultiPolygon25D)
     187             :     {
     188           8 :         CPLError(CE_Failure, CPLE_NotSupported, "unsupported geometry type %s",
     189             :                  OGRGeometryTypeToName(eGType));
     190           8 :         return nullptr;
     191             :     }
     192             : 
     193          32 :     if (!OGRGeometryFactory::haveGEOS() &&
     194           0 :         (eGType == wkbPolygon || eGType == wkbPolygon25D ||
     195           0 :          eGType == wkbMultiPolygon || eGType == wkbMultiPolygon25D))
     196             :     {
     197           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     198             :                  "unsupported geometry type %s without GEOS support",
     199             :                  OGRGeometryTypeToName(eGType));
     200           0 :         return nullptr;
     201             :     }
     202             : 
     203          32 :     if (oLayer.get())
     204             :     {
     205           8 :         CPLError(CE_Failure, CPLE_NotSupported,
     206             :                  "this data source does not support more than one layer");
     207           8 :         return nullptr;
     208             :     }
     209             : 
     210          48 :     CPLString sFirstField, sSecondField, sGeomField;
     211             : 
     212          24 :     const char *pszFields = CSLFetchNameValue(papszOptions, "WASP_FIELDS");
     213          48 :     const CPLString sFields(pszFields ? pszFields : "");
     214          24 :     if (!sFields.empty())
     215             :     {
     216             :         /* parse the comma separated list of fields */
     217           3 :         const size_t iComma = sFields.find(',');
     218           3 :         if (std::string::npos != iComma)
     219             :         {
     220           1 :             sFirstField = sFields.substr(0, iComma);
     221           1 :             sSecondField = sFields.substr(iComma + 1);
     222             :         }
     223             :         else
     224             :         {
     225           2 :             sFirstField = sFields;
     226             :         }
     227             :     }
     228             : 
     229             :     const char *pszGeomField =
     230          24 :         CSLFetchNameValue(papszOptions, "WASP_GEOM_FIELD");
     231          24 :     sGeomField = CPLString(pszGeomField ? pszGeomField : "");
     232             : 
     233             :     const bool bMerge =
     234          24 :         CPLTestBool(CSLFetchNameValueDef(papszOptions, "WASP_MERGE", "YES"));
     235             : 
     236          24 :     std::unique_ptr<double> pdfTolerance;
     237             :     {
     238             :         const char *pszToler =
     239          24 :             CSLFetchNameValue(papszOptions, "WASP_TOLERANCE");
     240             : 
     241          24 :         if (pszToler)
     242             :         {
     243           1 :             if (!OGRGeometryFactory::haveGEOS())
     244             :             {
     245           0 :                 CPLError(
     246             :                     CE_Warning, CPLE_IllegalArg,
     247             :                     "GEOS support not enabled, ignoring option WASP_TOLERANCE");
     248             :             }
     249             :             else
     250             :             {
     251           1 :                 pdfTolerance.reset(new double);
     252           1 :                 if (!(std::istringstream(pszToler) >> *pdfTolerance))
     253             :                 {
     254           0 :                     CPLError(CE_Failure, CPLE_IllegalArg,
     255             :                              "cannot set tolerance from %s", pszToler);
     256           0 :                     return nullptr;
     257             :                 }
     258             :             }
     259             :         }
     260             :     }
     261             : 
     262          24 :     std::unique_ptr<double> pdfAdjacentPointTolerance;
     263             :     {
     264             :         const char *pszAdjToler =
     265          24 :             CSLFetchNameValue(papszOptions, "WASP_ADJ_TOLER");
     266          24 :         if (pszAdjToler)
     267             :         {
     268           0 :             pdfAdjacentPointTolerance.reset(new double);
     269           0 :             if (!(std::istringstream(pszAdjToler) >>
     270           0 :                   *pdfAdjacentPointTolerance))
     271             :             {
     272           0 :                 CPLError(CE_Failure, CPLE_IllegalArg,
     273             :                          "cannot set tolerance from %s", pszAdjToler);
     274           0 :                 return nullptr;
     275             :             }
     276             :         }
     277             :     }
     278             : 
     279          24 :     std::unique_ptr<double> pdfPointToCircleRadius;
     280             :     {
     281             :         const char *pszPtToCircRad =
     282          24 :             CSLFetchNameValue(papszOptions, "WASP_POINT_TO_CIRCLE_RADIUS");
     283          24 :         if (pszPtToCircRad)
     284             :         {
     285           0 :             pdfPointToCircleRadius.reset(new double);
     286           0 :             if (!(std::istringstream(pszPtToCircRad) >>
     287           0 :                   *pdfPointToCircleRadius))
     288             :             {
     289           0 :                 CPLError(CE_Failure, CPLE_IllegalArg,
     290             :                          "cannot set tolerance from %s", pszPtToCircRad);
     291           0 :                 return nullptr;
     292             :             }
     293             :         }
     294             :     }
     295             : 
     296          24 :     OGRSpatialReference *poSRSClone = nullptr;
     297          24 :     if (poSpatialRef)
     298             :     {
     299           3 :         poSRSClone = poSpatialRef->Clone();
     300           3 :         poSRSClone->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     301             :     }
     302          24 :     oLayer.reset(new OGRWAsPLayer(
     303          48 :         this, CPLGetBasenameSafe(pszName).c_str(), hFile, poSRSClone,
     304          24 :         sFirstField, sSecondField, sGeomField, bMerge, pdfTolerance.release(),
     305          24 :         pdfAdjacentPointTolerance.release(), pdfPointToCircleRadius.release()));
     306          24 :     if (poSRSClone)
     307           3 :         poSRSClone->Release();
     308             : 
     309          24 :     char *ppszWktSpatialRef = nullptr;
     310          27 :     if (poSpatialRef &&
     311           3 :         poSpatialRef->exportToProj4(&ppszWktSpatialRef) == OGRERR_NONE)
     312             :     {
     313           3 :         VSIFPrintfL(hFile, "%s\n", ppszWktSpatialRef);
     314             :     }
     315             :     else
     316             :     {
     317          21 :         VSIFPrintfL(hFile, "no spatial ref sys\n");
     318             :     }
     319          24 :     CPLFree(ppszWktSpatialRef);
     320             : 
     321          24 :     VSIFPrintfL(hFile, "  0.0 0.0 0.0 0.0\n");
     322          24 :     VSIFPrintfL(hFile, "  1.0 0.0 1.0 0.0\n");
     323          24 :     VSIFPrintfL(hFile, "  1.0 0.0\n");
     324          24 :     return oLayer.get();
     325             : }

Generated by: LCOV version 1.14