cumulus3d_core/lib.rs
1/*
2 * lib.rs
3 *
4 * Copyright (c) 2026 ParkSangWoo
5 *
6 * Author(s):
7 *
8 * ParkSangWoo <dev.parksangwoo@gmail.com>
9 *
10 *
11 * This file is part of cumulus3d.
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *
25 * SPDX-License-Identifier: Apache-2.0
26 */
27
28//! Common foundation: camera models, geometry, reconstruction data structures, correspondence graph, feature store, RANSAC, I/O.
29//!
30//! Convention summary (public items per module are in the crate `README.md`):
31//! - Poses are `world_to_cam` (world -> camera); quaternions are Hamilton, stored in w,x,y,z order.
32//! - Camera frame: x right, y down, z forward. Pixel coordinates: top-left pixel center = (0.5, 0.5).
33//! - ids: camera/rig/frame/image = u32, 3D point = u64, pair = u64. The invalid value is the maximum of each type.
34//!
35//! # Usage example
36//!
37//! Builds a reconstruction from two images and one 3D point, computes the reprojection error, then saves and loads it as a model file.
38//!
39//! ```
40//! use cumulus3d_core::analyzer::ModelStats;
41//! use cumulus3d_core::interop::{read_model, write_model_binary, ImageOrder};
42//! use cumulus3d_core::{Camera, CameraModelKind, Image, Quat, Reconstruction, Rigid3, TrackEntry, Vec3};
43//!
44//! let mut cam = Camera::from_focal(CameraModelKind::Pinhole, 1000.0, 1920, 1080);
45//! cam.camera_id = 1;
46//! let mut rec = Reconstruction::new();
47//! rec.add_camera_own_rig(cam.clone())?;
48//!
49//! // Project one world point into the two cameras (1 m baseline) to produce 2D observations.
50//! let x = Vec3::new(0.2, -0.1, 5.0);
51//! for (id, tx) in [(1u32, 0.0), (2, -1.0)] {
52//! let world_to_cam = Rigid3::new(Quat::IDENTITY, Vec3::new(tx, 0.0, 0.0));
53//! let xy = cam.cam_to_img(&world_to_cam.transform_point(&x)).unwrap();
54//! rec.add_image_own_frame(Image::new(id, format!("img{id}.jpg"), 1, [xy]), Some(world_to_cam))?;
55//! rec.register_image(id)?;
56//! }
57//! let pid = rec.add_point3d(x, vec![TrackEntry::new(1, 0), TrackEntry::new(2, 0)], [255, 0, 0])?;
58//! rec.update_point3d_errors();
59//! assert!(rec.point3d(pid).unwrap().error < 1e-9);
60//! rec.check_invariants()?;
61//!
62//! let dir = std::env::temp_dir().join("cumulus3d_core_doc_example");
63//! std::fs::create_dir_all(&dir)?;
64//! write_model_binary(&rec, &dir, ImageOrder::default())?;
65//! let back = read_model(&dir)?;
66//! let stats = ModelStats::compute(&back);
67//! assert_eq!((stats.registered_image_count, stats.num_points3d), (2, 1));
68//! # Ok::<(), cumulus3d_core::Error>(())
69//! ```
70
71#![warn(missing_docs)]
72
73pub mod analyzer;
74pub mod camera;
75pub mod error;
76pub mod features;
77pub mod geometry;
78pub mod graph;
79pub mod ids;
80pub mod interop;
81pub mod io;
82pub mod linalg;
83pub mod ransac;
84pub mod reconstruction;
85pub mod store;
86
87pub use camera::{Camera, CameraModelKind};
88pub use error::{Error, Result};
89pub use features::{Descriptors, FeatureMatch, Keypoint, TwoViewGeometry, TwoViewGeometryConfig, DESCRIPTOR_DIM};
90pub use geometry::{Mat3, Mat3x4, Quat, Rigid3, Sim3, Vec2, Vec3};
91pub use graph::{MatchGraph, MatchGraphOptions};
92pub use ids::*;
93pub use reconstruction::{Frame, Image, Point2D, Point3D, Reconstruction, Rig, TrackEntry};
94pub use store::FeatureStore;