|
ReUseX
0.0.5
3D Point Cloud Processing for Building Reuse
|
Namespaces | |
| namespace | cgal |
| namespace | detail |
| Internals of detect_loop_edges, exposed ONLY so the geometry stages of the pipeline can be regression-tested without a database and without RGB-D fixtures (docs/STANDARDS.md §7; same rationale as plane_factor_consistent_residual() in PlaneGraphOptimizer.cpp). | |
| namespace | se3 |
| Minimal se(3) exp/log used by the joint pose optimizer. | |
Classes | |
| struct | AccuracyMetricsOptions |
| Options for ground-truth accuracy scoring. More... | |
| struct | AccuracyReport |
| Ground-truth accuracy report for a reconstructed point cloud. More... | |
| struct | BuildingComponent |
| A detected or manual building component (window, door, wall, ...). More... | |
| struct | CameraData |
| Camera data for texture mapping. More... | |
| class | CellComplex |
| struct | CellData |
| struct | CellEdgeData |
| struct | CellVertexData |
| struct | CoplanarPolygon |
| A closed 3D polygon whose vertices are coplanar. More... | |
| struct | CreateWindowsOptions |
| Configuration for the create_windows pipeline. More... | |
| struct | CreateWindowsResult |
| Output of create_windows(). More... | |
| struct | DensifyParams |
| Parameters for Multi-View Stereo dense reconstruction (OpenMVS). More... | |
| struct | DoorData |
| struct | FaceData |
| struct | FrameSurfels |
| A sensor frame represented as a surfel set for joint registration. More... | |
| class | JointPairwiseRegistration |
| Joint pairwise pose optimizer operating purely in memory. More... | |
| struct | JprParams |
| Parameters for joint pairwise pose refinement. More... | |
| struct | JprResult |
| Summary statistics from a registration run. More... | |
| struct | LoopClosureOptions |
| Parameters for wide-baseline loop-edge detection. More... | |
| struct | LoopClosureResult |
| Summary statistics from loop-edge detection. More... | |
| struct | LoopEdge |
| A metric relative-pose constraint between two frames, ready to become a gtsam::BetweenFactor<Pose3>. More... | |
| struct | MeshOptions |
| Options for mesh generation. More... | |
| struct | NoiseEstimate |
| Result of estimate_cloud_noise. More... | |
| struct | NoiseEstimateOptions |
| Options controlling the deterministic local-PCA cloud-noise estimator. More... | |
| struct | OdometryEdgeMotion |
| Seed motion of one consecutive-frame odometry edge. More... | |
| struct | OdometrySigmaScale |
| Multiplicative scale applied to an odometry edge's base sigmas. More... | |
| struct | OrphanedInstance |
| A previous instance whose GUID could not be matched to any new instance. More... | |
| struct | PanoramaAlignmentOptions |
| Parameters for content-based panorama alignment. More... | |
| struct | PanoramaAlignmentResult |
| Outcome of aligning one panorama. More... | |
| struct | PanoramaLoopOptions |
| Parameters for panorama-derived loop-edge detection. More... | |
| struct | PanoramaLoopResult |
| Statistics from panorama loop-edge detection. More... | |
| struct | PerspectiveView |
| A virtual pinhole view rendered out of an equirectangular panorama. More... | |
| struct | PlaneFitQuality |
| Fit statistics of one per-frame plane detection: the inputs from which the measurement noise of its OrientedPlane3Factor is derived. More... | |
| struct | PlaneFitSigmas |
| Statistical standard deviations of a plane fit, in the units of the OrientedPlane3Factor residual. More... | |
| class | PlaneGraphOptimizer |
| Plane-landmark pose-graph optimizer operating purely in memory. More... | |
| struct | PlaneGraphOptions |
| Parameters for plane-landmark pose-graph optimization. More... | |
| struct | PlaneGraphResult |
| Summary statistics from a plane-graph optimization run. More... | |
| struct | PlaneQuality |
| Quality statistics for a single detected plane. More... | |
| struct | PointCluster |
| struct | PoseDriftOptions |
| Parameters for synthetic trajectory drift (#338). More... | |
| struct | PoseDriftResult |
| What a drift-synthesis run did, in the units the benchmark reports. More... | |
| struct | PriorInstance |
| Prior instance state (typically loaded from ProjectDB::instances()). More... | |
| struct | QualityMetricsOptions |
| struct | QualityReport |
| Ground-truth-free reconstruction quality report. More... | |
| struct | ReconciledInstance |
| A single reconciled instance: its (new) label value, the semantic class it belongs to, its point count, and the stable GUID it should carry. More... | |
| struct | ReconcileOptions |
| Options controlling instance identity reconciliation. More... | |
| struct | ReconcileResult |
| Result of reconciling a freshly-segmented instance set against a previous one. More... | |
| struct | ReconstructionParams |
| Parameters for point cloud reconstruction from stored sensor frames. More... | |
| class | Registry |
| struct | SceneEdgeData |
| class | SceneGraph |
| struct | SceneObject |
| struct | ScenePlane |
| struct | SceneVertexData |
| struct | SectionSolveStats |
| Per-section solve diagnostics (issue #226). More... | |
| struct | SegmentInstancesRequest |
| Request structure for instance segmentation via Euclidean clustering. More... | |
| struct | SegmentInstancesResult |
| Result structure for instance segmentation. More... | |
| struct | SegmentPlanesOptions |
| struct | SegmentRoomsOptions |
| class | Solidifier |
| Solidifier solves room segmentation using Mixed Integer Programming. More... | |
| struct | SolidifierOptions |
| struct | SurfelExtractionParams |
| Parameters controlling per-frame surfel extraction (back-projection + normal estimation) used by the registration pipeline. More... | |
| struct | SyncDownsampleOptions |
| Options controlling a synchronized project-cloud downsample. More... | |
| struct | SyncDownsampleResult |
| Outcome of a synchronized downsample, for logging / reporting. More... | |
| struct | TextureQualityParams |
| Quality parameters for texture projection. More... | |
| struct | VertexProperties |
| struct | VoxelAssignment |
| Per-input-point assignment to an output voxel bucket. More... | |
| struct | WallCandidate |
| A connected component of coplanar mesh faces that may host a window. More... | |
| struct | WallData |
| struct | WindowData |
Typedefs | |
| using | ResolveInstanceGuidFn = std::function<std::string(uint32_t)> |
| Resolves the stable GUID of an instance from its integer label id. | |
| template<typename Scalar> | |
| using | Plane = Eigen::Matrix<Scalar, 4, 1> |
| template<typename Scalar> | |
| using | PlaneVector |
Enumerations | |
| enum class | ComponentType { window , door , wall } |
| Discriminator for building component types. More... | |
| enum class | CellNodeType { cell , face , vertex } |
| enum class | WindowBoundaryMode { rectangle , polyline } |
| How to compute the window boundary polygon. More... | |
| enum class | SceneNodeType { point_cluster , plane , object } |
| enum class | SolveStatus { not_solved , optimal , feasible , infeasible , unbounded , time_limit , iteration_limit , numerical_error , error } |
| Backend-agnostic classification of the last MIP solve outcome. More... | |
| enum class | SolverChoice { automatic , cuopt , highs } |
| Which MIP backend the Solidifier should use for each (sub)problem. More... | |
| enum class | LoopProposal { automatic , spatial , appearance , exhaustive } |
| How loop-candidate frame pairs are proposed before geometric verification. More... | |
| enum class | PlaneNoiseModel { uniform , inlier_count , fit_geometry } |
| How the measurement noise of an individual plane observation is chosen. More... | |
| enum class | OdometryNoiseModel { fixed , motion } |
| How the per-edge measurement noise of the consecutive-frame odometry BetweenFactors is derived (#225 odometry-trust experiment). More... | |
Functions | |
| std::string_view | to_string (ComponentType type) |
| ComponentType | component_type_from_string (std::string_view str) |
| std::string | component_data_to_json (const BuildingComponent &c) |
| Serialize the type-specific variant data to JSON TEXT. | |
| void | component_data_from_json (BuildingComponent &c, const std::string &json) |
| Deserialize JSON TEXT into the variant data on a BuildingComponent. | |
| core::ComponentRecord | to_component_record (const BuildingComponent &component) |
| Flatten a component into the persistence POD. | |
| BuildingComponent | from_component_record (const core::ComponentRecord &record) |
| Rebuild a component from the persistence POD. | |
| void | save_building_component (ProjectDB &db, const BuildingComponent &component) |
| Insert or replace component, keyed by its name. | |
| void | update_building_component_by_guid (ProjectDB &db, const BuildingComponent &component) |
| Update an existing component's mutable fields, matched by its immutable guid. | |
| BuildingComponent | building_component (const ProjectDB &db, std::string_view name) |
| Load the component stored under name. Throws if absent. | |
| std::vector< std::string > | list_building_components (const ProjectDB &db, ComponentType type) |
| Names of all stored components of the given type. | |
| Eigen::Vector3d | pixel_to_bearing (const cv::Size &equirect, double u, double v) |
| Equirect pixel (u,v) -> unit bearing in the panorama frame. | |
| Eigen::Vector2d | bearing_to_pixel (const cv::Size &equirect, const Eigen::Vector3d &bearing) |
| Unit bearing (need not be normalised) in panorama frame -> equirect pixel (u,v). | |
| PerspectiveView | extract_perspective (const cv::Mat &equirect, double yaw_deg, double pitch_deg, double fov_deg, int out_w, int out_h, int interp=1) |
| Render a virtual pinhole view centred at (yaw,pitch) with the given horizontal FOV. | |
| PerspectiveView | extract_perspective (const cv::Mat &equirect, const Eigen::Matrix3d &R_pano_from_view, const Eigen::Matrix3d &K, int out_w, int out_h, int interp=1) |
| Render a virtual pinhole view with an explicit view->panorama rotation and intrinsics. | |
| std::vector< PerspectiveView > | cube_faces (const cv::Mat &equirect, int face_size, int interp=1) |
| Tile the whole sphere as the six faces of a cube (90 deg FOV each). | |
| std::vector< PerspectiveView > | overlapping_views (const cv::Mat &equirect, int n_yaw, double fov_deg, int tile, int interp=1) |
Tile the sphere as n_yaw evenly spaced views around the equator plus one up and one down view, each with fov_deg horizontal FOV and tile pixels square. | |
| cv::Mat | stitch_labels_to_equirect (const cv::Size &out, const std::vector< PerspectiveView > &views, const std::vector< cv::Mat > &tile_labels) |
Stitch per-tile label maps (CV_32S, -1 = background) back into a single equirect label map of size out. | |
| Eigen::Affine3f | to_affine (const std::array< double, 16 > &m) |
| Build a 4x4 Eigen affine (float) from a row-major double[16] array. | |
| std::array< double, 16 > | to_array16 (const Eigen::Affine3f &aff) |
| Flatten a 4x4 Eigen affine (float) into a row-major double[16] array. | |
| pcl::PolygonMeshPtr | unweld_mesh (const pcl::PolygonMesh &mesh, float threshold_radians) |
| Unweld (split) mesh vertices along sharp edges. | |
| auto | dist_plane_point (const Eigen::Vector4d &plane, const Eigen::Vector3d &point) -> double |
| Calculate distance from a point to a plane. | |
| auto | make_pairs (EigenVectorContainer< double, 4 > &planes, std::vector< IndicesPtr > &inliers, EigenVectorContainer< double, 3 > ¢roids, const double threshold=0.6, const double new_plane_offset=0.5) -> std::vector< std::pair< size_t, size_t > > |
| Create pairs of opposite parallel planes. | |
| auto | force_orthogonal_planes (EigenVectorContainer< double, 4 > &planes, const double threshold=0.1, const Eigen::Matrix< double, 3, 1 > &up=Eigen::Matrix< double, 3, 1 >(0, 0, 1)) -> EigenVectorContainer< double, 4 > |
| Force planes to be orthogonal to a reference direction. | |
| auto | compute_number_of_inliers (CloudConstPtr cloud, Eigen::Vector4d const &plane, IndicesConstPtr indices, const float threshold=0.2) -> size_t |
| Count number of inliers for a plane. | |
| auto | merge_planes (EigenVectorContainer< double, 4 > const &planes_, std::vector< IndicesPtr > const &inliers_, EigenVectorContainer< double, 3 > const ¢roids_, CloudConstPtr cloud, const double angle_threshold=0.1, const double distance_threshold=0.5) -> std::tuple< EigenVectorContainer< double, 4 >, std::vector< IndicesPtr >, EigenVectorContainer< double, 3 > > |
| Merge similar planes based on angle and distance. | |
| auto | separate_planes (const EigenVectorContainer< double, 4 > &planes, const Eigen::Vector3d &up=Eigen::Vector3d(0, 0, 1), const double epsilon=0.1) -> std::tuple< std::vector< size_t >, std::vector< size_t > > |
| Separate planes into horizontal and vertical based on up vector. | |
| template<typename CloudPtr> | |
| auto | compute_polygon_normal (const pcl::Vertices &poly, const CloudPtr &cloud) -> Eigen::Vector3f |
| Compute the normal vector of a polygon. | |
| AccuracyReport | compute_accuracy (const Cloud &cloud, const CloudLoc >, const AccuracyMetricsOptions &opt={}) |
| Score a reconstructed cloud against a ground-truth point cloud. | |
| std::vector< WallCandidate > | extract_wall_candidates (const pcl::PolygonMesh &mesh, float normal_z_threshold=kWallVerticalityGateOff, float coplanarity_angle_deg=10.0f) |
| Extract planar wall candidates from a triangle mesh. | |
| CreateWindowsResult | create_windows (CloudConstPtr cloud, CloudLConstPtr instance_labels, const std::map< uint32_t, uint32_t > &instance_to_semantic, const pcl::PolygonMesh &mesh, const std::vector< uint32_t > &window_semantic_labels, const CreateWindowsOptions &options={}, const ResolveInstanceGuidFn &resolve_instance_guid={}) |
| Create window BuildingComponents from instance-labeled points and wall geometry. | |
| pcl::PolygonMeshPtr | mesh (CloudConstPtr cloud, CloudNConstPtr normals, EigenVectorContainer< double, 4 > &planes, EigenVectorContainer< double, 3 > ¢roids, std::vector< IndicesPtr > &inliers, CloudLConstPtr rooms, MeshOptions const opt=MeshOptions{}) |
| Generate a mesh from point cloud and geometric primitives. | |
| QualityReport | compute_plane_quality (const Cloud &cloud, const CloudL &labels, const QualityMetricsOptions &options={}) |
| Compute per-plane flatness/thickness quality metrics. | |
| template<typename Scalar, typename PointT> | |
| auto | regularizePlanes (PlaneVector< Scalar > &planes, typename pcl::PointCloud< PointT >::ConstPtr points, std::vector< pcl::IndicesPtr > &inliers, double angle_threshold=25.0, double distance_threshold=0.01) |
| const char * | to_string (SolveStatus status) |
| Human-readable name for a SolveStatus (for logging). | |
| SolverChoice | parse_solver_choice (const std::string &s) |
| Parse a –solver CLI string ("auto"/"cuopt"/"highs") into a SolverChoice. | |
| std::filesystem::path | prepare_texture_dir (const std::filesystem::path &requested={}) |
| Prepare the directory the generated texture images are staged in. | |
| pcl::TextureMesh::Ptr | texture_mesh_with_cloud (pcl::PolygonMesh::Ptr mesh, CloudConstPtr cloud, CloudNConstPtr normals=nullptr, bool debug_distinct_colors=false, const TextureQualityParams &quality=TextureQualityParams()) |
| pcl::TextureMesh::Ptr | texture_mesh (pcl::PolygonMesh::Ptr mesh, std::map< int, rtabmap::Transform > const &poses, std::map< int, rtabmap::Signature > const &nodes, const std::filesystem::path &texture_dir={}) |
| Texture mesh using RTABMap signatures (legacy API). | |
| pcl::TextureMesh::Ptr | texture_mesh (pcl::PolygonMesh::Ptr mesh, std::map< int, CameraData > const &cameras, const std::filesystem::path &texture_dir={}) |
| Texture mesh using simple camera data (ProjectDB API). | |
| void | densify_from_images (ProjectDB &db, const DensifyParams ¶ms) |
| Run OpenMVS Multi-View Stereo in-process to produce a dense point cloud from the project's sensor frames. | |
| void | apply_depth_discontinuity_filter (cv::Mat &depth, cv::Mat &confidence, float gradient_threshold=0.5f) |
| Remove "flying pixels" at depth discontinuity edges. | |
| void | apply_ray_consistency_filter (cv::Mat &depth, cv::Mat &confidence, float consistency_threshold=0.2f) |
| Remove isolated noisy depth measurements. | |
| VoxelAssignment | voxel_assignment (const Cloud &cloud, float leaf_size) |
| Build a voxel assignment for cloud at the given leaf size. | |
| CloudPtr | downsample (const Cloud &cloud, const VoxelAssignment &a) |
| Downsample cloud using the precomputed assignment. | |
| CloudNPtr | downsample (const CloudN &cloud, const VoxelAssignment &a) |
| Downsample a parallel normals cloud using the same assignment that was built from a sibling XYZRGB cloud. | |
| CloudLPtr | downsample (const CloudL &cloud, const VoxelAssignment &a) |
| Downsample a parallel label cloud (labels, planes, rooms, instances) using the same assignment that was built from a sibling XYZRGB cloud. | |
| auto | estimate_cloud_noise (CloudConstPtr cloud, CloudNConstPtr normals, const NoiseEstimateOptions &options=NoiseEstimateOptions{}) -> NoiseEstimate |
| Estimate per-cloud sensor noise (sigma) and point density from local PCA patches. | |
| ReconcileResult | reconcile_instance_identities (const CloudL *old_labels, const CloudL &new_labels, const std::vector< PriorInstance > &prior, const std::map< uint32_t, uint32_t > &new_semantic, const std::map< uint32_t, size_t > &new_sizes, const std::function< std::string()> &make_guid, const ReconcileOptions &opts={}) |
| Carry stable GUIDs across an instance-cloud regeneration. | |
| void | reconstruct_point_clouds (ProjectDB &db, const ReconstructionParams ¶ms) |
| Generate merged point clouds from sensor frames stored in a ProjectDB. | |
| auto | segment_instances (const SegmentInstancesRequest &request) -> SegmentInstancesResult |
| Segment point cloud into instances using Euclidean clustering. | |
| auto | segment_instances_impl (const SegmentInstancesRequest &request) -> SegmentInstancesResult |
| Implementation function for segment_instances. | |
| auto | segment_planes_impl (CloudConstPtr cloud, CloudNConstPtr normals, const SegmentPlanesOptions &options) -> std::tuple< CloudLPtr, CloudLocPtr, CloudNPtr > |
| auto | segment_planes (CloudConstPtr cloud, CloudNConstPtr normals, const SegmentPlanesOptions &options=SegmentPlanesOptions{}) -> std::tuple< CloudLPtr, CloudLocPtr, CloudNPtr > |
| auto | propagate_room_labels (CloudConstPtr cloud, CloudLPtr labels, IndicesConstPtr sampled_indices, IndicesConstPtr missing_indices, int k, float max_radius) -> size_t |
| Propagate room labels from a labelled subset to a set of missing points using a distance-bounded k-NN majority vote. | |
| auto | segment_rooms_impl (CloudConstPtr cloud, CloudNConstPtr normals, CloudLConstPtr planes, const SegmentRoomsOptions &options) -> CloudLPtr |
| auto | segment_rooms (CloudConstPtr cloud, CloudNConstPtr normals, CloudLConstPtr planes, const SegmentRoomsOptions &options=SegmentRoomsOptions{}) -> CloudLPtr |
| std::optional< FrameSurfels > | extract_frame_surfels (ProjectDB &db, int node_id, const SurfelExtractionParams ¶ms) |
| Back-project one sensor frame into an optical-frame surfel set and seed its world pose from the stored transform and local (optical->sensor) transform. | |
| SyncDownsampleResult | sync_downsample (ProjectDB &db, const std::string &primary, const SyncDownsampleOptions &opts) |
| Downsample primary and — unless only_primary is set — all of its index-aligned sibling clouds in db, using one shared voxel assignment so the outputs stay row-aligned. | |
| JprResult | refine_sensor_poses (ProjectDB &db, const JprParams ¶ms, bool dry_run=false) |
High-level entry point: extract surfels for every sensor frame in db, jointly refine their poses via JPR, and (unless dry_run) write the refined world poses back into the sensor_frames table. | |
| double | trajectory_extent (const std::vector< Eigen::Matrix4d > &poses) |
| Spatial extent of a trajectory: the diagonal of the axis-aligned bounding box of the camera centres, in metres. | |
| double | seed_disagreement_gate (double extent, double fraction, double floor_m) |
| Effective seed-disagreement gate in metres, combining a scale-relative term with an absolute floor: max(fraction * extent, floor), with negative inputs treated as 0. | |
| std::vector< LoopEdge > | detect_loop_edges (ProjectDB &db, const std::vector< int > &node_ids, const std::vector< Eigen::Matrix4d > &seed_poses, const LoopClosureOptions &options, LoopClosureResult *out_result=nullptr) |
| Detect wide-baseline loop edges among the given frames. | |
| std::vector< LoopEdge > | load_loop_edges (const std::string &path, const std::vector< int > &node_ids, LoopClosureResult *out_result=nullptr) |
| Load externally-computed loop edges from a JSON file and map them onto the optimizer's frame indices. | |
| std::vector< LoopEdge > | filter_consistent_loop_edges (std::vector< LoopEdge > edges, const std::vector< Eigen::Matrix4d > &seed, const LoopClosureOptions &options) |
Keep only the largest mutually consistent subset of edges (Pairwise Consistency Maximization, Mangelson et al. | |
| PanoramaAlignmentResult | align_panorama (ProjectDB &db, int pano_id, int seed_node_id, const PanoramaAlignmentOptions &opt) |
| Align one panorama against nearby sensor frames. | |
| std::vector< LoopEdge > | detect_panorama_loop_edges (ProjectDB &db, const std::vector< int > &node_ids, const std::vector< Eigen::Matrix4d > &seed_poses, const PanoramaLoopOptions &options, const LoopClosureOptions &gates, PanoramaLoopResult *out_result=nullptr) |
| Detect panorama-derived wide-baseline loop edges. | |
| PoseDriftResult | perturb_trajectory (std::vector< Eigen::Matrix4d > &poses, const PoseDriftOptions &opt) |
| Apply synthetic drift to a trajectory in place (the pure, database-free core — this is what the unit tests exercise). | |
| double | median_pair_disagreement (const std::vector< Eigen::Matrix4d > &reference, const std::vector< Eigen::Matrix4d > &other, int min_frame_gap) |
| Measure the median relative-pose disagreement between two trajectories over temporally distant frame pairs (m). | |
| PoseDriftResult | perturb_sensor_poses (ProjectDB &db, const PoseDriftOptions &opt, bool dry_run=false) |
Apply synthetic drift to every sensor-frame pose stored in db (#338). | |
| std::vector< OdometrySigmaScale > | odometry_motion_scales (const std::vector< OdometryEdgeMotion > &motion, double min_scale, double max_scale) |
| Per-edge sigma scales for OdometryNoiseModel::motion. | |
| PlaneFitSigmas | plane_fit_sigmas (const PlaneFitQuality &q) |
Standard first-order uncertainty of a least-squares plane fit through q .inliers points with point noise sigma = q.residual_rms and in-plane RMS extent r = q.extent_minor: | |
| PlaneGraphResult | optimize_sensor_poses (ProjectDB &db, const PlaneGraphOptions &options, bool dry_run=false) |
High-level entry point: extract surfels for every sensor frame in db, globally optimize their poses via the plane-landmark graph, and (unless dry_run) write the optimized world poses back into the sensor_frames table. | |
Variables | |
| constexpr float | kWallVerticalityGateOff = 1.0f |
| Verticality-gate threshold at which the gate is off (#326). | |
| using reusex::geometry::Plane = Eigen::Matrix<Scalar, 4, 1> |
Definition at line 71 of file regularization.hpp.
| using reusex::geometry::PlaneVector |
Definition at line 74 of file regularization.hpp.
| using reusex::geometry::ResolveInstanceGuidFn = std::function<std::string(uint32_t)> |
Resolves the stable GUID of an instance from its integer label id.
Returns an empty string when no GUID is available (unknown/legacy). The caller (CLI) wires this to ProjectDB::instance_guid once per-instance identity exists; the library keeps no dependency on the database. See #211.
Definition at line 96 of file create_windows.hpp.
|
strong |
| Enumerator | |
|---|---|
| cell | |
| face | |
| vertex | |
Definition at line 28 of file CellComplex.hpp.
|
strong |
Discriminator for building component types.
| Enumerator | |
|---|---|
| window | |
| door | |
| wall | |
Definition at line 17 of file BuildingComponent.hpp.
|
strong |
How loop-candidate frame pairs are proposed before geometric verification.
Definition at line 61 of file LoopClosure.hpp.
|
strong |
How the per-edge measurement noise of the consecutive-frame odometry BetweenFactors is derived (#225 odometry-trust experiment).
Definition at line 74 of file PlaneGraphOptimizer.hpp.
|
strong |
How the measurement noise of an individual plane observation is chosen.
Every observation enters the graph as an OrientedPlane3Factor whose 3-DoF residual is (two normal-tilt components [rad], one plane-offset component [m]). This enum selects how much authority a particular observation gets relative to the others; plane_sigma_normal / plane_sigma_distance always remain the sigmas of a median-quality observation, so switching models redistributes authority without changing the plane term's aggregate weight against odometry.
| Enumerator | |
|---|---|
| uniform | Every observation gets plane_sigma_* unscaled. A plane fit from 40 surfels on a cluttered shelf carries exactly as much authority as one fit from 4000 surfels on a bare wall — measured to be actively harmful once plane extraction gets dense (honka laser-GT F 0.795 -> 0.759). |
| inlier_count | Legacy (pre-#225 round 4): sigma *= clamp(sqrt(median_N / N), min, max), the SAME scalar on both the normal and the distance channel. Retained so the numbers recorded in #225 stay reproducible. |
| fit_geometry | Sigmas derived from the fit statistics of each detection — its inlier count, its point-to-plane residual RMS and its in-plane extent — see plane_fit_sigmas. Unlike inlier_count this weights the two channels separately, which matters because extent affects only the normal. |
Definition at line 55 of file PlaneGraphOptimizer.hpp.
|
strong |
| Enumerator | |
|---|---|
| point_cluster | |
| plane | |
| object | |
Definition at line 31 of file SceneGraph.hpp.
|
strong |
Which MIP backend the Solidifier should use for each (sub)problem.
| Enumerator | |
|---|---|
| automatic | |
| cuopt | |
| highs | |
Definition at line 48 of file Solidifier.hpp.
|
strong |
Backend-agnostic classification of the last MIP solve outcome.
Lets callers distinguish why a solve failed (infeasible vs. time-limit vs. error) without depending on the underlying solver's status enum.
| Enumerator | |
|---|---|
| not_solved | |
| optimal | |
| feasible | |
| infeasible | |
| unbounded | |
| time_limit | |
| iteration_limit | |
| numerical_error | |
| error | |
Definition at line 25 of file Solidifier.hpp.
|
strong |
How to compute the window boundary polygon.
| Enumerator | |
|---|---|
| rectangle | |
| polyline | |
Definition at line 41 of file create_windows.hpp.
| PanoramaAlignmentResult reusex::geometry::align_panorama | ( | ProjectDB & | db, |
| int | pano_id, | ||
| int | seed_node_id, | ||
| const PanoramaAlignmentOptions & | opt ) |
Align one panorama against nearby sensor frames.
Read-only on db (does not write the pose back — the caller decides, e.g. rux align 360
--dry-run).
| db | project database |
| pano_id | panoramic_images.id |
| seed_node_id | timestamp-matched sensor frame node id (>=0), used to seed the candidate window and measure the correction |
| opt | parameters |
| void reusex::geometry::apply_depth_discontinuity_filter | ( | cv::Mat & | depth, |
| cv::Mat & | confidence, | ||
| float | gradient_threshold = 0.5f ) |
Remove "flying pixels" at depth discontinuity edges.
Computes depth gradients via Sobel operators and zeros out pixels with gradient magnitudes exceeding gradient_threshold.
| depth | Input/output depth map (single-channel), modified in-place. |
| confidence | Input/output confidence map, modified in-place (may be empty). |
| gradient_threshold | Maximum allowed gradient in meters per pixel. |
| void reusex::geometry::apply_ray_consistency_filter | ( | cv::Mat & | depth, |
| cv::Mat & | confidence, | ||
| float | consistency_threshold = 0.2f ) |
Remove isolated noisy depth measurements.
Compares each pixel to the median of its 5x5 neighbourhood and zeros out pixels deviating by more than consistency_threshold.
| depth | Input/output depth map (single-channel), modified in-place. |
| confidence | Input/output confidence map, modified in-place (may be empty). |
| consistency_threshold | Maximum allowed deviation from neighbourhood median in meters. |
| Eigen::Vector2d reusex::geometry::bearing_to_pixel | ( | const cv::Size & | equirect, |
| const Eigen::Vector3d & | bearing ) |
Unit bearing (need not be normalised) in panorama frame -> equirect pixel (u,v).
u wraps into [0,W); v is clamped to [0,H).
|
inline |
Load the component stored under name. Throws if absent.
Definition at line 92 of file component_persistence.hpp.
References reusex::ProjectDB::component_record(), and from_component_record().
| void reusex::geometry::component_data_from_json | ( | BuildingComponent & | c, |
| const std::string & | json ) |
Deserialize JSON TEXT into the variant data on a BuildingComponent.
Referenced by from_component_record().
| std::string reusex::geometry::component_data_to_json | ( | const BuildingComponent & | c | ) |
Serialize the type-specific variant data to JSON TEXT.
Referenced by to_component_record().
| ComponentType reusex::geometry::component_type_from_string | ( | std::string_view | str | ) |
Referenced by from_component_record().
| AccuracyReport reusex::geometry::compute_accuracy | ( | const Cloud & | cloud, |
| const CloudLoc & | gt, | ||
| const AccuracyMetricsOptions & | opt = {} ) |
Score a reconstructed cloud against a ground-truth point cloud.
Nearest-neighbour distances are computed with a KdTree; the ground truth is optionally voxel-downsampled first (opt.gt_voxel). Non-finite points in either cloud are skipped.
| std::invalid_argument | if either input is empty, or if every point of either input is non-finite (nothing left to score). |
| auto reusex::geometry::compute_number_of_inliers | ( | CloudConstPtr | cloud, |
| Eigen::Vector4d const & | plane, | ||
| IndicesConstPtr | indices, | ||
| const float | threshold = 0.2 ) -> size_t |
Count number of inliers for a plane.
| cloud | Input point cloud. |
| plane | Plane coefficients. |
| indices | Point indices to check. |
| threshold | Distance threshold for inliers. Default 0.2. |
| QualityReport reusex::geometry::compute_plane_quality | ( | const Cloud & | cloud, |
| const CloudL & | labels, | ||
| const QualityMetricsOptions & | options = {} ) |
Compute per-plane flatness/thickness quality metrics.
Each plane (points sharing a label > 0 in labels) is refit by least squares (PCA), independent of any stored plane parameters, and residuals are measured against the refit plane.
| std::invalid_argument | if cloud and labels sizes differ or the cloud is empty. |
| auto reusex::geometry::compute_polygon_normal | ( | const pcl::Vertices & | poly, |
| const CloudPtr & | cloud ) -> Eigen::Vector3f |
Compute the normal vector of a polygon.
Calculates the normal vector of a polygon using the cross product sum method (also known as Newell's method). The normal is automatically normalized.
| CloudPtr | Point cloud pointer type (const or non-const, e.g., CloudLocConstPtr). |
| poly | Polygon with vertex indices. |
| cloud | Point cloud containing the vertices (read-only). |
| std::invalid_argument | if polygon has fewer than 3 vertices. |
| std::runtime_error | if polygon is degenerate (zero normal magnitude). |
| CreateWindowsResult reusex::geometry::create_windows | ( | CloudConstPtr | cloud, |
| CloudLConstPtr | instance_labels, | ||
| const std::map< uint32_t, uint32_t > & | instance_to_semantic, | ||
| const pcl::PolygonMesh & | mesh, | ||
| const std::vector< uint32_t > & | window_semantic_labels, | ||
| const CreateWindowsOptions & | options = {}, | ||
| const ResolveInstanceGuidFn & | resolve_instance_guid = {} ) |
Create window BuildingComponents from instance-labeled points and wall geometry.
For each window instance, projects its points onto the nearest wall plane, computes a boundary polygon (AABB or concave hull), and offsets it along the outward wall normal. Performs validation to filter out windows that intersect the mesh, are out of bounds, or are internal (optional).
| resolve_instance_guid | Optional callback mapping an instance label id to its stable GUID; the result is stored on each component's source_instance_guid for provenance (issue #211). Defaults to a function returning empty (no provenance). |
References mesh().
| std::vector< PerspectiveView > reusex::geometry::cube_faces | ( | const cv::Mat & | equirect, |
| int | face_size, | ||
| int | interp = 1 ) |
Tile the whole sphere as the six faces of a cube (90 deg FOV each).
Poles are covered by the up/down faces, avoiding the equirect's polar stretch.
| void reusex::geometry::densify_from_images | ( | ProjectDB & | db, |
| const DensifyParams & | params ) |
Run OpenMVS Multi-View Stereo in-process to produce a dense point cloud from the project's sensor frames.
This is the C++ library equivalent of the historical COLMAP patch_match_stereo + stereo_fusion pipeline, but linked into libreusex rather than invoked as a subprocess.
The function constructs an MVS::Scene directly from ProjectDB sensor frames (one MVS Platform per intrinsics group, one Pose per frame), runs Scene::DenseReconstruction(), and converts the resulting point cloud into a pcl::PointCloud<PointXYZRGB> saved under params.output_name.
Decoded JPEGs are staged in a temp directory because OpenMVS's depth estimator loads pixels through cv::imread regardless of API surface. The temp directory is removed on success.
| std::runtime_error | if no sensor frames are usable, the scene cannot be built, or DenseReconstruction returns failure. |
| std::vector< LoopEdge > reusex::geometry::detect_loop_edges | ( | ProjectDB & | db, |
| const std::vector< int > & | node_ids, | ||
| const std::vector< Eigen::Matrix4d > & | seed_poses, | ||
| const LoopClosureOptions & | options, | ||
| LoopClosureResult * | out_result = nullptr ) |
Detect wide-baseline loop edges among the given frames.
| db | project database (read-only image/depth/intrinsics access) |
| node_ids | database node id of each frame, in frame-index order (so LoopEdge::i/j index straight into the caller's vector) |
| seed_poses | optical->world pose of each frame (used to propose spatial candidates and sanity-check edges) |
| options | detection parameters |
| out_result | optional statistics |
| std::vector< LoopEdge > reusex::geometry::detect_panorama_loop_edges | ( | ProjectDB & | db, |
| const std::vector< int > & | node_ids, | ||
| const std::vector< Eigen::Matrix4d > & | seed_poses, | ||
| const PanoramaLoopOptions & | options, | ||
| const LoopClosureOptions & | gates, | ||
| PanoramaLoopResult * | out_result = nullptr ) |
Detect panorama-derived wide-baseline loop edges.
Deterministic given the same database and options (STANDARDS §6): panoramas and frames are processed in sorted id order, the OpenCV RNG is re-seeded per panorama, and edge ordering/capping breaks ties on (i, j).
A project with no panoramas returns an empty vector and is NOT an error — the caller decides whether the user explicitly asked for panorama edges and should therefore be warned. out_result->panoramas reports the count either way.
| db | project database (read-only: panorama images, frame colour/depth/intrinsics; panorama POSES are never read) |
| node_ids | database node id of each frame, in frame-index order, so LoopEdge::i/j index straight into the caller's vector |
| seed_poses | optical->world seed pose of each frame. Used ONLY by the seed-disagreement gates — never to build the measurement. |
| options | detection parameters |
| gates | min_frame_gap / min_seed_disagreement / max_seed_disagreement reused from the ORB front-end, so one set of CLI knobs governs every edge source |
| out_result | optional statistics |
| auto reusex::geometry::dist_plane_point | ( | const Eigen::Vector4d & | plane, |
| const Eigen::Vector3d & | point ) -> double |
Calculate distance from a point to a plane.
| plane | Plane coefficients (nx, ny, nz, d) where n is the normal. |
| point | 3D point coordinates. |
| CloudPtr reusex::geometry::downsample | ( | const Cloud & | cloud, |
| const VoxelAssignment & | a ) |
Downsample cloud using the precomputed assignment.
The output point in bucket b is the centroid (mean position and mean RGB) of every input point that fell into bucket b.
cloud.size() must equal a.point_to_bucket.size().
| CloudLPtr reusex::geometry::downsample | ( | const CloudL & | cloud, |
| const VoxelAssignment & | a ) |
Downsample a parallel label cloud (labels, planes, rooms, instances) using the same assignment that was built from a sibling XYZRGB cloud.
The output label in bucket b is the majority label among all input points that fell into b. Ties are broken deterministically by choosing the lowest label value, so results are reproducible (docs/STANDARDS.md §6).
Output rows stay aligned position-for-position with the primary downsampled cloud: every bucket produces exactly one row, and buckets with no input points (which cannot happen for the primary cloud) emit label 0 (unlabeled, per the label contract in docs/STANDARDS.md §3.1).
cloud.size() must equal a.point_to_bucket.size().
| CloudNPtr reusex::geometry::downsample | ( | const CloudN & | cloud, |
| const VoxelAssignment & | a ) |
Downsample a parallel normals cloud using the same assignment that was built from a sibling XYZRGB cloud.
Per-bucket normals are averaged and renormalized. Curvature is averaged.
cloud.size() must equal a.point_to_bucket.size().
| auto reusex::geometry::estimate_cloud_noise | ( | CloudConstPtr | cloud, |
| CloudNConstPtr | normals, | ||
| const NoiseEstimateOptions & | options = NoiseEstimateOptions{} ) -> NoiseEstimate |
Estimate per-cloud sensor noise (sigma) and point density from local PCA patches.
For each of NoiseEstimateOptions::seed_count random seed points, the NoiseEstimateOptions::k_neighbors nearest neighbours are found via a KdTree and a plane is fit by PCA (smallest-eigenvalue eigenvector = normal). The per-seed residual is the median absolute point-to-plane distance within the patch; sigma is the median of those residuals scaled by 1.4826 (the MAD→sigma consistency constant for Gaussian noise). Density is the median nearest-neighbour spacing across the seeds.
Deterministic for fixed inputs and options (STANDARDS §6).
| cloud | Input point cloud (must be non-empty; needs enough points for at least a few k-neighbour patches). |
| normals | Point normals (currently unused by the fit but kept for interface symmetry with the segmentation pipeline). |
| options | Sampling/neighbourhood parameters. |
| std::runtime_error | if cloud is empty. |
| std::optional< FrameSurfels > reusex::geometry::extract_frame_surfels | ( | ProjectDB & | db, |
| int | node_id, | ||
| const SurfelExtractionParams & | params ) |
Back-project one sensor frame into an optical-frame surfel set and seed its world pose from the stored transform and local (optical->sensor) transform.
Points and normals are returned in the camera optical frame; normals are estimated with the viewpoint at the optical-frame origin so they face the camera. The returned world_pose equals worldTf * localTf, so that world_pt = world_pose * optical_pt reproduces the reconstruction geometry.
| PerspectiveView reusex::geometry::extract_perspective | ( | const cv::Mat & | equirect, |
| const Eigen::Matrix3d & | R_pano_from_view, | ||
| const Eigen::Matrix3d & | K, | ||
| int | out_w, | ||
| int | out_h, | ||
| int | interp = 1 ) |
Render a virtual pinhole view with an explicit view->panorama rotation and intrinsics.
Used to reproject a specific camera's view out of the panorama (e.g. render what a sensor frame should see, given the aligned pose).
| PerspectiveView reusex::geometry::extract_perspective | ( | const cv::Mat & | equirect, |
| double | yaw_deg, | ||
| double | pitch_deg, | ||
| double | fov_deg, | ||
| int | out_w, | ||
| int | out_h, | ||
| int | interp = 1 ) |
Render a virtual pinhole view centred at (yaw,pitch) with the given horizontal FOV.
Longitude wraps (BORDER_WRAP); the horizon stays level (no roll). interp is an OpenCV interpolation flag (default INTER_LINEAR).
| std::vector< WallCandidate > reusex::geometry::extract_wall_candidates | ( | const pcl::PolygonMesh & | mesh, |
| float | normal_z_threshold = kWallVerticalityGateOff, | ||
| float | coplanarity_angle_deg = 10.0f ) |
Extract planar wall candidates from a triangle mesh.
Decomposes the mesh into connected components of coplanar faces. Each component becomes a WallCandidate with a fitted plane, centroid, outward normal, and boundary vertices.
| normal_z_threshold | Verticality gate: a region is kept only when |mean_normal.z| < normal_z_threshold. The default kWallVerticalityGateOff keeps every orientation (floors, ceilings and tilted roofs included) so skylight windows still find a host surface; pass e.g. 0.3 to keep near-vertical walls only (#326). |
| coplanarity_angle_deg | Maximum angular deviation inside one region. |
References kWallVerticalityGateOff, and mesh().
| std::vector< LoopEdge > reusex::geometry::filter_consistent_loop_edges | ( | std::vector< LoopEdge > | edges, |
| const std::vector< Eigen::Matrix4d > & | seed, | ||
| const LoopClosureOptions & | options ) |
Keep only the largest mutually consistent subset of edges (Pairwise Consistency Maximization, Mangelson et al.
2018): two edges are consistent when chaining them through the seed odometry between their endpoints closes a near-identity cycle. True loops satisfy this even under heavy drift; a perceptual-aliasing false positive does not.
Public because loop edges reach the graph from TWO sources — internal detection (detect_loop_edges, which PCM-filters its own output) and the external --loop-edges file — and consistency is a property of the UNION, not of either source alone. Callers that union the two must run this over the combined set, otherwise an aliasing false positive in the file has no consistency filter at all (which is exactly the case --loop-trust makes dangerous). Honour options.pcm (CLI --loop-no-pcm) at the call site so one switch governs both sources.
| edges | candidate edges; indices must address seed |
| seed | seed (pre-optimization) pose of every frame |
| options | pcm_trans_threshold / pcm_rot_threshold / pcm_max_edges |
| auto reusex::geometry::force_orthogonal_planes | ( | EigenVectorContainer< double, 4 > & | planes, |
| const double | threshold = 0.1, | ||
| const Eigen::Matrix< double, 3, 1 > & | up = Eigen::Matrix< double, 3, 1 >(0, 0, 1) ) -> EigenVectorContainer< double, 4 > |
Force planes to be orthogonal to a reference direction.
Adjusts plane normals to be either parallel or perpendicular to the up vector.
| planes | Plane coefficients to adjust. |
| threshold | Angular threshold for orthogonality. Default 0.1. |
| up | Reference up vector. Default (0, 0, 1). |
|
inline |
Rebuild a component from the persistence POD.
Definition at line 56 of file component_persistence.hpp.
References reusex::geometry::BuildingComponent::boundary, component_data_from_json(), component_type_from_string(), reusex::core::ComponentRecord::confidence, reusex::geometry::BuildingComponent::confidence, reusex::geometry::CoplanarPolygon::deserialize_vertices(), reusex::core::ComponentRecord::guid, reusex::geometry::BuildingComponent::guid, reusex::core::ComponentRecord::metadata, reusex::core::ComponentRecord::name, reusex::geometry::BuildingComponent::name, reusex::core::ComponentRecord::notes, reusex::geometry::BuildingComponent::notes, reusex::core::ComponentRecord::parent_id, reusex::geometry::BuildingComponent::parent_id, reusex::core::ComponentRecord::plane, reusex::geometry::CoplanarPolygon::plane, reusex::core::ComponentRecord::type, reusex::geometry::BuildingComponent::type, reusex::core::ComponentRecord::vertex_data, and reusex::geometry::CoplanarPolygon::vertices.
Referenced by building_component().
|
inline |
Names of all stored components of the given type.
Definition at line 98 of file component_persistence.hpp.
References reusex::ProjectDB::list_building_components(), and to_string().
| std::vector< LoopEdge > reusex::geometry::load_loop_edges | ( | const std::string & | path, |
| const std::vector< int > & | node_ids, | ||
| LoopClosureResult * | out_result = nullptr ) |
Load externally-computed loop edges from a JSON file and map them onto the optimizer's frame indices.
This is the license-clean bridge for learned matchers: any external producer — a commercial-safe matcher (XFeat / EfficientLoFTR / LightGlue+ALIKED / MapAnything-apache) or an offline research oracle (MASt3R / MapAnything-NC — non-commercial, run in Python only for accuracy-ceiling probes) — writes a file of relative-pose constraints, and the GPL C++ consumes it as DATA. No non-commercial or non-GPL model ever links into the binary; see docs/research/loop-closure-learned-matchers.md.
File schema "reusex.loop_edges.v1" (JSON): { "schema": "reusex.loop_edges.v1", "producer": "<free-text tag, e.g. mast3r@<sha> or xfeat>", "edges": [ { "node_i": <int>, "node_j": <int>, "T_ij": [16 doubles, row-major 4x4 = pose(i)^-1 * pose(j) in the optical->world convention the graph uses], "sigma_rot": <double, rad>, "sigma_trans": <double, m>, "inliers": <int> } ] } node_i/node_j are DB sensor_frame node ids; they are mapped to frame indices via node_ids (node_ids[k] is the DB id of frame k). Edges that reference a node id absent from node_ids, self-loops, or duplicate the same (i,j) are skipped with a warning (never silently dropped — docs/STANDARDS.md §5). Missing sigma/inliers fall back to the LoopEdge defaults.
The numeric payload is validated, not merely shape-checked: an edge is rejected as malformed when T_ij is not finite, its 3x3 block is not a proper rotation (R^T R != I beyond 1e-3, or det(R) < 0 — a reflection would corrupt the solve), its bottom row is not [0,0,0,1] (beyond 1e-6), or a supplied sigma is non-finite or <= 0. A zero sigma is specifically dangerous: it becomes a gtsam Constrained (hard-equality) noise model, so one bad producer line would nail two poses together.
This loader does NOT apply consistency filtering. PCM and the seed-disagreement gate are applied by the caller over the UNION of the external and internally-detected edges — see filter_consistent_loop_edges and optimize_sensor_poses().
| path | JSON file path |
| node_ids | DB node id of each frame, in frame-index order |
| out_result | optional statistics (edges accepted, summed inliers) |
| std::runtime_error | if the file cannot be opened or is not valid JSON of the expected schema (a bad edge file must fail loudly, not run a silently-unconstrained optimization). |
| auto reusex::geometry::make_pairs | ( | EigenVectorContainer< double, 4 > & | planes, |
| std::vector< IndicesPtr > & | inliers, | ||
| EigenVectorContainer< double, 3 > & | centroids, | ||
| const double | threshold = 0.6, | ||
| const double | new_plane_offset = 0.5 ) -> std::vector< std::pair< size_t, size_t > > |
Create pairs of opposite parallel planes.
Finds pairs of planes with opposite normals within a distance threshold. Creates new planes for unpaired planes.
| planes | Plane coefficients. |
| inliers | Indices of points belonging to each plane. |
| centroids | Plane centroids. |
| threshold | Maximum distance threshold for pairing. Default 0.6. |
| new_plane_offset | Offset for creating new planes. Default 0.5. |
| double reusex::geometry::median_pair_disagreement | ( | const std::vector< Eigen::Matrix4d > & | reference, |
| const std::vector< Eigen::Matrix4d > & | other, | ||
| int | min_frame_gap ) |
Measure the median relative-pose disagreement between two trajectories over temporally distant frame pairs (m).
This is the §9.5 "edge <-> seed disagreement" statistic, computed against a known reference instead of against a matcher, and is exported so the benchmark can report the same number for a drifted scan that #337 reported for a real one.
Both vectors must be the same length and in the same temporal order.
| auto reusex::geometry::merge_planes | ( | EigenVectorContainer< double, 4 > const & | planes_, |
| std::vector< IndicesPtr > const & | inliers_, | ||
| EigenVectorContainer< double, 3 > const & | centroids_, | ||
| CloudConstPtr | cloud, | ||
| const double | angle_threshold = 0.1, | ||
| const double | distance_threshold = 0.5 ) -> std::tuple< EigenVectorContainer< double, 4 >, std::vector< IndicesPtr >, EigenVectorContainer< double, 3 > > |
Merge similar planes based on angle and distance.
Agglomerative clustering: a pair merges when it is coplanar (normal and offset within the tolerances below) and spatially adjacent (inlier bounding boxes overlap, or their gap is below the coplanarity tolerance).
There is no inlier-overlap gate. The min_overlap parameter this function used to accept was removed in #325: measured on a real scan, honouring it at its documented 0.8 default blocked legitimate split-wall merges (the very regression #215 fixed), and any lower value changed nothing while doubling the merge cost.
| planes_ | Input plane coefficients. |
| inliers_ | Inliers for each plane. |
| centroids_ | Plane centroids. |
| cloud | Point cloud. |
| angle_threshold | Angular similarity threshold. Default 0.1. |
| distance_threshold | Distance threshold for merging. Default 0.5. |
| pcl::PolygonMeshPtr reusex::geometry::mesh | ( | CloudConstPtr | cloud, |
| CloudNConstPtr | normals, | ||
| EigenVectorContainer< double, 4 > & | planes, | ||
| EigenVectorContainer< double, 3 > & | centroids, | ||
| std::vector< IndicesPtr > & | inliers, | ||
| CloudLConstPtr | rooms, | ||
| MeshOptions const | opt = MeshOptions{} ) |
Generate a mesh from point cloud and geometric primitives.
| cloud | Input point cloud. |
| normals | Point cloud normals. |
| planes | Detected plane coefficients. |
| centroids | Plane centroids. |
| inliers | Indices of points belonging to each plane. |
| rooms | Room labels for points. |
| opt | Mesh generation options (includes optional filter). |
Referenced by create_windows(), reusex::geometry::cgal::decompose_mesh(), extract_wall_candidates(), texture_mesh(), texture_mesh(), texture_mesh_with_cloud(), and unweld_mesh().
| std::vector< OdometrySigmaScale > reusex::geometry::odometry_motion_scales | ( | const std::vector< OdometryEdgeMotion > & | motion, |
| double | min_scale, | ||
| double | max_scale ) |
Per-edge sigma scales for OdometryNoiseModel::motion.
Each channel is scaled by that edge's motion relative to the median motion over the run, clamped to [min_scale, max_scale]:
scale_trans_i = clamp(|dt_i| / median_j(|dt_j|), min, max) scale_rot_i = clamp(|dr_i| / median_j(|dr_j|), min, max)
Properties this function guarantees, and which the unit tests pin:
The two channels are normalised independently because a pure-rotation sweep and a pure-translation dolly are different failure modes of the seed.
| PlaneGraphResult reusex::geometry::optimize_sensor_poses | ( | ProjectDB & | db, |
| const PlaneGraphOptions & | options, | ||
| bool | dry_run = false ) |
High-level entry point: extract surfels for every sensor frame in db, globally optimize their poses via the plane-landmark graph, and (unless dry_run) write the optimized world poses back into the sensor_frames table.
The optimizer works on the combined optical->world pose; on write-back the constant local (optical->sensor) transform is removed so the stored transform column keeps its worldTf meaning (identical to refine_sensor_poses).
| db | Project database (read/write). |
| options | Optimization parameters. |
| dry_run | When true, compute and report statistics without writing. |
| std::vector< PerspectiveView > reusex::geometry::overlapping_views | ( | const cv::Mat & | equirect, |
| int | n_yaw, | ||
| double | fov_deg, | ||
| int | tile, | ||
| int | interp = 1 ) |
Tile the sphere as n_yaw evenly spaced views around the equator plus one up and one down view, each with fov_deg horizontal FOV and tile pixels square.
Overlap between neighbours (fov_deg > 360/n_yaw) hides seams; the larger overlap (vs cube faces) is what the ORB matcher wants so a feature is never split across a tile boundary.
| SolverChoice reusex::geometry::parse_solver_choice | ( | const std::string & | s | ) |
Parse a –solver CLI string ("auto"/"cuopt"/"highs") into a SolverChoice.
Throws std::runtime_error on an unrecognized value.
| PoseDriftResult reusex::geometry::perturb_sensor_poses | ( | ProjectDB & | db, |
| const PoseDriftOptions & | opt, | ||
| bool | dry_run = false ) |
Apply synthetic drift to every sensor-frame pose stored in db (#338).
Frames are ordered by node id (the same ordering optimize_sensor_poses uses) and only frames that actually carry a pose participate. The stored poses are OVERWRITTEN — this is a destructive operation intended for a disposable COPY of a project, never for an original capture; rux edit perturb-poses says so in its help and the bench harness copies first.
| db | project to perturb, opened read-write |
| opt | drift parameters |
| dry_run | measure and report without writing anything back (how the harness reads a trajectory's extent before committing) |
| std::runtime_error | if fewer than two frames carry a pose |
| PoseDriftResult reusex::geometry::perturb_trajectory | ( | std::vector< Eigen::Matrix4d > & | poses, |
| const PoseDriftOptions & | opt ) |
Apply synthetic drift to a trajectory in place (the pure, database-free core — this is what the unit tests exercise).
| poses | optical->world poses in temporal order; perturbed in place. Fewer than 2 poses is a no-op. |
| opt | drift parameters |
| Eigen::Vector3d reusex::geometry::pixel_to_bearing | ( | const cv::Size & | equirect, |
| double | u, | ||
| double | v ) |
Equirect pixel (u,v) -> unit bearing in the panorama frame.
| PlaneFitSigmas reusex::geometry::plane_fit_sigmas | ( | const PlaneFitQuality & | q | ) |
Standard first-order uncertainty of a least-squares plane fit through q .inliers points with point noise sigma = q.residual_rms and in-plane RMS extent r = q.extent_minor:
sigma_distance = sigma / sqrt(N) sigma_normal = sigma / (r * sqrt(N))
The offset is an average over the inliers, so it tightens as 1/sqrt(N). The tilt is a lever-arm estimate: the same point noise at the edge of a 3 m wall subtends a far smaller angle than at the edge of a 20 cm patch, so the normal additionally tightens as 1/r. This factor of r is the whole reason the two channels must not share one scalar — two detections with identical N and sigma but 15x different extent are equally certain in offset and 15x apart in tilt.
The returned values are relative quality indicators, not absolute calibrated sigmas: the dominant real error is model error (surface roughness, depth bias, slight mis-association), not the fit's own statistical error. The optimizer therefore normalises them by their median across the run and applies the result as a scale on plane_sigma_normal / plane_sigma_distance.
Degenerate inputs are clamped rather than propagated, so the result is always finite and strictly positive.
| std::filesystem::path reusex::geometry::prepare_texture_dir | ( | const std::filesystem::path & | requested = {} | ) |
Prepare the directory the generated texture images are staged in.
The library never writes to — or deletes from — the process working directory (issue #245):
| std::runtime_error | if the directory cannot be created. |
| auto reusex::geometry::propagate_room_labels | ( | CloudConstPtr | cloud, |
| CloudLPtr | labels, | ||
| IndicesConstPtr | sampled_indices, | ||
| IndicesConstPtr | missing_indices, | ||
| int | k, | ||
| float | max_radius ) -> size_t |
Propagate room labels from a labelled subset to a set of missing points using a distance-bounded k-NN majority vote.
For each index in missing_indices the function polls up to k nearest neighbours drawn from sampled_indices, discards any farther than max_radius, and assigns the majority room label among the remainder. Ties break deterministically towards the smallest room label. Points with no labelled neighbour inside the radius keep their current label (expected to be reusex::core::kUnlabeled == 0) and are counted.
| cloud | Full point cloud (positions used for the search). |
| labels | In/out labels; sampled_indices must already hold the seed room labels, missing points are written here. |
| sampled_indices | Indices whose labels act as propagation seeds. |
| missing_indices | Indices to assign a label to. |
| k | Neighbours polled per missing point (clamped to >=1). |
| max_radius | Maximum neighbour distance in meters. |
| ReconcileResult reusex::geometry::reconcile_instance_identities | ( | const CloudL * | old_labels, |
| const CloudL & | new_labels, | ||
| const std::vector< PriorInstance > & | prior, | ||
| const std::map< uint32_t, uint32_t > & | new_semantic, | ||
| const std::map< uint32_t, size_t > & | new_sizes, | ||
| const std::function< std::string()> & | make_guid, | ||
| const ReconcileOptions & | opts = {} ) |
Carry stable GUIDs across an instance-cloud regeneration.
Both old_labels and new_labels are index-aligned instance-label clouds over the same point cloud (identical indices; 0 = unlabeled). For each new instance we find the old instance of the same semantic class with the greatest mutual point-set overlap (intersection over the smaller instance); if that overlap exceeds ReconcileOptions::min_overlap the new instance inherits the old GUID, otherwise it receives a fresh GUID from make_guid. Matching is greedy by descending overlap and one-to-one: each old GUID is carried to at most one new instance.
| old_labels | Previous instance-label cloud (may be null/empty). |
| new_labels | Newly-segmented instance-label cloud. |
| prior | Prior instance rows (semantic class + GUID per old id). |
| new_semantic | Map: new instance_id -> semantic class. |
| new_sizes | Map: new instance_id -> point count. |
| make_guid | Factory for fresh GUIDs (e.g. a UUID generator). |
| opts | Reconciliation options. |
| std::invalid_argument | if old/new label clouds differ in size. |
| void reusex::geometry::reconstruct_point_clouds | ( | ProjectDB & | db, |
| const ReconstructionParams & | params ) |
Generate merged point clouds from sensor frames stored in a ProjectDB.
For each sensor frame the function reads depth, confidence, color, pose, and intrinsics; applies depth filters; performs custom pinhole back-projection; estimates normals; and accumulates into a single cloud. Post-processing includes voxelisation, NaN removal, label majority voting, statistical outlier removal, and radius outlier removal.
Results are saved into the ProjectDB as "cloud", "normals", and "labels".
| db | Project database (read/write). |
| params | Reconstruction parameters. |
| JprResult reusex::geometry::refine_sensor_poses | ( | ProjectDB & | db, |
| const JprParams & | params, | ||
| bool | dry_run = false ) |
High-level entry point: extract surfels for every sensor frame in db, jointly refine their poses via JPR, and (unless dry_run) write the refined world poses back into the sensor_frames table.
The optimizer works on the combined optical->world pose; on write-back the constant local (optical->sensor) transform is removed so the stored transform column keeps its worldTf meaning.
| db | Project database (read/write). |
| params | Refinement parameters. |
| dry_run | When true, compute and report statistics without writing. |
| auto reusex::geometry::regularizePlanes | ( | PlaneVector< Scalar > & | planes, |
| typename pcl::PointCloud< PointT >::ConstPtr | points, | ||
| std::vector< pcl::IndicesPtr > & | inliers, | ||
| double | angle_threshold = 25.0, | ||
| double | distance_threshold = 0.01 ) |
Definition at line 78 of file regularization.hpp.
References reusex::trace().
|
inline |
Insert or replace component, keyed by its name.
A guid is generated on first save and preserved across later saves.
Definition at line 78 of file component_persistence.hpp.
References reusex::ProjectDB::save_component_record(), and to_component_record().
| double reusex::geometry::seed_disagreement_gate | ( | double | extent, |
| double | fraction, | ||
| double | floor_m ) |
Effective seed-disagreement gate in metres, combining a scale-relative term with an absolute floor: max(fraction * extent, floor), with negative inputs treated as 0.
A result of 0 means "no gate" (keep every edge).
Issue #339: expressing the gate purely in metres does not transfer across capture scales. The 0.50 m external default was tuned on a scan with ~16 m of drift over an 18 m extent; applied unchanged to a 1.8 m ARKitScenes room scan it stops selecting informative edges and starts selecting the most disagreeing — i.e. the wrong — ones, measured at F@50mm 0.29 (registration-improvements.md §9.4). The fraction term fixes that. The floor term is kept because a matcher's own error is a sensor property that does NOT shrink with the room: on a small scan the floor is what keeps loop closure a no-op instead of injecting depth noise.
| auto reusex::geometry::segment_instances | ( | const SegmentInstancesRequest & | request | ) | -> SegmentInstancesResult |
Segment point cloud into instances using Euclidean clustering.
Applies PCL's Euclidean clustering algorithm within each semantic class to separate spatially-disconnected regions into distinct instances.
Algorithm:
| request | Configuration and input data |
| std::invalid_argument | if inputs are invalid |
| std::runtime_error | if cancellation requested |
| auto reusex::geometry::segment_instances_impl | ( | const SegmentInstancesRequest & | request | ) | -> SegmentInstancesResult |
Implementation function for segment_instances.
Separated for future enhancements (e.g., different clustering algorithms)
| auto reusex::geometry::segment_planes | ( | CloudConstPtr | cloud, |
| CloudNConstPtr | normals, | ||
| const SegmentPlanesOptions & | options = SegmentPlanesOptions{} ) -> std::tuple< CloudLPtr, CloudLocPtr, CloudNPtr > |
| auto reusex::geometry::segment_planes_impl | ( | CloudConstPtr | cloud, |
| CloudNConstPtr | normals, | ||
| const SegmentPlanesOptions & | options ) -> std::tuple< CloudLPtr, CloudLocPtr, CloudNPtr > |
| auto reusex::geometry::segment_rooms | ( | CloudConstPtr | cloud, |
| CloudNConstPtr | normals, | ||
| CloudLConstPtr | planes, | ||
| const SegmentRoomsOptions & | options = SegmentRoomsOptions{} ) -> CloudLPtr |
| auto reusex::geometry::segment_rooms_impl | ( | CloudConstPtr | cloud, |
| CloudNConstPtr | normals, | ||
| CloudLConstPtr | planes, | ||
| const SegmentRoomsOptions & | options ) -> CloudLPtr |
| auto reusex::geometry::separate_planes | ( | const EigenVectorContainer< double, 4 > & | planes, |
| const Eigen::Vector3d & | up = Eigen::Vector3d(0, 0, 1), | ||
| const double | epsilon = 0.1 ) -> std::tuple< std::vector< size_t >, std::vector< size_t > > |
Separate planes into horizontal and vertical based on up vector.
| planes | Plane coefficients. |
| up | Reference up vector. Default (0, 0, 1). |
| epsilon | Angular epsilon for classification. Default 0.1. |
| cv::Mat reusex::geometry::stitch_labels_to_equirect | ( | const cv::Size & | out, |
| const std::vector< PerspectiveView > & | views, | ||
| const std::vector< cv::Mat > & | tile_labels ) |
Stitch per-tile label maps (CV_32S, -1 = background) back into a single equirect label map of size out.
For each equirect pixel the covering tile whose optical axis is closest to that bearing wins (most central sample, least perspective distortion). Tiles must align 1:1 with views. Background (-1) samples never override a real label from another tile.
| SyncDownsampleResult reusex::geometry::sync_downsample | ( | ProjectDB & | db, |
| const std::string & | primary, | ||
| const SyncDownsampleOptions & | opts ) |
Downsample primary and — unless only_primary is set — all of its index-aligned sibling clouds in db, using one shared voxel assignment so the outputs stay row-aligned.
Sibling discovery: every point cloud whose point count equals the primary cloud's point count (excluding the primary itself) is treated as a sibling. Supported sibling types are downsampled with the matching overload:
When only_primary is true and index-aligned siblings exist, the call throws unless force_desync is also set; the exception message names every sibling that would be invalidated.
The operation is recorded in the pipeline log (start/end), naming the affected clouds, so staleness is auditable.
Throws std::invalid_argument if the primary is missing, not PointXYZRGB, empty, or the leaf size is non-positive; std::runtime_error on unsupported sibling types, size mismatches, or a refused desync.
| pcl::TextureMesh::Ptr reusex::geometry::texture_mesh | ( | pcl::PolygonMesh::Ptr | mesh, |
| std::map< int, CameraData > const & | cameras, | ||
| const std::filesystem::path & | texture_dir = {} ) |
Texture mesh using simple camera data (ProjectDB API).
| texture_dir | staging directory for the texture images; see prepare_texture_dir() for the empty-default semantics. |
References mesh().
| pcl::TextureMesh::Ptr reusex::geometry::texture_mesh | ( | pcl::PolygonMesh::Ptr | mesh, |
| std::map< int, rtabmap::Transform > const & | poses, | ||
| std::map< int, rtabmap::Signature > const & | nodes, | ||
| const std::filesystem::path & | texture_dir = {} ) |
Texture mesh using RTABMap signatures (legacy API).
| texture_dir | staging directory for the texture images; see prepare_texture_dir() for the empty-default semantics. |
References mesh().
| pcl::TextureMesh::Ptr reusex::geometry::texture_mesh_with_cloud | ( | pcl::PolygonMesh::Ptr | mesh, |
| CloudConstPtr | cloud, | ||
| CloudNConstPtr | normals = nullptr, | ||
| bool | debug_distinct_colors = false, | ||
| const TextureQualityParams & | quality = TextureQualityParams() ) |
References mesh().
|
inline |
Build a 4x4 Eigen affine (float) from a row-major double[16] array.
Definition at line 17 of file transform_utils.hpp.
|
inline |
Flatten a 4x4 Eigen affine (float) into a row-major double[16] array.
Definition at line 28 of file transform_utils.hpp.
|
inline |
Flatten a component into the persistence POD.
The variant payload and the source_instance_guid provenance link are folded into the record's opaque metadata JSON, exactly as the previous in-ProjectDB code did, so the on-disk bytes are unchanged.
Definition at line 39 of file component_persistence.hpp.
References reusex::geometry::BuildingComponent::boundary, component_data_to_json(), reusex::core::ComponentRecord::confidence, reusex::geometry::BuildingComponent::confidence, reusex::core::ComponentRecord::guid, reusex::geometry::BuildingComponent::guid, reusex::core::ComponentRecord::metadata, reusex::core::ComponentRecord::name, reusex::geometry::BuildingComponent::name, reusex::core::ComponentRecord::notes, reusex::geometry::BuildingComponent::notes, reusex::core::ComponentRecord::parent_id, reusex::geometry::BuildingComponent::parent_id, reusex::core::ComponentRecord::plane, reusex::geometry::CoplanarPolygon::plane, reusex::geometry::CoplanarPolygon::serialize_vertices(), to_string(), reusex::core::ComponentRecord::type, reusex::geometry::BuildingComponent::type, and reusex::core::ComponentRecord::vertex_data.
Referenced by save_building_component(), and update_building_component_by_guid().
| std::string_view reusex::geometry::to_string | ( | ComponentType | type | ) |
Referenced by list_building_components(), and to_component_record().
| const char * reusex::geometry::to_string | ( | SolveStatus | status | ) |
Human-readable name for a SolveStatus (for logging).
| double reusex::geometry::trajectory_extent | ( | const std::vector< Eigen::Matrix4d > & | poses | ) |
Spatial extent of a trajectory: the diagonal of the axis-aligned bounding box of the camera centres, in metres.
This is the capture-scale denominator every scale-relative threshold in the loop-closure front-end divides by (issue #339). It is deliberately the bbox diagonal rather than the travelled path length: what a loop edge can be asked to correct is how far apart two places are, not how long the operator walked between them, and a scan that walks the same corridor twice must not read as twice the scale. Deterministic, O(N), independent of frame ordering (STANDARDS §6). Returns 0 for fewer than two poses.
Reference values (registration-improvements.md §9.5): office 18.01 m, ARKitScenes 41069048/50/51 1.82 / 1.86 / 2.57 m.
| pcl::PolygonMeshPtr reusex::geometry::unweld_mesh | ( | const pcl::PolygonMesh & | mesh, |
| float | threshold_radians ) |
Unweld (split) mesh vertices along sharp edges.
Vertices shared by faces whose normals differ by more than threshold_radians are duplicated so each smooth face group gets its own copy. This produces correct per-face normals for export to formats like OBJ, Speckle, or Rhino.
| mesh | Input polygon mesh (const ref, not modified). |
| threshold_radians | Maximum dihedral angle (in radians) between face normals for vertices to remain shared. 0 = fully unweld, pi = preserve all sharing. |
References mesh().
|
inline |
Update an existing component's mutable fields, matched by its immutable guid.
Throws if no component has that guid.
Definition at line 86 of file component_persistence.hpp.
References to_component_record(), and reusex::ProjectDB::update_component_record_by_guid().
| VoxelAssignment reusex::geometry::voxel_assignment | ( | const Cloud & | cloud, |
| float | leaf_size ) |
Build a voxel assignment for cloud at the given leaf size.
Non-finite points are recorded with kSkippedPoint in point_to_bucket and contribute neither a bucket nor a centroid.
Throws std::invalid_argument if leaf_size <= 0, the cloud is empty, or all points are non-finite. Throws std::out_of_range if the cloud's bounding-box extent exceeds ~2 million voxels along any axis at the chosen leaf size (raise the leaf size). Throws std::overflow_error if the number of occupied voxels exceeds 2^32 - 1 (raise the leaf size).
|
inlineconstexpr |
Verticality-gate threshold at which the gate is off (#326).
The gate keeps a region when |mean_normal.z| < normal_z_threshold. Since every unit normal has |n.z| <= 1, this value admits every orientation — and it is treated as an exact opt-out so perfectly horizontal faces (|n.z| == 1) are kept too.
Definition at line 49 of file create_windows.hpp.
Referenced by extract_wall_candidates().