Skip to content

Commit

Permalink
fix(wkb): add support for Solid and MultiSolid with correct WKB codes…
Browse files Browse the repository at this point in the history
… 25/26

Previously, the WKB export did not support `Solid` and `MultiSolid`, as these
geometries are not commonly found in existing standards. However, WKT export
was already implemented for both types. According to the ISO/IEC 13249-3:2016
standard, the code 102 is assigned to `AffinePlacement`, and while `ST_SOLID`
is not instantiable, `SOLID` is the name used in (City)GML, corresponding to
`ST_BRepSolid`.

Our implementation of `Solid` aligns with `ST_BRepSolid`, which consists of
shells (represented as `PolyhedralSurface` in our case;
`PolyhedralSurface` + `CompoundSurface` in the standard).
However, the WKB code is not officially listed for `BRepSolid`, except for
`BRepSolidZ` with the code `<wkbbrepsolidz> 1025`.

This implies that the regular code for `BRepSolid` should be 25
(with 1000 added for the Z coordinate). Additionally, since `MultiSolid` has no
existing WKB code, we propose assigning the code 26, as it is currently
available.
Thus, we move from the previous 101/102 to 25/26, ensuring we use the correct
WKB code for `Solid` (BRepSolid).
  • Loading branch information
lbartoletti committed Oct 10, 2024
1 parent e782b2c commit 1685149
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 6 deletions.
4 changes: 2 additions & 2 deletions src/Geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ enum GeometryType {
TYPE_TRIANGLE = 17,

//-- not official codes
TYPE_SOLID = 101,
TYPE_MULTISOLID = 102
TYPE_SOLID = 25,
TYPE_MULTISOLID = 26
};

/**
Expand Down
23 changes: 23 additions & 0 deletions src/detail/io/WkbReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,27 @@ WkbReader::readInnerPolyhedralSurface() -> PolyhedralSurface
return result;
}

/**
* Read Solid content from wkb
*/
auto
WkbReader::readInnerSolid() -> Solid
{
std::vector<PolyhedralSurface> geoms;
try {
const uint32_t numGeoms{read<uint32_t>()};
for (uint32_t i = 0; i < numGeoms; ++i) {
readWkb();
if (_geometry != nullptr) {
geoms.push_back(_geometry->as<SFCGAL::PolyhedralSurface>());
}
}
} catch (std::exception &e) {
std::cerr << e.what();
return {};
}
SFCGAL::Solid const result{geoms};
return result;
}

} // namespace SFCGAL::detail::io
15 changes: 15 additions & 0 deletions src/detail/io/WkbReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
#include "SFCGAL/MultiLineString.h"
#include "SFCGAL/MultiPoint.h"
#include "SFCGAL/MultiPolygon.h"
#include "SFCGAL/MultiSolid.h"
#include "SFCGAL/Point.h"
#include "SFCGAL/Polygon.h"
#include "SFCGAL/PolyhedralSurface.h"
#include "SFCGAL/PreparedGeometry.h"
#include "SFCGAL/Solid.h"
#include "SFCGAL/Triangle.h"
#include "SFCGAL/TriangulatedSurface.h"

Expand Down Expand Up @@ -227,6 +229,13 @@ class SFCGAL_API WkbReader {
return std::unique_ptr<SFCGAL::Geometry>(
readInnerPolyhedralSurface().clone());

case TYPE_SOLID:
return std::unique_ptr<SFCGAL::Geometry>(readInnerSolid().clone());

case TYPE_MULTISOLID:
return std::unique_ptr<SFCGAL::Geometry>(
readInnerMultiGeometries<MultiSolid, Solid>().clone());

default:
std::ostringstream oss;
oss << "WkbWriter: type '" << geometryType << "' is not supported";
Expand Down Expand Up @@ -295,6 +304,12 @@ class SFCGAL_API WkbReader {
auto
readInnerPolyhedralSurface() -> PolyhedralSurface;

/**
* Read Solid content from wkb
*/
auto
readInnerSolid() -> Solid;

/**
* actually reading 3D ?
*/
Expand Down
26 changes: 22 additions & 4 deletions src/detail/io/WkbWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
#include "SFCGAL/MultiLineString.h"
#include "SFCGAL/MultiPoint.h"
#include "SFCGAL/MultiPolygon.h"
#include "SFCGAL/MultiSolid.h"
#include "SFCGAL/Point.h"
#include "SFCGAL/Polygon.h"
#include "SFCGAL/PolyhedralSurface.h"
#include "SFCGAL/Solid.h"
#include "SFCGAL/Triangle.h"
#include "SFCGAL/TriangulatedSurface.h"

Expand Down Expand Up @@ -71,6 +73,14 @@ WkbWriter::writeRec(const Geometry &g, boost::endian::order wkbOrder)
writeInner<PolyhedralSurface, Polygon>(g.as<PolyhedralSurface>(), wkbOrder);
return;

case TYPE_SOLID:
writeInner<Solid, PolyhedralSurface>(g.as<Solid>(), wkbOrder);
return;

case TYPE_MULTISOLID:
writeInner<MultiSolid, Solid>(g.as<MultiSolid>(), wkbOrder);
return;

default:
std::ostringstream oss;
oss << "WkbWriter: type '" << g.geometryType() << "' is not supported";
Expand Down Expand Up @@ -278,11 +288,19 @@ WkbWriter::writeInner(const M &g, boost::endian::order wkbOrder)
// WkbType
writeGeometryType(g, wkbOrder);

// Number of Geometries
toByte(static_cast<uint32_t>(g.numGeometries()), wkbOrder);
// Number of Geometries/Shells
if constexpr (std::is_same<M, Solid>::value) {
toByte(static_cast<uint32_t>(g.numShells()), wkbOrder);

for (size_t i = 0; i < g.numGeometries(); i++) {
writeInner(g.geometryN(i).template as<G>(), wkbOrder);
for (size_t i = 0; i < g.numShells(); i++) {
writeRec(g.shellN(i).template as<G>(), wkbOrder);
}
} else {
toByte(static_cast<uint32_t>(g.numGeometries()), wkbOrder);

for (size_t i = 0; i < g.numGeometries(); i++) {
writeRec(g.geometryN(i).template as<G>(), wkbOrder);
}
}
}

Expand Down
19 changes: 19 additions & 0 deletions test/unit/SFCGAL/io/WkbWriterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,23 @@ BOOST_AUTO_TEST_CASE(PostgisEWkb)
}
}
}

BOOST_AUTO_TEST_CASE(SolidWKB)
{
std::string cube{"SOLID((((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0)),((1 0 0,1 1 0,1 1 "
"1,1 0 1,1 0 0)),((0 1 0,0 1 1,1 1 1,1 1 0,0 1 0)),((0 0 "
"1,0 1 1,0 1 0,0 0 0,0 0 1)),((1 0 1,1 1 1,0 1 1,0 0 1,1 0 "
"1)),((1 0 0,1 0 1,0 0 1,0 0 0,1 0 0))))"};

std::unique_ptr<Geometry> g(io::readWkt(cube));
auto wkbBinary = g->asWkb();
std::unique_ptr<Geometry> g2(io::readWkb(wkbBinary));
BOOST_CHECK_EQUAL(g->asText(0), g2->asText(0));

/*
wkbBinary = g->asWkb(boost::endian::order::native, true);
std::cerr << wkbBinary << "\n";
*/
}

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 1685149

Please sign in to comment.