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

Generated by: LCOV version 1.14