ReUseX  0.0.5
3D Point Cloud Processing for Building Reuse
Loading...
Searching...
No Matches
ProjectDB.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025 Povl Filip Sonne-Frederiksen
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#pragma once
6// Point-cloud aliases (Cloud/CloudN/CloudL and pcl::PointCloud<pcl::PointXYZ>)
7// are part of the public signatures below, so the point-type header stays.
8// The heavier OpenCV and PCL mesh headers are only needed by the .cpp: they
9// are forward-declared here (cv::Mat by value/reference, mesh types via
10// std::shared_ptr) to keep DB clients from transitively compiling them.
11#include "reusex/core/component_record.hpp"
12#include "reusex/types/point_types.hpp"
13
14#include <array>
15#include <cstdint>
16#include <filesystem>
17#include <map>
18#include <memory>
19#include <optional>
20#include <string>
21#include <string_view>
22#include <vector>
23
24// Forward declarations for heavy third-party types used only by-value or via
25// shared_ptr in the public API (definitions pulled in by ProjectDB.cpp).
26namespace cv {
27class Mat;
28} // namespace cv
29namespace pcl {
30struct PolygonMesh;
31struct TextureMesh;
32} // namespace pcl
33
34namespace reusex {
35
36// Forward declarations
37namespace core {
38struct MaterialPassport;
39struct MaterialPassportMetadata;
40struct SensorIntrinsics;
41} // namespace core
42
43class ProjectDB {
44 public:
68 explicit ProjectDB(std::filesystem::path dbPath, bool readOnly = false);
73
74 // Non-copyable (RAII resource management)
75 ProjectDB(const ProjectDB &) = delete;
76 ProjectDB &operator=(const ProjectDB &) = delete;
77
78 // Movable
79 ProjectDB(ProjectDB &&) noexcept;
80 ProjectDB &operator=(ProjectDB &&) noexcept;
81
82 // --- Core Database Operations ---
83
84 bool is_open() const noexcept;
85 const std::filesystem::path &path() const noexcept;
86 int schema_version() const;
87 void validate_schema() const;
88
89 // --- Sensor Frame Operations ---
90
91 void save_sensor_frame(int nodeId, const cv::Mat &colorImage);
92
93 void save_sensor_frame(int nodeId, const cv::Mat &color, const cv::Mat &depth,
94 const cv::Mat &confidence,
95 const std::array<double, 16> &worldPose,
96 const core::SensorIntrinsics &intrinsics,
97 double timestamp = -1.0);
98
104 const std::array<double, 16> &worldPose);
105
106 std::vector<int> sensor_frame_ids() const;
107 cv::Mat sensor_frame_image(int nodeId) const;
108 cv::Mat sensor_frame_depth(int nodeId) const;
109 cv::Mat sensor_frame_confidence(int nodeId) const;
126 std::array<double, 16> sensor_frame_pose(int nodeId) const;
127
139 bool has_sensor_frame_pose(int nodeId) const;
140
141 core::SensorIntrinsics sensor_frame_intrinsics(int nodeId) const;
142 bool has_sensor_frame(int nodeId) const;
143
146 double sensor_frame_timestamp(int nodeId) const;
147
150 int nearest_sensor_frame_by_timestamp(double timestamp) const;
151
152 // --- Panoramic Image Operations ---
153
155 int id;
156 std::string filename;
157 double timestamp; // -1.0 if unknown
158 int node_id; // -1 if unmatched
159 // Refined 6-DoF pose from content-based alignment (`rux align 360`). When
160 // has_pose is false the panorama has only its timestamp-matched frame pose.
161 bool has_pose = false;
162 std::array<double, 16> pose = {1, 0, 0, 0, 0, 1, 0, 0,
163 0, 0, 1, 0, 0, 0, 0, 1}; // row-major world
164 std::string pose_source = "timestamp"; // "timestamp" | "aligned"
165 int align_inliers = -1; // RANSAC inliers, -1 if not aligned
166 // Angular RMS of the inlier bearings after resection, in degrees
167 // (PanoramaAlignmentResult::rms_deg). -1 if not aligned.
168 double align_rms = -1.0;
169 };
170
171 void save_panoramic_image(const std::string &filename,
172 const std::vector<uint8_t> &jpeg_data,
173 double timestamp = -1.0, int nodeId = -1);
174
175 cv::Mat panoramic_image(int id) const;
176 cv::Mat panoramic_image(std::string_view filename) const;
177 bool has_panoramic_image(std::string_view filename) const;
179 void delete_panoramic_image(std::string_view filename);
180 std::vector<PanoramicImage> list_panoramic_images() const;
182
184 void save_panorama_pose(int id, const std::array<double, 16> &pose,
185 int inliers, double rms);
186
187 // --- Panorama Segmentation Operations ---
188
189 bool has_panorama_segmentation(int panoId) const;
190 cv::Mat panorama_segmentation(int panoId) const;
191 void save_panorama_segmentation(int panoId, const cv::Mat &labels);
192
193 // --- Segmentation Image Operations ---
194
195 bool has_segmentation_image(int nodeId) const;
196 cv::Mat segmentation_image(int nodeId) const;
197 std::vector<int> segmentation_image_ids() const;
198 void save_segmentation_image(int nodeId, const cv::Mat &labels);
199 void save_segmentation_images(const std::vector<int> &nodeIds,
200 const std::vector<cv::Mat> &labels);
201
202 // --- Point Cloud Operations ---
203
204 void save_point_cloud(std::string_view name, const Cloud &cloud,
205 std::string_view stage = "",
206 std::string_view paramsJson = "");
207
208 void save_point_cloud(std::string_view name, const CloudN &cloud,
209 std::string_view stage = "",
210 std::string_view paramsJson = "");
211
212 void save_point_cloud(std::string_view name, const CloudL &cloud,
213 std::string_view stage = "",
214 std::string_view paramsJson = "");
215
216 void save_point_cloud(std::string_view name,
217 const pcl::PointCloud<pcl::PointXYZ> &cloud,
218 std::string_view stage = "",
219 std::string_view paramsJson = "");
220
221 CloudPtr point_cloud_xyzrgb(std::string_view name) const;
222 CloudNPtr point_cloud_normal(std::string_view name) const;
223 CloudLPtr point_cloud_label(std::string_view name) const;
224 pcl::PointCloud<pcl::PointXYZ>::Ptr
225 point_cloud_xyz(std::string_view name) const;
226
227 bool has_point_cloud(std::string_view name) const;
228 void delete_point_cloud(std::string_view name);
229 std::vector<std::string> list_point_clouds() const;
230 std::string point_cloud_type(std::string_view name) const;
231
234 struct CloudPage {
236 std::string point_type;
237 uint32_t point_step = 0;
238 uint64_t offset = 0;
239 uint64_t count = 0;
240 uint64_t total = 0;
242 std::vector<uint8_t> data;
243 };
244
265 CloudPage point_cloud_page(std::string_view name, uint64_t offset,
266 uint64_t limit) const;
267
268 // --- Label Definitions ---
269
270 void save_label_definitions(std::string_view cloudName,
271 const std::map<int, std::string> &labelMap);
272
273 std::map<int, std::string>
274 label_definitions(std::string_view cloudName) const;
275
276 // --- Instances (stable identity) ---
277
281 uint32_t instance_id = 0;
282 std::string guid;
283 int semantic_class = -1;
284 int point_count = 0;
285 };
286
290 void save_instances(const std::string &cloud_name,
291 const std::vector<InstanceRecord> &records);
292
294 std::vector<InstanceRecord> instances(const std::string &cloud_name) const;
295
298 std::string instance_guid(const std::string &cloud_name,
299 uint32_t instance_id) const;
300
301 // --- Instance ↔ Material Links ---
302
309 void set_instance_material(std::string_view cloudName, int instanceId,
310 std::string_view materialGuid);
311
313 std::optional<std::string> instance_material_guid(std::string_view cloudName,
314 int instanceId) const;
315
317 std::map<int, std::string>
318 instance_materials(std::string_view cloudName) const;
319
320 // --- Mesh Operations ---
321
322 void save_mesh(std::string_view name, const pcl::PolygonMesh &mesh,
323 std::string_view stage = "", std::string_view paramsJson = "");
324
325 void save_mesh(std::string_view name, const pcl::TextureMesh &mesh,
326 std::string_view stage = "", std::string_view paramsJson = "");
327
328 std::shared_ptr<pcl::PolygonMesh> mesh(std::string_view name) const;
329 std::shared_ptr<pcl::TextureMesh> texture_mesh(std::string_view name) const;
330 bool has_mesh(std::string_view name) const;
331 std::vector<std::string> list_meshes() const;
332 std::string mesh_format(std::string_view name) const;
333
337 };
338 MeshMetadata mesh_metadata(std::string_view name) const;
339
340 std::vector<uint8_t> mesh_data_blob(std::string_view name) const;
341
343 std::string tex_name, format;
344 std::vector<uint8_t> image_data;
346 };
347 std::vector<MeshTextureInfo> mesh_texture_blobs(std::string_view name) const;
348
350 std::string tex_name, format;
352 };
353 std::vector<MeshTextureMetadata>
354 mesh_texture_metadata(std::string_view name) const;
355
356 // --- Gaussian Splat Operations ---
357 //
358 // A trained splat is stored verbatim, as the INRIA `.ply` bytes, chunked
359 // across `gaussian_splat_data` rows the same way point clouds are: a splat
360 // is routinely hundreds of MB and SQLite materializes a whole blob column
361 // on read, so a single-row layout would cost peak memory proportional to
362 // the entire file even to answer "how many Gaussians".
363 //
364 // The bytes are opaque to core — nothing here inflates a splat into a
365 // geometry type. What core *does* own is the guarantee that the bytes are a
366 // splat at all: `save_gaussian_splat()` parses the PLY header
367 // (core/gaussian_splat.hpp) and refuses anything else, so the point-cloud
368 // PLY that `rux export ply` writes is rejected at the door instead of
369 // reaching a renderer that would draw nothing and say nothing.
370
373 std::string name;
374 std::string format;
375 std::uint64_t gaussian_count = 0;
376 int sh_degree = 0;
377 std::uint64_t byte_size = 0;
378 std::string created_at;
379 std::string stage;
380 std::string parameters;
381 };
382
393 void save_gaussian_splat(std::string_view name,
394 const std::vector<uint8_t> &ply,
395 std::string_view stage = "",
396 std::string_view parameters = "");
397
401 bool has_gaussian_splat(std::string_view name) const;
402
405 std::vector<std::string> list_gaussian_splats() const;
406
408 GaussianSplatMetadata gaussian_splat_metadata(std::string_view name) const;
409
413 std::vector<uint8_t> gaussian_splat_blob(std::string_view name) const;
414
417 bool delete_gaussian_splat(std::string_view name);
418
419 // --- Building Component Operations ---
420 //
421 // Persistence speaks only core::ComponentRecord (see
422 // reusex/core/component_record.hpp), so core stays free of geometry types
423 // (#227). To store/load a geometry::BuildingComponent, use the mapping and
424 // convenience free functions in reusex/geometry/component_persistence.hpp.
425
435 core::ComponentRecord component_record(std::string_view name) const;
436 bool has_building_component(std::string_view name) const;
437 void delete_building_component(std::string_view name);
438 std::vector<std::string> list_building_components() const;
440 std::vector<std::string>
441 list_building_components(std::string_view type) const;
443
444 // --- Pipeline Log ---
445
446 int log_pipeline_start(std::string_view stage,
447 std::string_view paramsJson = "");
448
449 void log_pipeline_end(int logId, bool success,
450 std::string_view errorMsg = "");
451
453 int id;
454 std::string stage;
455 std::string started_at;
456 std::string finished_at; // Empty if still running
457 std::string parameters; // JSON string
458 std::string status; // "running", "success", "failed"
459 std::string error_msg; // Empty if no error
460 };
461
462 std::vector<PipelineLogEntry> pipeline_log(int limit = 0) const;
463
464 // --- Project Summary ---
465
467 struct CloudInfo {
468 std::string name;
469 std::string type; // "PointXYZRGB", "Normal", "Label", "PointXYZ"
471 size_t width;
472 size_t height;
473 bool organized; // height > 1
474 std::map<int, std::string> labels; // Only for Label clouds
475 };
476
477 struct MeshInfo {
478 std::string name;
481 };
482
485 int width; // 0 if no frames
486 int height; // 0 if no frames
487 int segmented_count; // frames with segmentation
488 };
489
491 int total_count = 0;
492 int matched_count = 0; // images linked to a sensor frame
493 };
494
496 int total_count = 0;
497 std::map<std::string, int> count_by_type;
498 };
499
501 std::string id;
502 std::string guid;
504 std::string created_at; // ISO 8601 timestamp
505 std::string version_number; // Semver (e.g., "0.1.1")
506 };
507
508 struct ProjectInfo {
509 std::string id;
510 std::string name;
511 std::string building_address;
512 int year_of_construction = 0; // 0 = not set
513 std::string survey_date;
515 std::string notes;
516 };
517
518 std::filesystem::path path;
520 std::vector<ProjectInfo> projects;
521 std::vector<CloudInfo> clouds;
522 std::vector<MeshInfo> meshes;
525 std::vector<GaussianSplatMetadata> gaussian_splats;
529 std::vector<MaterialInfo> materials;
530 };
531
533
534 // --- Material Passport Operations ---
535
536 core::MaterialPassport material_passport(std::string_view documentGuid) const;
537 std::vector<core::MaterialPassport> all_material_passports() const;
538
540 std::string_view projectId);
541
554 std::string_view projectId, std::string_view id);
555
561 void delete_material_passport(std::string_view documentGuid);
562
567 std::vector<std::string> list_passport_guids() const;
568
580 std::map<std::string, std::string>
581 passport_stored_properties(std::string_view documentGuid) const;
582
590 std::string passport_property_value(std::string_view documentGuid,
591 std::string_view fieldName) const;
592
607 std::optional<int>
608 passport_linked_node_id(std::string_view documentGuid) const;
609
617 passport_metadata(std::string_view documentGuid) const;
618
630 void set_passport_metadata_field(std::string_view documentGuid,
631 std::string_view column,
632 std::string_view value);
633
646 void set_passport_property(std::string_view documentGuid,
647 std::string_view fieldName,
648 std::string_view value);
649
656 void delete_passport_property(std::string_view documentGuid,
657 std::string_view fieldName);
658
659 // --- Project Metadata Operations ---
660
662 std::string id;
663 std::string name;
664 std::string building_address;
665 int year_of_construction = 0; // 0 = not set
666 std::string survey_date;
668 std::string notes;
669 };
670
677 ProjectMetadata get_project_metadata(std::string_view projectId) const;
678
685
690 std::vector<std::string> list_project_ids() const;
691
692 private:
693 class Impl;
694 std::unique_ptr<Impl> impl_;
695};
696} // namespace reusex
double sensor_frame_timestamp(int nodeId) const
Get the timestamp (epoch seconds) of a sensor frame.
int log_pipeline_start(std::string_view stage, std::string_view paramsJson="")
std::string point_cloud_type(std::string_view name) const
bool has_point_cloud(std::string_view name) const
bool delete_gaussian_splat(std::string_view name)
Deleting the metadata row cascades to its data chunks.
std::vector< uint8_t > mesh_data_blob(std::string_view name) const
void add_material_passport(const core::MaterialPassport &passport, std::string_view projectId)
bool has_sensor_frame_pose(int nodeId) const
True when this frame carries a usable stored world pose.
std::map< int, std::string > instance_materials(std::string_view cloudName) const
All instance_id → material_guid links for a cloud.
ProjectDB(const ProjectDB &)=delete
void save_point_cloud(std::string_view name, const pcl::PointCloud< pcl::PointXYZ > &cloud, std::string_view stage="", std::string_view paramsJson="")
std::shared_ptr< pcl::TextureMesh > texture_mesh(std::string_view name) const
bool has_segmentation_image(int nodeId) const
void log_pipeline_end(int logId, bool success, std::string_view errorMsg="")
std::vector< std::string > list_building_components() const
CloudLPtr point_cloud_label(std::string_view name) const
std::vector< std::string > list_building_components(std::string_view type) const
Names of the components whose stored type discriminator equals type.
ProjectDB & operator=(const ProjectDB &)=delete
int nearest_sensor_frame_by_timestamp(double timestamp) const
Find the sensor frame with the closest timestamp to the given value.
std::array< double, 16 > sensor_frame_pose(int nodeId) const
The stored world pose, verbatim — row-major 4x4, identity when the row is missing,...
std::vector< PipelineLogEntry > pipeline_log(int limit=0) const
std::vector< MeshTextureMetadata > mesh_texture_metadata(std::string_view name) const
void add_material_passport(const core::MaterialPassport &passport, std::string_view projectId, std::string_view id)
Add a material passport with a custom row ID.
void save_panoramic_image(const std::string &filename, const std::vector< uint8_t > &jpeg_data, double timestamp=-1.0, int nodeId=-1)
bool has_mesh(std::string_view name) const
std::vector< std::string > list_passport_guids() const
List document GUIDs ordered by created_at.
std::shared_ptr< pcl::PolygonMesh > mesh(std::string_view name) const
void set_passport_metadata_field(std::string_view documentGuid, std::string_view column, std::string_view value)
Set a metadata column on a material passport.
void delete_panoramic_image(std::string_view filename)
void save_point_cloud(std::string_view name, const Cloud &cloud, std::string_view stage="", std::string_view paramsJson="")
std::vector< int > sensor_frame_ids() const
void save_instances(const std::string &cloud_name, const std::vector< InstanceRecord > &records)
Replace the full set of instance rows for a cloud (transactional).
std::vector< std::string > list_gaussian_splats() const
Empty on a pre-v12 schema, for the same reason as has_gaussian_splat().
ProjectSummary project_summary() const
std::vector< core::MaterialPassport > all_material_passports() const
core::MaterialPassport material_passport(std::string_view documentGuid) const
void save_segmentation_image(int nodeId, const cv::Mat &labels)
int schema_version() const
void save_segmentation_images(const std::vector< int > &nodeIds, const std::vector< cv::Mat > &labels)
int building_component_count() const
ProjectDB(std::filesystem::path dbPath, bool readOnly=false)
Opens a ReUseX project database and validates its schema.
bool is_open() const noexcept
void delete_building_component(std::string_view name)
void save_mesh(std::string_view name, const pcl::TextureMesh &mesh, std::string_view stage="", std::string_view paramsJson="")
std::optional< int > passport_linked_node_id(std::string_view documentGuid) const
Return the sensor frame node_id this passport was linked to.
cv::Mat sensor_frame_confidence(int nodeId) const
void delete_point_cloud(std::string_view name)
GaussianSplatMetadata gaussian_splat_metadata(std::string_view name) const
cv::Mat sensor_frame_image(int nodeId) const
int panoramic_image_count() const
cv::Mat panoramic_image(std::string_view filename) const
std::map< int, std::string > label_definitions(std::string_view cloudName) const
std::vector< InstanceRecord > instances(const std::string &cloud_name) const
All instance rows for a cloud, ordered by instance_id.
bool has_panoramic_image(std::string_view filename) const
cv::Mat segmentation_image(int nodeId) const
std::vector< std::string > list_project_ids() const
List all project IDs in the database.
void save_panorama_segmentation(int panoId, const cv::Mat &labels)
void save_point_cloud(std::string_view name, const CloudL &cloud, std::string_view stage="", std::string_view paramsJson="")
std::string passport_property_value(std::string_view documentGuid, std::string_view fieldName) const
Get a single passport property value by field name.
std::vector< PanoramicImage > list_panoramic_images() const
core::ComponentRecord component_record(std::string_view name) const
Load the component row with the given name. Throws if absent.
void save_point_cloud(std::string_view name, const CloudN &cloud, std::string_view stage="", std::string_view paramsJson="")
CloudPtr point_cloud_xyzrgb(std::string_view name) const
MeshMetadata mesh_metadata(std::string_view name) const
CloudNPtr point_cloud_normal(std::string_view name) const
bool has_sensor_frame(int nodeId) const
void validate_schema() const
void update_project_metadata(const ProjectMetadata &metadata)
Update project metadata.
std::vector< MeshTextureInfo > mesh_texture_blobs(std::string_view name) const
std::map< std::string, std::string > passport_stored_properties(std::string_view documentGuid) const
Get stored property field_name→string pairs for a passport.
bool has_gaussian_splat(std::string_view name) const
False — not an error — on a project whose schema predates the splat tables, which is what a read-only...
bool has_building_component(std::string_view name) const
const std::filesystem::path & path() const noexcept
std::vector< std::string > list_point_clouds() const
void save_gaussian_splat(std::string_view name, const std::vector< uint8_t > &ply, std::string_view stage="", std::string_view parameters="")
Store an INRIA-format 3DGS .ply under name, replacing any splat already stored under it (chunks of th...
void delete_panoramic_image(int id)
void set_passport_property(std::string_view documentGuid, std::string_view fieldName, std::string_view value)
Set a single property value by field name (upsert).
std::string mesh_format(std::string_view name) const
void save_mesh(std::string_view name, const pcl::PolygonMesh &mesh, std::string_view stage="", std::string_view paramsJson="")
std::optional< std::string > instance_material_guid(std::string_view cloudName, int instanceId) const
Material passport guid linked to an instance, or nullopt if unlinked.
std::vector< uint8_t > gaussian_splat_blob(std::string_view name) const
The stored bytes, reassembled from their chunks — byte-for-byte what save_gaussian_splat() was given.
~ProjectDB()
Destructor closes database connection.
bool has_panorama_segmentation(int panoId) const
core::SensorIntrinsics sensor_frame_intrinsics(int nodeId) const
cv::Mat panoramic_image(int id) const
core::MaterialPassportMetadata passport_metadata(std::string_view documentGuid) const
Get passport metadata without loading all properties.
pcl::PointCloud< pcl::PointXYZ >::Ptr point_cloud_xyz(std::string_view name) const
void set_instance_material(std::string_view cloudName, int instanceId, std::string_view materialGuid)
Link an instance (a row in the instances table) to a material passport by its document guid.
void delete_passport_property(std::string_view documentGuid, std::string_view fieldName)
Delete a single property value by field name.
void update_sensor_frame_pose(int nodeId, const std::array< double, 16 > &worldPose)
Update only the stored world pose (transform) of an existing sensor frame.
cv::Mat panorama_segmentation(int panoId) const
void save_panorama_pose(int id, const std::array< double, 16 > &pose, int inliers, double rms)
Store a content-aligned pose (row-major 4x4 world) for a panorama.
std::vector< int > segmentation_image_ids() const
void save_component_record(const core::ComponentRecord &record)
Insert or replace the component row identified by record.name.
cv::Mat sensor_frame_depth(int nodeId) const
std::vector< std::string > list_meshes() const
void save_sensor_frame(int nodeId, const cv::Mat &colorImage)
CloudPage point_cloud_page(std::string_view name, uint64_t offset, uint64_t limit) const
Read one page of a point cloud without materializing the cloud.
void update_component_record_by_guid(const core::ComponentRecord &record)
Update an existing component's mutable fields (name, type, parent_id, confidence, metadata,...
ProjectDB(ProjectDB &&) noexcept
std::string instance_guid(const std::string &cloud_name, uint32_t instance_id) const
Stable GUID of a single instance.
ProjectMetadata get_project_metadata(std::string_view projectId) const
Get project metadata by project ID.
void delete_material_passport(std::string_view documentGuid)
Delete a material passport by GUID.
void save_label_definitions(std::string_view cloudName, const std::map< int, std::string > &labelMap)
typename CloudN::Ptr CloudNPtr
pcl::PointCloud< PointT > Cloud
typename CloudL::Ptr CloudLPtr
typename Cloud::Ptr CloudPtr
pcl::PointCloud< LabelT > CloudL
pcl::PointCloud< NormalT > CloudN
A contiguous window of one cloud's stored records, still in storage layout — no PCL type has been inf...
uint64_t total
Points in the whole cloud.
uint64_t count
Points actually read.
uint32_t point_step
Bytes per stored record.
std::string point_type
"PointXYZRGB" | "PointXYZ" | "Normal" | "Label".
std::vector< uint8_t > data
count * point_step bytes, exactly as stored.
uint64_t offset
First point index, clamped to total.
One row of the gaussian_splats table, minus the payload.
std::uint64_t byte_size
Size of the stored .ply, in bytes.
std::string format
"ply" (INRIA 3DGS layout) — the only one today.
std::string stage
Pipeline stage that produced it, may be empty.
int sh_degree
Derived from the f_rest_* count.
std::string parameters
JSON provenance, may be empty.
One row of the instances table: a spatially-distinct object within an instance-label cloud,...
int point_count
Number of points in the instance.
std::string guid
Stable identity (UUID-v4-like).
uint32_t instance_id
Label value in the instance cloud (>= 1).
int semantic_class
Semantic class this instance belongs to.
std::vector< uint8_t > image_data
std::array< double, 16 > pose
std::map< int, std::string > labels
std::vector< CloudInfo > clouds
std::vector< ProjectInfo > projects
std::vector< MaterialInfo > materials
std::vector< GaussianSplatMetadata > gaussian_splats
Metadata only — the summary never carries a splat's payload, which is routinely hundreds of MB.
std::vector< MeshInfo > meshes
Core-owned persistence contract for a row of the building_components table (#227).
Document-level metadata for the material passport.
A complete material passport for a reused building material.