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-11-21 22:18:42 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          18 :     oLayer.reset(new OGRWAsPLayer(this, CPLGetBasename(sFilename.c_str()),
     106           9 :                                   hFile, poSpatialRef));
     107           9 :     if (poSpatialRef)
     108           1 :         poSpatialRef->Release();
     109             : 
     110           9 :     const vsi_l_offset iOffset = VSIFTellL(hFile);
     111           9 :     pszLine = CPLReadLineL(hFile);
     112           9 :     if (!pszLine)
     113             :     {
     114           6 :         if (!bSilent)
     115           0 :             CPLError(CE_Failure, CPLE_FileIO, "no feature in file");
     116           6 :         oLayer.reset();
     117           6 :         return OGRERR_FAILURE;
     118             :     }
     119             : 
     120           3 :     double dfValues[4] = {0};
     121           3 :     int iNumValues = 0;
     122             :     {
     123           6 :         std::istringstream iss(pszLine);
     124           9 :         while (iNumValues < 4 && (iss >> dfValues[iNumValues]))
     125             :         {
     126           6 :             ++iNumValues;
     127             :         }
     128             : 
     129           3 :         if (iNumValues < 2)
     130             :         {
     131           0 :             if (!bSilent && iNumValues)
     132           0 :                 CPLError(CE_Failure, CPLE_FileIO, "no enough values");
     133           0 :             else if (!bSilent)
     134           0 :                 CPLError(CE_Failure, CPLE_FileIO, "no feature in file");
     135             : 
     136           0 :             oLayer.reset();
     137           0 :             return OGRERR_FAILURE;
     138             :         }
     139             :     }
     140             : 
     141           3 :     if (iNumValues == 3 || iNumValues == 4)
     142             :     {
     143           0 :         OGRFieldDefn left("z_left", OFTReal);
     144           0 :         OGRFieldDefn right("z_right", OFTReal);
     145           0 :         oLayer->CreateField(&left);
     146           0 :         oLayer->CreateField(&right);
     147             :     }
     148           3 :     if (iNumValues == 2 || iNumValues == 4)
     149             :     {
     150           6 :         OGRFieldDefn height("elevation", OFTReal);
     151           3 :         oLayer->CreateField(&height);
     152             :     }
     153             : 
     154           3 :     VSIFSeekL(hFile, iOffset, SEEK_SET);
     155           3 :     return OGRERR_NONE;
     156             : }
     157             : 
     158             : /************************************************************************/
     159             : /*                              GetLayer()                              */
     160             : /************************************************************************/
     161             : 
     162           1 : OGRLayer *OGRWAsPDataSource::GetLayer(int iLayer)
     163             : 
     164             : {
     165           1 :     return (iLayer == 0) ? oLayer.get() : nullptr;
     166             : }
     167             : 
     168             : /************************************************************************/
     169             : /*                             ICreateLayer()                           */
     170             : /************************************************************************/
     171             : 
     172             : OGRLayer *
     173          40 : OGRWAsPDataSource::ICreateLayer(const char *pszName,
     174             :                                 const OGRGeomFieldDefn *poGeomFieldDefn,
     175             :                                 CSLConstList papszOptions)
     176             : 
     177             : {
     178          40 :     const auto eGType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
     179             :     const auto poSpatialRef =
     180          40 :         poGeomFieldDefn ? poGeomFieldDefn->GetSpatialRef() : nullptr;
     181             : 
     182          40 :     if (eGType != wkbLineString && eGType != wkbLineString25D &&
     183          26 :         eGType != wkbMultiLineString && eGType != wkbMultiLineString25D &&
     184          19 :         eGType != wkbPolygon && eGType != wkbPolygon25D &&
     185          11 :         eGType != wkbMultiPolygon && eGType != wkbMultiPolygon25D)
     186             :     {
     187           8 :         CPLError(CE_Failure, CPLE_NotSupported, "unsupported geometry type %s",
     188             :                  OGRGeometryTypeToName(eGType));
     189           8 :         return nullptr;
     190             :     }
     191             : 
     192          32 :     if (!OGRGeometryFactory::haveGEOS() &&
     193           0 :         (eGType == wkbPolygon || eGType == wkbPolygon25D ||
     194           0 :          eGType == wkbMultiPolygon || eGType == wkbMultiPolygon25D))
     195             :     {
     196           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     197             :                  "unsupported geometry type %s without GEOS support",
     198             :                  OGRGeometryTypeToName(eGType));
     199           0 :         return nullptr;
     200             :     }
     201             : 
     202          32 :     if (oLayer.get())
     203             :     {
     204           8 :         CPLError(CE_Failure, CPLE_NotSupported,
     205             :                  "this data source does not support more than one layer");
     206           8 :         return nullptr;
     207             :     }
     208             : 
     209          48 :     CPLString sFirstField, sSecondField, sGeomField;
     210             : 
     211          24 :     const char *pszFields = CSLFetchNameValue(papszOptions, "WASP_FIELDS");
     212          48 :     const CPLString sFields(pszFields ? pszFields : "");
     213          24 :     if (!sFields.empty())
     214             :     {
     215             :         /* parse the comma separated list of fields */
     216           3 :         const size_t iComma = sFields.find(',');
     217           3 :         if (std::string::npos != iComma)
     218             :         {
     219           1 :             sFirstField = sFields.substr(0, iComma);
     220           1 :             sSecondField = sFields.substr(iComma + 1);
     221             :         }
     222             :         else
     223             :         {
     224           2 :             sFirstField = sFields;
     225             :         }
     226             :     }
     227             : 
     228             :     const char *pszGeomField =
     229          24 :         CSLFetchNameValue(papszOptions, "WASP_GEOM_FIELD");
     230          24 :     sGeomField = CPLString(pszGeomField ? pszGeomField : "");
     231             : 
     232             :     const bool bMerge =
     233          24 :         CPLTestBool(CSLFetchNameValueDef(papszOptions, "WASP_MERGE", "YES"));
     234             : 
     235          24 :     std::unique_ptr<double> pdfTolerance;
     236             :     {
     237             :         const char *pszToler =
     238          24 :             CSLFetchNameValue(papszOptions, "WASP_TOLERANCE");
     239             : 
     240          24 :         if (pszToler)
     241             :         {
     242           1 :             if (!OGRGeometryFactory::haveGEOS())
     243             :             {
     244           0 :                 CPLError(
     245             :                     CE_Warning, CPLE_IllegalArg,
     246             :                     "GEOS support not enabled, ignoring option WASP_TOLERANCE");
     247             :             }
     248             :             else
     249             :             {
     250           1 :                 pdfTolerance.reset(new double);
     251           1 :                 if (!(std::istringstream(pszToler) >> *pdfTolerance))
     252             :                 {
     253           0 :                     CPLError(CE_Failure, CPLE_IllegalArg,
     254             :                              "cannot set tolerance from %s", pszToler);
     255           0 :                     return nullptr;
     256             :                 }
     257             :             }
     258             :         }
     259             :     }
     260             : 
     261          24 :     std::unique_ptr<double> pdfAdjacentPointTolerance;
     262             :     {
     263             :         const char *pszAdjToler =
     264          24 :             CSLFetchNameValue(papszOptions, "WASP_ADJ_TOLER");
     265          24 :         if (pszAdjToler)
     266             :         {
     267           0 :             pdfAdjacentPointTolerance.reset(new double);
     268           0 :             if (!(std::istringstream(pszAdjToler) >>
     269           0 :                   *pdfAdjacentPointTolerance))
     270             :             {
     271           0 :                 CPLError(CE_Failure, CPLE_IllegalArg,
     272             :                          "cannot set tolerance from %s", pszAdjToler);
     273           0 :                 return nullptr;
     274             :             }
     275             :         }
     276             :     }
     277             : 
     278          24 :     std::unique_ptr<double> pdfPointToCircleRadius;
     279             :     {
     280             :         const char *pszPtToCircRad =
     281          24 :             CSLFetchNameValue(papszOptions, "WASP_POINT_TO_CIRCLE_RADIUS");
     282          24 :         if (pszPtToCircRad)
     283             :         {
     284           0 :             pdfPointToCircleRadius.reset(new double);
     285           0 :             if (!(std::istringstream(pszPtToCircRad) >>
     286           0 :                   *pdfPointToCircleRadius))
     287             :             {
     288           0 :                 CPLError(CE_Failure, CPLE_IllegalArg,
     289             :                          "cannot set tolerance from %s", pszPtToCircRad);
     290           0 :                 return nullptr;
     291             :             }
     292             :         }
     293             :     }
     294             : 
     295          24 :     OGRSpatialReference *poSRSClone = nullptr;
     296          24 :     if (poSpatialRef)
     297             :     {
     298           3 :         poSRSClone = poSpatialRef->Clone();
     299           3 :         poSRSClone->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     300             :     }
     301          24 :     oLayer.reset(new OGRWAsPLayer(
     302          24 :         this, CPLGetBasename(pszName), hFile, poSRSClone, sFirstField,
     303          24 :         sSecondField, sGeomField, bMerge, pdfTolerance.release(),
     304          24 :         pdfAdjacentPointTolerance.release(), pdfPointToCircleRadius.release()));
     305          24 :     if (poSRSClone)
     306           3 :         poSRSClone->Release();
     307             : 
     308          24 :     char *ppszWktSpatialRef = nullptr;
     309          27 :     if (poSpatialRef &&
     310           3 :         poSpatialRef->exportToProj4(&ppszWktSpatialRef) == OGRERR_NONE)
     311             :     {
     312           3 :         VSIFPrintfL(hFile, "%s\n", ppszWktSpatialRef);
     313             :     }
     314             :     else
     315             :     {
     316          21 :         VSIFPrintfL(hFile, "no spatial ref sys\n");
     317             :     }
     318          24 :     CPLFree(ppszWktSpatialRef);
     319             : 
     320          24 :     VSIFPrintfL(hFile, "  0.0 0.0 0.0 0.0\n");
     321          24 :     VSIFPrintfL(hFile, "  1.0 0.0 1.0 0.0\n");
     322          24 :     VSIFPrintfL(hFile, "  1.0 0.0\n");
     323          24 :     return oLayer.get();
     324             : }

Generated by: LCOV version 1.14