LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/openfilegdb - filegdb_coordprec_write.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 52 54 96.3 %
Date: 2024-11-21 22:18:42 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements Open FileGDB OGR driver.
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #ifndef FILEGDB_COORDPREC_WRITE_H
      14             : #define FILEGDB_COORDPREC_WRITE_H
      15             : 
      16             : #include "ogr_spatialref.h"
      17             : #include "ogr_geomcoordinateprecision.h"
      18             : 
      19             : /*************************************************************************/
      20             : /*                      GDBGridSettingsFromOGR()                         */
      21             : /*************************************************************************/
      22             : 
      23             : /** Compute grid settings from coordinate precision of source geometry field
      24             :  * and layer creation options.
      25             :  * The "FileGeodatabase" key of the output oFormatSpecificOptions will be
      26             :  * set with the values.
      27             :  */
      28             : static OGRGeomCoordinatePrecision
      29         333 : GDBGridSettingsFromOGR(const OGRGeomFieldDefn *poSrcGeomFieldDefn,
      30             :                        CSLConstList aosLayerCreationOptions)
      31             : {
      32         333 :     const auto poSRS = poSrcGeomFieldDefn->GetSpatialRef();
      33             : 
      34             :     double dfXOrigin;
      35             :     double dfYOrigin;
      36             :     double dfXYScale;
      37         333 :     double dfZOrigin = -100000;
      38         333 :     double dfMOrigin = -100000;
      39         333 :     double dfMScale = 10000;
      40             :     double dfXYTolerance;
      41             :     // default tolerance is 1mm in the units of the coordinate system
      42             :     double dfZTolerance =
      43         333 :         0.001 * (poSRS ? poSRS->GetTargetLinearUnits("VERT_CS") : 1.0);
      44         333 :     double dfZScale = 1 / dfZTolerance * 10;
      45         333 :     double dfMTolerance = 0.001;
      46             : 
      47         333 :     if (poSRS == nullptr || poSRS->IsProjected())
      48             :     {
      49             :         // default tolerance is 1mm in the units of the coordinate system
      50         196 :         dfXYTolerance =
      51         196 :             0.001 * (poSRS ? poSRS->GetTargetLinearUnits("PROJCS") : 1.0);
      52             :         // default scale is 10x the tolerance
      53         196 :         dfXYScale = 1 / dfXYTolerance * 10;
      54             : 
      55             :         // Ideally we would use the same X/Y origins as ArcGIS, but we need
      56             :         // the algorithm they use.
      57         196 :         dfXOrigin = -2147483647;
      58         196 :         dfYOrigin = -2147483647;
      59             :     }
      60             :     else
      61             :     {
      62         137 :         dfXOrigin = -400;
      63         137 :         dfYOrigin = -400;
      64         137 :         dfXYScale = 1000000000;
      65         137 :         dfXYTolerance = 0.000000008983153;
      66             :     }
      67             : 
      68         333 :     const auto &oSrcCoordPrec = poSrcGeomFieldDefn->GetCoordinatePrecision();
      69             : 
      70         333 :     if (oSrcCoordPrec.dfXYResolution != OGRGeomCoordinatePrecision::UNKNOWN)
      71             :     {
      72          10 :         dfXYScale = 1.0 / oSrcCoordPrec.dfXYResolution;
      73          10 :         dfXYTolerance = oSrcCoordPrec.dfXYResolution / 10.0;
      74             :     }
      75             : 
      76         333 :     if (oSrcCoordPrec.dfZResolution != OGRGeomCoordinatePrecision::UNKNOWN)
      77             :     {
      78          10 :         dfZScale = 1.0 / oSrcCoordPrec.dfZResolution;
      79          10 :         dfZTolerance = oSrcCoordPrec.dfZResolution / 10.0;
      80             :     }
      81             : 
      82         333 :     if (oSrcCoordPrec.dfMResolution != OGRGeomCoordinatePrecision::UNKNOWN)
      83             :     {
      84          10 :         dfMScale = 1.0 / oSrcCoordPrec.dfMResolution;
      85          10 :         dfMTolerance = oSrcCoordPrec.dfMResolution / 10.0;
      86             :     }
      87             : 
      88         333 :     const char *const paramNames[] = {
      89             :         "XOrigin", "YOrigin", "XYScale",     "ZOrigin",    "ZScale",
      90             :         "MOrigin", "MScale",  "XYTolerance", "ZTolerance", "MTolerance"};
      91             :     double *pGridValues[] = {
      92             :         &dfXOrigin, &dfYOrigin, &dfXYScale,     &dfZOrigin,    &dfZScale,
      93         333 :         &dfMOrigin, &dfMScale,  &dfXYTolerance, &dfZTolerance, &dfMTolerance};
      94             :     static_assert(CPL_ARRAYSIZE(paramNames) == CPL_ARRAYSIZE(pGridValues));
      95             : 
      96             :     const auto oIterCoordPrecFileGeodatabase =
      97         333 :         oSrcCoordPrec.oFormatSpecificOptions.find("FileGeodatabase");
      98             : 
      99             :     /*
     100             :      * Use coordinate precision layer creation options in priority.
     101             :      * Otherwise use the settings from the "FileGeodatabase" entry in
     102             :      * oSrcCoordPrec.oFormatSpecificOptions when set.
     103             :      * Otherwise, use above defaults.
     104             :      */
     105         666 :     CPLStringList aosCoordinatePrecisionOptions;
     106        3663 :     for (size_t i = 0; i < CPL_ARRAYSIZE(paramNames); i++)
     107             :     {
     108        3330 :         const char *pszVal = CSLFetchNameValueDef(
     109        3330 :             aosLayerCreationOptions, paramNames[i],
     110        3330 :             oIterCoordPrecFileGeodatabase !=
     111        3330 :                     oSrcCoordPrec.oFormatSpecificOptions.end()
     112         160 :                 ? oIterCoordPrecFileGeodatabase->second.FetchNameValue(
     113          80 :                       paramNames[i])
     114             :                 : nullptr);
     115        3330 :         if (pszVal)
     116             :         {
     117         292 :             *(pGridValues[i]) = CPLAtof(pszVal);
     118         292 :             if (strstr(paramNames[i], "Scale") ||
     119         215 :                 strstr(paramNames[i], "Tolerance"))
     120             :             {
     121         154 :                 if (*(pGridValues[i]) <= 0)
     122             :                 {
     123           0 :                     CPLError(CE_Warning, CPLE_AppDefined,
     124             :                              "%s should be strictly greater than zero",
     125           0 :                              paramNames[i]);
     126             :                 }
     127             :             }
     128             :         }
     129             :         aosCoordinatePrecisionOptions.SetNameValue(
     130        3330 :             paramNames[i], CPLSPrintf("%.15g", *(pGridValues[i])));
     131             :     }
     132             : 
     133         333 :     OGRGeomCoordinatePrecision oCoordPrec;
     134         333 :     oCoordPrec.dfXYResolution = 1.0 / dfXYScale;
     135         333 :     oCoordPrec.dfZResolution = 1.0 / dfZScale;
     136         333 :     oCoordPrec.dfMResolution = 1.0 / dfMScale;
     137         666 :     oCoordPrec.oFormatSpecificOptions["FileGeodatabase"] =
     138         666 :         std::move(aosCoordinatePrecisionOptions);
     139             : 
     140         666 :     return oCoordPrec;
     141             : }
     142             : 
     143             : #endif /* FILEGDB_COORDPREC_WRITE_H */

Generated by: LCOV version 1.14