LCOV - code coverage report
Current view: top level - frmts/netcdf - netcdfsg.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 50 73 68.5 %
Date: 2024-05-04 12:52:34 Functions: 20 29 69.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  netCDF read/write Driver
       4             :  * Purpose:  GDAL bindings over netCDF library.
       5             :  * Author:   Winor Chen <wchen329 at wisc.edu>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2019, Winor Chen <wchen329 at wisc.edu>
       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             : #ifndef __NETCDFSG_H__
      29             : #define __NETCDFSG_H__
      30             : #include <cstring>
      31             : #include <memory>
      32             : #include <set>
      33             : #include <string>
      34             : #include <vector>
      35             : #include "netcdf.h"
      36             : 
      37             : // Interface used for netCDF functions
      38             : // implementing awareness for the CF-1.8 convention
      39             : //
      40             : // Author: wchen329
      41             : namespace nccfdriver
      42             : {
      43             : // Constants
      44             : const int INVALID_VAR_ID = -2;
      45             : const int INVALID_DIM_ID = INVALID_VAR_ID;
      46             : 
      47             : // Enum used for easily identifying Geometry types
      48             : enum geom_t
      49             : {
      50             :     NONE,          // no geometry found
      51             :     POLYGON,       // OGRPolygon
      52             :     MULTIPOLYGON,  // OGRMultipolygon
      53             :     LINE,          // OGRLineString
      54             :     MULTILINE,     // OGRMultiLineString
      55             :     POINT,         // OGRPoint
      56             :     MULTIPOINT,    // OGRMultiPoint
      57             :     UNSUPPORTED    // Unsupported feature type
      58             : };
      59             : 
      60             : // Concrete "Point" class, holds n dimensional double precision floating point
      61             : // value, defaults to all zero values
      62             : class Point
      63             : {
      64             :     int size;
      65             :     std::unique_ptr<double, std::default_delete<double[]>> values;
      66             :     Point(Point &);
      67             :     Point operator=(const Point &);
      68             : 
      69             :   public:
      70          72 :     explicit Point(int dim)
      71          72 :         : size(dim),
      72             :           values(std::unique_ptr<double, std::default_delete<double[]>>(
      73          72 :               new double[dim]))
      74             :     {
      75          72 :     }
      76             : 
      77      269842 :     double &operator[](size_t i)
      78             :     {
      79      269842 :         return this->values.get()[i];
      80             :     }
      81             : 
      82             :     int getOrder()
      83             :     {
      84             :         return this->size;
      85             :     }
      86             : };
      87             : 
      88             : // Simple geometry - doesn't actually hold the points, rather serves
      89             : // as a pseudo reference to a NC variable
      90             : class SGeometry_Reader
      91             : {
      92             :     std::string container_name_s;  // name of the underlying geometry container
      93             :     geom_t type;                   // internal geometry type structure
      94             :     int ncid;                      // ncid - as used in netcdf.h
      95             :     int gc_varId;  // the id of the underlying geometry_container variable
      96             :     std::string gm_name_s;  // grid mapping variable name
      97             :     int gm_varId;           // id used for grid mapping
      98             :     int inst_dimId;         // dimension id for geometry instance dimension
      99             :     size_t inst_dimLen;     // value of instance dimension
     100             :     int touple_order;       // amount of "coordinates" in a point
     101             :     std::vector<int> nodec_varIds;  // varIds for each node_coordinate entry
     102             :     std::vector<int>
     103             :         node_counts;  // node counts of each geometry in a container
     104             :     std::vector<int>
     105             :         pnode_counts;  // part node counts of each geometry in a container
     106             :     std::vector<bool> int_rings;     // list of parts that are interior rings
     107             :     std::vector<size_t> bound_list;  // a quick list used to store the real
     108             :                                      // beginning indices of shapes
     109             :     std::vector<size_t> pnc_bl;      // a quick list of indices for part counts
     110             :                                      // corresponding to a geometry
     111             :     std::vector<int>
     112             :         parts_count;  // a count of total parts in a single geometry instance
     113             :     std::vector<int> poly_count;       // count of polygons, for use only when
     114             :                                        // interior rings are present
     115             :     std::unique_ptr<Point> pt_buffer;  // holds the current point
     116             :     SGeometry_Reader(SGeometry_Reader &);
     117             :     SGeometry_Reader operator=(const SGeometry_Reader &);
     118             : 
     119             :   public:
     120             :     /* int SGeometry_Reader::get_ncID()
     121             :      * return the group/file ID that the SGeometry object is operating over
     122             :      */
     123          96 :     int get_ncID()
     124             :     {
     125          96 :         return ncid;
     126             :     }
     127             : 
     128             :     /* int SGeometry_Reader::get_axisCount()
     129             :      * Returns the count of axis (i.e. X, Y, Z)
     130             :      */
     131       68289 :     int get_axisCount()
     132             :     {
     133       68289 :         return this->touple_order;
     134             :     }
     135             : 
     136             :     /* int SGeometry_Reader::getInstDim()
     137             :      * Returns the geometry instance dimension ID of this geometry
     138             :      */
     139         492 :     int getInstDim()
     140             :     {
     141         492 :         return this->inst_dimId;
     142             :     }
     143             : 
     144             :     /* size_t SGeometry_Reader::getInstDimLen()
     145             :      * Returns the length of the instance dimension
     146             :      */
     147             :     size_t getInstDimLen()
     148             :     {
     149             :         return this->inst_dimLen;
     150             :     }
     151             : 
     152             :     /* std::string& getGridMappingName()
     153             :      * returns the variable name which holds grid mapping data
     154             :      */
     155          48 :     std::string &getGridMappingName()
     156             :     {
     157          48 :         return this->gm_name_s;
     158             :     }
     159             : 
     160             :     /* int SGeometry_Reader::getGridMappingVarID();
     161             :      * returns the varID of the associated grid mapping variable ID
     162             :      */
     163          72 :     int getGridMappingVarID()
     164             :     {
     165          72 :         return this->gm_varId;
     166             :     }
     167             : 
     168             :     /* geom_t getGeometryType()
     169             :      * Retrieves the associated geometry type with this geometry
     170             :      */
     171        1548 :     geom_t getGeometryType()
     172             :     {
     173        1548 :         return this->type;
     174             :     }
     175             : 
     176             :     /* void SGeometry_Reader::get_geometry_count()
     177             :      * returns a size, indicating the amount of geometries
     178             :      * contained in the variable
     179             :      */
     180             :     size_t get_geometry_count();
     181             : 
     182             :     /* const char* SGeometry_Reader::getContainerName()
     183             :      * Returns the container name as a string
     184             :      */
     185             :     std::string &getContainerName()
     186             :     {
     187             :         return container_name_s;
     188             :     }
     189             : 
     190             :     /* int SGeometry_Reader::getContainerId()
     191             :      * Get the ncID of the geometry_container variable
     192             :      */
     193          72 :     int getContainerId()
     194             :     {
     195          72 :         return gc_varId;
     196             :     }
     197             : 
     198             :     /* std::vector<unsigned char> serializeToWKB
     199             :      * Returns a pre-allocated array which serves as the WKB reference to this
     200             :      * geometry
     201             :      */
     202             :     std::vector<unsigned char> serializeToWKB(size_t featureInd);
     203             : 
     204             :     /* Return a point at a specific index specifically
     205             :      * this point should NOT be explicitly freed.
     206             :      *
     207             :      */
     208             :     Point &operator[](size_t ind);
     209             : 
     210             :     /* std::vector<int>& getNodeCoordVars
     211             :      * Returns a vector with the node coord vars in X, Y, Z (if present) order
     212             :      */
     213          96 :     std::vector<int> &getNodeCoordVars()
     214             :     {
     215          96 :         return this->nodec_varIds;
     216             :     }
     217             : 
     218             :     /* ncID - as used in netcdf.h
     219             :      * baseVarId - the id of a variable with a geometry container attribute
     220             :      */
     221             :     SGeometry_Reader(int ncId, int baseVarId);
     222             : };
     223             : 
     224             : /* SGeometry_PropertyScanner
     225             :  * Holds names of properties for geometry containers
     226             :  * Pass in the geometry_container ID, automatically scans the netcdf Dataset for
     227             :  * properties associated
     228             :  *
     229             :  * to construct: pass in the ncid which the reader should work over
     230             :  */
     231             : class SGeometry_PropertyScanner
     232             : {
     233             :     std::vector<int> v_ids;
     234             :     std::vector<std::string> v_headers;
     235             :     int nc;
     236             : 
     237             :     void open(int container_id);  // opens and initializes a geometry_container
     238             :                                   // into the scanner
     239             : 
     240             :   public:
     241             :     std::vector<std::string> &headers()
     242             :     {
     243             :         return this->v_headers;
     244             :     }
     245             : 
     246          71 :     std::vector<int> &ids()
     247             :     {
     248          71 :         return this->v_ids;
     249             :     }
     250             : 
     251          72 :     SGeometry_PropertyScanner(int ncid, int cid) : nc(ncid)
     252             :     {
     253          72 :         this->open(cid);
     254          72 :     }
     255             : };
     256             : 
     257             : // General exception interface for Simple Geometries
     258             : // Whatever pointer returned should NOT be freed- it will be deconstructed
     259             : // automatically, if needed
     260             : class SG_Exception
     261             : {
     262             :   public:
     263             :     virtual const char *get_err_msg() = 0;
     264             :     virtual ~SG_Exception();
     265             : };
     266             : 
     267             : // Mismatched dimension exception
     268             : class SG_Exception_Dim_MM : public SG_Exception
     269             : {
     270             :     std::string err_msg;
     271             : 
     272             :   public:
     273           1 :     const char *get_err_msg() override
     274             :     {
     275           1 :         return err_msg.c_str();
     276             :     }
     277             : 
     278             :     SG_Exception_Dim_MM(const char *geometry_container, const char *field_1,
     279             :                         const char *field_2);
     280             : };
     281             : 
     282             : // Missing (existential) property error
     283             : class SG_Exception_Existential : public SG_Exception
     284             : {
     285             :     std::string err_msg;
     286             : 
     287             :   public:
     288           2 :     const char *get_err_msg() override
     289             :     {
     290           2 :         return err_msg.c_str();
     291             :     }
     292             : 
     293             :     SG_Exception_Existential(const char *geometry_container,
     294             :                              const char *missing_name);
     295             : };
     296             : 
     297             : // Missing dependent property (arg_1 is dependent on arg_2)
     298             : class SG_Exception_Dep : public SG_Exception
     299             : {
     300             :     std::string err_msg;
     301             : 
     302             :   public:
     303           0 :     const char *get_err_msg() override
     304             :     {
     305           0 :         return err_msg.c_str();
     306             :     }
     307             : 
     308             :     SG_Exception_Dep(const char *geometry_container, const char *arg_1,
     309             :                      const char *arg_2);
     310             : };
     311             : 
     312             : // The sum of all values in a variable does not match the sum of another
     313             : // variable
     314             : class SG_Exception_BadSum : public SG_Exception
     315             : {
     316             :     std::string err_msg;
     317             : 
     318             :   public:
     319           0 :     const char *get_err_msg() override
     320             :     {
     321           0 :         return err_msg.c_str();
     322             :     }
     323             : 
     324             :     SG_Exception_BadSum(const char *geometry_container, const char *arg_1,
     325             :                         const char *arg_2);
     326             : };
     327             : 
     328             : // Unsupported Feature Type
     329             : class SG_Exception_BadFeature : public SG_Exception
     330             : {
     331             :     std::string err_msg;
     332             : 
     333             :   public:
     334           1 :     const char *get_err_msg() override
     335             :     {
     336           1 :         return err_msg.c_str();
     337             :     }
     338             : 
     339           1 :     SG_Exception_BadFeature()
     340           1 :         : err_msg("Unsupported or unrecognized feature type.")
     341             :     {
     342           1 :     }
     343             : };
     344             : 
     345             : // Failed Read
     346             : class SG_Exception_BadPoint : public SG_Exception
     347             : {
     348             :     std::string err_msg;
     349             : 
     350             :   public:
     351           0 :     const char *get_err_msg() override
     352             :     {
     353           0 :         return err_msg.c_str();
     354             :     }
     355             : 
     356           0 :     SG_Exception_BadPoint()
     357           0 :         : err_msg("An attempt was made to read an invalid point (likely index "
     358           0 :                   "out of bounds).")
     359             :     {
     360           0 :     }
     361             : };
     362             : 
     363             : // Too many dimensions on node coordinates variable
     364             : class SG_Exception_Not1D : public SG_Exception
     365             : {
     366             :     std::string err_msg;
     367             : 
     368             :   public:
     369           0 :     const char *get_err_msg() override
     370             :     {
     371           0 :         return err_msg.c_str();
     372             :     }
     373             : 
     374           0 :     SG_Exception_Not1D()
     375           0 :         : err_msg("A node coordinates axis variable or node_counts is not one "
     376           0 :                   "dimensional.")
     377             :     {
     378           0 :     }
     379             : };
     380             : 
     381             : // Too many empty dimension
     382             : class SG_Exception_EmptyDim : public SG_Exception
     383             : {
     384             :     std::string err_msg;
     385             : 
     386             :   public:
     387           0 :     const char *get_err_msg() override
     388             :     {
     389           0 :         return err_msg.c_str();
     390             :     }
     391             : 
     392           0 :     SG_Exception_EmptyDim()
     393           0 :         : err_msg("A dimension has length <= 0, but it must have length > 0")
     394             :     {
     395           0 :     }
     396             : };
     397             : 
     398             : // general corruption or malformed error
     399             : class SG_Exception_General_Malformed : public SG_Exception
     400             : {
     401             :     std::string err_msg;
     402             : 
     403             :   public:
     404           0 :     const char *get_err_msg() override
     405             :     {
     406           0 :         return err_msg.c_str();
     407             :     }
     408             : 
     409             :     explicit SG_Exception_General_Malformed(const char *);
     410             : };
     411             : 
     412             : // Invalid value detected
     413             : class SG_Exception_Value_Violation : public SG_Exception
     414             : {
     415             :     std::string err_msg;
     416             : 
     417             :   public:
     418           2 :     const char *get_err_msg() override
     419             :     {
     420           2 :         return err_msg.c_str();
     421             :     }
     422             : 
     423           2 :     SG_Exception_Value_Violation(const char *containername, const char *type,
     424             :                                  const char *badvalue)
     425           4 :         : err_msg(std::string("[") + std::string(containername) +
     426           8 :                   std::string("] ") + std::string(type) +
     427           6 :                   std::string(" values may not be ") + std::string(badvalue))
     428             :     {
     429           2 :     }
     430             : };
     431             : 
     432             : // Required value(s)
     433             : class SG_Exception_Value_Required : public SG_Exception
     434             : {
     435             :     std::string err_msg;
     436             : 
     437             :   public:
     438           1 :     const char *get_err_msg() override
     439             :     {
     440           1 :         return err_msg.c_str();
     441             :     }
     442             : 
     443           1 :     SG_Exception_Value_Required(const char *containername, const char *type,
     444             :                                 const char *expvalue)
     445           2 :         : err_msg(std::string("[") + std::string(containername) +
     446           4 :                   std::string("] ") + std::string(type) +
     447           3 :                   std::string(" values must be ") + std::string(expvalue))
     448             :     {
     449           1 :     }
     450             : };
     451             : 
     452             : // Some helpers which simply call some netcdf library functions, unless
     453             : // otherwise mentioned, ncid, refers to its use in netcdf.h
     454             : 
     455             : /* Retrieves the version from the value Conventions global attr
     456             :  * Returns: a double precision decimal corresponding to the conventions value
     457             :  *    if not CF-x.y then return negative value, -1
     458             :  */
     459             : double getCFVersion(int ncid);
     460             : 
     461             : /* Given a geometry_container varID, searches that variable for a geometry_type
     462             :  * attribute Returns: the equivalent geometry type
     463             :  */
     464             : geom_t getGeometryType(int ncid, int varid);
     465             : 
     466             : void inPlaceSerialize_Point(SGeometry_Reader *ge, size_t seek_pos,
     467             :                             std::vector<unsigned char> &buffer);
     468             : void inPlaceSerialize_LineString(SGeometry_Reader *ge, int node_count,
     469             :                                  size_t seek_begin,
     470             :                                  std::vector<unsigned char> &buffer);
     471             : void inPlaceSerialize_PolygonExtOnly(SGeometry_Reader *ge, int node_count,
     472             :                                      size_t seek_begin,
     473             :                                      std::vector<unsigned char> &buffer);
     474             : void inPlaceSerialize_Polygon(SGeometry_Reader *ge, std::vector<int> &pnc,
     475             :                               int ring_count, size_t seek_begin,
     476             :                               std::vector<unsigned char> &buffer);
     477             : 
     478             : /* scanForGeometryContainers
     479             :  * A simple function that scans a netCDF File for Geometry Containers
     480             :  * -
     481             :  * Scans the given ncid for geometry containers
     482             :  * The vector passed in will be overwritten with a vector of scan results
     483             :  */
     484             : int scanForGeometryContainers(int ncid, std::set<int> &r_ids);
     485             : 
     486             : /* Attribute Fetch
     487             :  * -
     488             :  * A function which makes it a bit easier to fetch single text attribute values
     489             :  * ncid: as used in netcdf.h
     490             :  * varID: variable id in which to look for the attribute
     491             :  * attrName: name of attribute to fine
     492             :  * alloc: a reference to a string that will be filled with the attribute (i.e.
     493             :  * truncated and filled with the return value) Returns: a reference to the
     494             :  * string to fill (a.k.a. string pointed to by alloc reference)
     495             :  */
     496             : std::string &attrf(int ncid, int varId, const char *attrName,
     497             :                    std::string &alloc);
     498             : }  // namespace nccfdriver
     499             : 
     500             : #endif

Generated by: LCOV version 1.14