Skip to main content

cumulus3d_cli/
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//! Library part of the cumulus3d executable: the incremental stream pipeline and the stage-by-stage compatible subcommands ([`interop`]).
29//!
30//! - [`ahead`]: [`ahead::Lookahead`], the handle that gets feature extraction of upcoming positions started ahead of the position loop.
31//! - [`session`]: the state value [`session::Session`] and the reducer functions [`session::step`] / [`session::poll`] /
32//!   [`session::command`] / [`session::finish`].
33//! - [`pipeline`]: [`pipeline::Pipeline`], which wraps the reducer and provides hooks, queue policy, panic isolation and subscription
34//!   channels.
35//! - [`events`]: per-stage results [`events::Event`] and commands [`events::Command`].
36//! - [`sinks`]: default hooks that produce the file output of `cumulus3d stream` (timeline.txt, run.log, PLY, snapshots).
37//! - [`stream`]: input folder -> session -> pipeline assembly ([`stream::run_stream`]).
38//! - [`compose`]: a persistent node for live input. Declare the current input state ([`compose::FrameState`]) and it is compared with the
39//!   accepted record to process incrementally.
40//! - [`declare`]: the declarative builder layer. It only records a plan ([`declare::Plan`]); `build` validates it and `run` executes it
41//!   in one go
42//!   ([`declare::Recon`]). Plans are saved and read as TOML (`cumulus3d run plan.toml`).
43//!
44//! # Usage example
45//!
46//! Feed an image folder (`images/camF|camR|camL/*.jpg`, `gps_ref.txt`) position by position for incremental reconstruction,
47//! and use the default output hook to produce the same files as `cumulus3d stream`.
48//!
49//! ```no_run
50//! use cumulus3d_cli::events::{Event, EventKind};
51//! use cumulus3d_cli::pipeline::Pipeline;
52//! use cumulus3d_cli::session::{Input, Session, SessionConfig};
53//! use cumulus3d_cli::sinks::{self, SinkOptions};
54//! use cumulus3d_cli::stream::{frame_set, Layout};
55//! use cumulus3d_core::io::read_gps_file;
56//! use std::path::Path;
57//!
58//! fn main() -> Result<(), String> {
59//!     let src = Path::new("data");
60//!     let layout = Layout::discover(src, 3)?;
61//!     let mut cfg = SessionConfig::new(src.join("images"));
62//!     cfg.gps = read_gps_file(src.join("gps_ref.txt")).map_err(|e| e.to_string())?;
63//!     cfg.total_positions = Some(layout.frames.len());
64//!
65//!     let pipeline = Pipeline::new(Session::new(cfg)).on(EventKind::ZonePreview, |e: &Event| {
66//!         if let Event::ZonePreview { range, cloud, .. } = e {
67//!             println!("preview zone {}: {} points", range.zone, cloud.len());
68//!         }
69//!     });
70//!     let mut pipeline = sinks::attach(pipeline, Path::new("out"), &SinkOptions::default()).map_err(|e| e.to_string())?;
71//!     for p in 0..layout.frames.len() {
72//!         pipeline.push(Input::Frames(frame_set(&layout, p)));
73//!     }
74//!     let (_session, summary) = pipeline.finish();
75//!     println!("{} events", summary.events);
76//!     Ok(())
77//! }
78//! ```
79//!
80//! Declarative (record a plan -> validate -> run):
81//!
82//! ```no_run
83//! use cumulus3d_cli::declare::{Dense, Recon, Sinks};
84//!
85//! let recon = Recon::declare()
86//!     .input("data")
87//!     .preset("aerial-formation")
88//!     .zones(12, 2)
89//!     .dense(Dense::profile("fast").fusion_min_views(3))
90//!     .sinks(Sinks::default_files("out"))
91//!     .seed(7)
92//!     .build()
93//!     .unwrap_or_else(|e| panic!("{e}"));
94//! let summary = recon.run().unwrap();
95//! println!("{} events", summary.events);
96//! ```
97//!
98//! Functional use that only passes state values around, without hooks:
99//!
100//! ```no_run
101//! use cumulus3d_cli::session::{finish, step, FrameSet, Session, SessionConfig};
102//!
103//! let s0 = Session::new(SessionConfig::new("data/images"));
104//! let frames = FrameSet::new([("camF", "camF/camF_0000.jpg"), ("camR", "camR/camR_0000.jpg")]);
105//! let (s1, events) = step(&s0, frames);
106//! for e in &events {
107//!     if let Some(t) = e.timeline_text() {
108//!         println!("{t}");
109//!     }
110//! }
111//! let (_done, _summary_events) = finish(&s1);
112//! ```
113
114#![warn(missing_docs)]
115
116pub mod ahead;
117pub mod blocks;
118pub mod compose;
119pub mod declare;
120pub mod densewrap;
121pub mod events;
122pub mod fusion_variants;
123pub mod interop;
124pub mod intrinsics;
125pub mod live;
126pub mod pipeline;
127pub mod post;
128pub mod session;
129pub mod sinks;
130pub mod stream;
131pub mod util;