LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/flatgeobuf - geometrywriter.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 141 145 97.2 %
Date: 2024-05-15 13:15:52 Functions: 13 13 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  FlatGeobuf driver
       4             :  * Purpose:  Implements GeometryWriter class.
       5             :  * Author:   Björn Harrtell <bjorn at wololo dot org>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2018-2019, Björn Harrtell <bjorn at wololo dot org>
       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 "geometrywriter.h"
      30             : 
      31             : using namespace flatbuffers;
      32             : using namespace FlatGeobuf;
      33             : using namespace ogr_flatgeobuf;
      34             : 
      35             : GeometryType
      36         249 : GeometryWriter::translateOGRwkbGeometryType(const OGRwkbGeometryType eGType)
      37             : {
      38         249 :     const auto flatType = wkbFlatten(eGType);
      39         249 :     GeometryType geometryType = GeometryType::Unknown;
      40         249 :     if (flatType <= 17)
      41         247 :         geometryType = (GeometryType)flatType;
      42         249 :     return geometryType;
      43             : }
      44             : 
      45         115 : void GeometryWriter::writePoint(const OGRPoint *p)
      46             : {
      47         115 :     m_xy.push_back(p->getX());
      48         115 :     m_xy.push_back(p->getY());
      49         115 :     if (m_hasZ)
      50          25 :         m_z.push_back(p->getZ());
      51         115 :     if (m_hasM)
      52          22 :         m_m.push_back(p->getM());
      53         115 : }
      54             : 
      55           9 : void GeometryWriter::writeMultiPoint(const OGRMultiPoint *mp)
      56             : {
      57          33 :     for (const auto part : *mp)
      58          24 :         if (!part->IsEmpty())
      59          23 :             writePoint(part);
      60           9 : }
      61             : 
      62         176 : uint32_t GeometryWriter::writeSimpleCurve(const OGRSimpleCurve *sc)
      63             : {
      64         176 :     uint32_t numPoints = sc->getNumPoints();
      65         176 :     const auto xyLength = m_xy.size();
      66         176 :     m_xy.resize(xyLength + (numPoints * 2));
      67         176 :     const auto zLength = m_z.size();
      68         176 :     double *padfZOut = nullptr;
      69         176 :     if (m_hasZ)
      70             :     {
      71          73 :         m_z.resize(zLength + numPoints);
      72          73 :         padfZOut = m_z.data() + zLength;
      73             :     }
      74         176 :     const auto mLength = m_m.size();
      75         176 :     double *padfMOut = nullptr;
      76         176 :     if (m_hasM)
      77             :     {
      78          58 :         m_m.resize(mLength + numPoints);
      79          58 :         padfMOut = m_m.data() + mLength;
      80             :     }
      81         176 :     sc->getPoints(reinterpret_cast<double *>(
      82         176 :                       reinterpret_cast<OGRRawPoint *>(m_xy.data() + xyLength)),
      83             :                   sizeof(OGRRawPoint),
      84             :                   reinterpret_cast<double *>(
      85         176 :                       reinterpret_cast<OGRRawPoint *>(m_xy.data() + xyLength)) +
      86             :                       1,
      87             :                   sizeof(OGRRawPoint), padfZOut, sizeof(double), padfMOut,
      88             :                   sizeof(double));
      89         176 :     return numPoints;
      90             : }
      91             : 
      92          13 : void GeometryWriter::writeMultiLineString(const OGRMultiLineString *mls)
      93             : {
      94          13 :     uint32_t e = 0;
      95          37 :     for (const auto part : *mls)
      96          24 :         if (!part->IsEmpty())
      97          23 :             m_ends.push_back(e += writeSimpleCurve(part));
      98          13 : }
      99             : 
     100          78 : void GeometryWriter::writePolygon(const OGRPolygon *p)
     101             : {
     102          78 :     const auto exteriorRing = p->getExteriorRing();
     103          78 :     const auto numInteriorRings = p->getNumInteriorRings();
     104          78 :     uint32_t e = writeSimpleCurve(exteriorRing);
     105             :     // NOTE: should not write ends if only exterior ring
     106          78 :     if (numInteriorRings > 0)
     107             :     {
     108          16 :         m_ends.push_back(e);
     109          32 :         for (int i = 0; i < numInteriorRings; i++)
     110          16 :             m_ends.push_back(e += writeSimpleCurve(p->getInteriorRing(i)));
     111             :     }
     112          78 : }
     113             : 
     114             : const Offset<Geometry>
     115          21 : GeometryWriter::writeMultiPolygon(const OGRMultiPolygon *mp, int depth)
     116             : {
     117          42 :     std::vector<Offset<Geometry>> parts;
     118          55 :     for (const auto part : *mp)
     119          34 :         if (!part->IsEmpty())
     120          33 :             parts.push_back(writePart(part, GeometryType::Polygon, depth + 1));
     121             :     return CreateGeometryDirect(m_fbb, nullptr, nullptr, nullptr, nullptr,
     122          42 :                                 nullptr, nullptr, m_geometryType, &parts);
     123             : }
     124             : 
     125             : const Offset<Geometry>
     126          23 : GeometryWriter::writeGeometryCollection(const OGRGeometryCollection *gc,
     127             :                                         int depth)
     128             : {
     129          46 :     std::vector<Offset<Geometry>> parts;
     130          71 :     for (const auto part : *gc)
     131          48 :         if (!part->IsEmpty())
     132          47 :             parts.push_back(writePart(part, depth + 1));
     133             :     return CreateGeometryDirect(m_fbb, nullptr, nullptr, nullptr, nullptr,
     134          46 :                                 nullptr, nullptr, m_geometryType, &parts);
     135             : }
     136             : 
     137             : const Offset<Geometry>
     138           4 : GeometryWriter::writeCompoundCurve(const OGRCompoundCurve *cc, int depth)
     139             : {
     140           8 :     std::vector<Offset<Geometry>> parts;
     141          12 :     for (const auto curve : *cc)
     142           8 :         parts.push_back(writePart(curve, depth + 1));
     143             :     return CreateGeometryDirect(m_fbb, nullptr, nullptr, nullptr, nullptr,
     144           8 :                                 nullptr, nullptr, m_geometryType, &parts);
     145             : }
     146             : 
     147             : const Offset<Geometry>
     148           8 : GeometryWriter::writeCurvePolygon(const OGRCurvePolygon *cp, int depth)
     149             : {
     150          16 :     std::vector<Offset<Geometry>> parts;
     151          24 :     for (const auto curve : *cp)
     152          16 :         parts.push_back(writePart(curve, depth + 1));
     153             :     return CreateGeometryDirect(m_fbb, nullptr, nullptr, nullptr, nullptr,
     154          16 :                                 nullptr, nullptr, m_geometryType, &parts);
     155             : }
     156             : 
     157             : const Offset<Geometry>
     158           1 : GeometryWriter::writePolyhedralSurface(const OGRPolyhedralSurface *p, int depth)
     159             : {
     160           2 :     std::vector<Offset<Geometry>> parts;
     161           7 :     for (const auto part : *p)
     162           6 :         parts.push_back(writePart(part, depth + 1));
     163             :     return CreateGeometryDirect(m_fbb, nullptr, nullptr, nullptr, nullptr,
     164           2 :                                 nullptr, nullptr, m_geometryType, &parts);
     165             : }
     166             : 
     167           2 : void GeometryWriter::writeTIN(const OGRTriangulatedSurface *ts)
     168             : {
     169           2 :     const auto numGeometries = ts->getNumGeometries();
     170           2 :     if (numGeometries == 1)
     171           1 :         return (void)writeSimpleCurve(ts->getGeometryRef(0)->getExteriorRing());
     172           1 :     uint32_t e = 0;
     173           3 :     for (const auto part : *ts)
     174           2 :         m_ends.push_back(e += writeSimpleCurve(part->getExteriorRing()));
     175             : }
     176             : 
     177         307 : const Offset<Geometry> GeometryWriter::write(int depth)
     178             : {
     179         307 :     bool unknownGeometryType = false;
     180         307 :     if (depth == 0 && m_geometryType == GeometryType::Unknown)
     181             :     {
     182           5 :         m_geometryType =
     183           5 :             translateOGRwkbGeometryType(m_ogrGeometry->getGeometryType());
     184           5 :         unknownGeometryType = true;
     185             :     }
     186         307 :     switch (m_geometryType)
     187             :     {
     188          92 :         case GeometryType::Point:
     189          92 :             writePoint(m_ogrGeometry->toPoint());
     190          92 :             break;
     191           9 :         case GeometryType::MultiPoint:
     192           9 :             writeMultiPoint(m_ogrGeometry->toMultiPoint());
     193           9 :             break;
     194          36 :         case GeometryType::LineString:
     195          36 :             writeSimpleCurve(m_ogrGeometry->toLineString());
     196          36 :             break;
     197          13 :         case GeometryType::MultiLineString:
     198          13 :             writeMultiLineString(m_ogrGeometry->toMultiLineString());
     199          13 :             break;
     200          77 :         case GeometryType::Polygon:
     201          77 :             writePolygon(m_ogrGeometry->toPolygon());
     202          77 :             break;
     203          21 :         case GeometryType::MultiPolygon:
     204          21 :             return writeMultiPolygon(m_ogrGeometry->toMultiPolygon(), depth);
     205          15 :         case GeometryType::GeometryCollection:
     206             :             return writeGeometryCollection(
     207          15 :                 m_ogrGeometry->toGeometryCollection(), depth);
     208          20 :         case GeometryType::CircularString:
     209          20 :             writeSimpleCurve(m_ogrGeometry->toCircularString());
     210          20 :             break;
     211           4 :         case GeometryType::CompoundCurve:
     212           4 :             return writeCompoundCurve(m_ogrGeometry->toCompoundCurve(), depth);
     213           8 :         case GeometryType::CurvePolygon:
     214           8 :             return writeCurvePolygon(m_ogrGeometry->toCurvePolygon(), depth);
     215           4 :         case GeometryType::MultiCurve:
     216           4 :             return writeGeometryCollection(m_ogrGeometry->toMultiCurve(),
     217           4 :                                            depth);
     218           4 :         case GeometryType::MultiSurface:
     219           4 :             return writeGeometryCollection(m_ogrGeometry->toMultiSurface(),
     220           4 :                                            depth);
     221           1 :         case GeometryType::PolyhedralSurface:
     222           1 :             return writePolyhedralSurface(m_ogrGeometry->toPolyhedralSurface(),
     223           1 :                                           depth);
     224           1 :         case GeometryType::Triangle:
     225           1 :             writePolygon(m_ogrGeometry->toTriangle());
     226           1 :             break;
     227           2 :         case GeometryType::TIN:
     228           2 :             writeTIN(m_ogrGeometry->toTriangulatedSurface());
     229           2 :             break;
     230           0 :         default:
     231           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     232             :                      "GeometryWriter::write: Unknown type %d",
     233           0 :                      (int)m_geometryType);
     234           0 :             return 0;
     235             :     }
     236         250 :     const auto pEnds = m_ends.empty() ? nullptr : &m_ends;
     237         250 :     const auto pXy = m_xy.empty() ? nullptr : &m_xy;
     238         250 :     const auto pZ = m_z.empty() ? nullptr : &m_z;
     239         250 :     const auto pM = m_m.empty() ? nullptr : &m_m;
     240         148 :     const auto geometryType = depth > 0 || unknownGeometryType
     241         398 :                                   ? m_geometryType
     242             :                                   : GeometryType::Unknown;
     243             :     return FlatGeobuf::CreateGeometryDirect(m_fbb, pEnds, pXy, pZ, pM, nullptr,
     244         250 :                                             nullptr, geometryType);
     245             : }

Generated by: LCOV version 1.14