1#include <fcb/generated/geometry_generated.h>
17#define FCB_ASSERT_KIND(name) \
18 static_assert(static_cast<std::uint8_t>(GeometryKind::name) == \
19 static_cast<std::uint8_t>(::GeometryType::name), \
20 "GeometryKind::" #name " has drifted from the generated GeometryType")
32static_assert(
static_cast<std::uint8_t
>(::GeometryType::MAX) ==
34 "geometry.fbs gained a GeometryType; give it a depth in this file");
38[[noreturn]]
void overrun(
const char* what) {
40 std::string(
"geometry boundaries overrun in ") + what);
45nlohmann::json index_to_json(std::uint32_t v) {
57std::uint32_t count_at(
UIntView counts, std::size_t& cursor) {
58 const std::uint32_t n = (cursor < counts.size()) ? counts[cursor] : 0;
77 const std::uint32_t ring_size =
strings[c.ring++];
79 if (c.index > indices.size() || indices.size() - c.index < ring_size) {
82 auto ring = nlohmann::json::array();
83 for (std::uint32_t i = 0; i < ring_size; ++i) {
84 ring.push_back(indices[c.index + i]);
94 const std::uint32_t ring_count =
surfaces[c.surface++];
96 auto surface = nlohmann::json::array();
97 for (std::uint32_t i = 0; i < ring_count; ++i) {
108 const std::uint32_t surface_count =
shells[c.shell++];
110 auto shell = nlohmann::json::array();
111 for (std::uint32_t i = 0; i < surface_count; ++i) {
127 std::size_t
shell = 0;
129 std::size_t
string = 0;
132 nlohmann::json take_ring() {
133 const std::uint32_t size = count_at(
strings,
string);
135 auto ring = nlohmann::json::array();
141 nlohmann::json take_surface() {
142 const std::uint32_t rings = count_at(surfaces, surface);
143 auto out = nlohmann::json::array();
144 for (std::uint32_t i = 0; i < rings; ++i)
145 out.push_back(take_ring());
149 nlohmann::json take_shell() {
150 const std::uint32_t n = count_at(shells, shell);
151 auto out = nlohmann::json::array();
152 for (std::uint32_t i = 0; i < n; ++i)
153 out.push_back(take_surface());
167 auto out = nlohmann::json::array();
172 for (std::size_t i = 0; i < indices.
size(); ++i)
173 out.push_back(indices[i]);
180 out.push_back(take_ring(
strings, indices, c));
195 for (std::size_t i = 0; i < solids.
size(); ++i) {
196 auto solid = nlohmann::json::array();
197 for (std::uint32_t k = 0; k < solids[i]; ++k) {
200 out.push_back(std::move(solid));
217 for (std::size_t i = 0; i <
shells.
size(); ++i) {
226 std::size_t cursor = 0;
227 auto take = [&](std::uint32_t n) {
228 const std::size_t end = std::min(cursor + n, values.
size());
229 auto out = nlohmann::json::array();
230 for (; cursor < end; ++cursor)
231 out.push_back(index_to_json(values[cursor]));
235 auto out = nlohmann::json::array();
239 for (std::size_t i = 0; i <
shells.
size(); ++i)
240 out.push_back(take(
shells[i]));
246 std::size_t shell_cursor = 0;
247 for (std::size_t i = 0; i < solids.
size(); ++i) {
248 auto solid = nlohmann::json::array();
249 for (std::uint32_t k = 0; k < solids[i]; ++k) {
250 solid.push_back(take(count_at(
shells, shell_cursor)));
252 out.push_back(std::move(solid));
261 for (std::size_t i = 0; i < values.
size(); ++i) {
262 out.push_back(index_to_json(values[i]));
271 auto take_shell = [&](std::uint32_t n) {
273 auto out = nlohmann::json::array();
279 auto out = nlohmann::json::array();
281 out.push_back(index_to_json(
vertices[i]));
286 auto out = nlohmann::json::array();
290 for (std::size_t i = 0; i <
shells.
size(); ++i) {
291 if (
shells[i] == UINT32_MAX) {
292 out.push_back(
nullptr);
294 out.push_back(take_shell(
shells[i]));
302 std::size_t shell_cursor = 0;
303 for (std::size_t i = 0; i < solids.
size(); ++i) {
304 if (solids[i] == UINT32_MAX) {
305 out.push_back(
nullptr);
308 auto solid = nlohmann::json::array();
309 for (std::uint32_t k = 0; k < solids[i]; ++k) {
310 const std::uint32_t n = count_at(
shells, shell_cursor);
311 if (n == UINT32_MAX) {
312 solid.push_back(
nullptr);
314 solid.push_back(take_shell(n));
317 out.push_back(std::move(solid));
335 auto out = nlohmann::json::array();
341 out.push_back(c.take_surface());
346 for (std::size_t i = 0; i <
shells.
size(); ++i)
347 out.push_back(c.take_shell());
353 for (std::size_t i = 0; i < solids.
size(); ++i) {
354 auto solid = nlohmann::json::array();
355 for (std::uint32_t k = 0; k < solids[i]; ++k)
356 solid.push_back(c.take_shell());
357 out.push_back(std::move(solid));
366 const std::size_t n = std::max<std::size_t>(
surfaces.
size(), 1);
367 for (std::size_t i = 0; i < n; ++i)
368 out.push_back(c.take_surface());
377 switch (
static_cast<::GeometryType
>(type)) {
378 case ::GeometryType::MultiPoint:
380 case ::GeometryType::MultiLineString:
381 return "MultiLineString";
382 case ::GeometryType::MultiSurface:
383 return "MultiSurface";
384 case ::GeometryType::CompositeSurface:
385 return "CompositeSurface";
386 case ::GeometryType::Solid:
388 case ::GeometryType::MultiSolid:
390 case ::GeometryType::CompositeSolid:
391 return "CompositeSolid";
392 case ::GeometryType::GeometryInstance:
393 return "GeometryInstance";
Every failure the library reports is one of these.
Minimal C++17 stand-in for std::span: a non-owning view over contiguous memory.
std::size_t size() const noexcept
#define FCB_ASSERT_KIND(name)
nlohmann::json decode_boundaries(GeometryKind type, UIntView solids, UIntView shells, UIntView surfaces, UIntView strings, UIntView indices)
Rebuild CityJSON's nested boundaries from the five flattened arrays, at the depth type implies.
nlohmann::json decode_texture_values(GeometryKind type, UIntView solids, UIntView shells, UIntView surfaces, UIntView strings, UIntView vertices)
Rebuild the values array of one texture theme from a TextureMapping.
span< const std::uint32_t > UIntView
nlohmann::json decode_material_values(GeometryKind type, UIntView solids, UIntView shells, UIntView vertices)
Rebuild the values array of one material theme from a MaterialMapping.
nlohmann::json decode_semantics_values(GeometryKind type, UIntView solids, UIntView shells, UIntView values)
Rebuild the nested semantics values array from the flat run of semantic indices.
GeometryKind
The FlatBuffers GeometryType enumerators, mirrored here so a caller can name a geometry type without ...
std::string geometry_type_name(std::uint8_t type)
CityJSON name for a GeometryType enumerator, e.g.