pub mod rng;
mod surfaces;
use nalgebra::{Vector3, Vector6};
use rigidity_core::PointCloud;
pub use surfaces::SceneKind;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct SceneParams {
pub points_per_face: usize,
pub scale: f64,
pub noise_sigma: f64,
pub outlier_ratio: f64,
pub outlier_extent: f64,
pub seed: u64,
}
impl Default for SceneParams {
fn default() -> Self {
Self {
points_per_face: 2_000,
scale: 1.0,
noise_sigma: 0.0,
outlier_ratio: 0.0,
outlier_extent: 0.25,
seed: 0x1234_5678_9ABC_DEF0,
}
}
}
#[derive(Debug, Clone)]
pub struct Scene {
pub kind: SceneKind,
pub params: SceneParams,
pub points: Vec<Vector3<f64>>,
pub cloud: PointCloud,
pub normals: Vec<Vector3<f64>>,
pub inlier_count: usize,
}
impl Scene {
pub fn generate(kind: SceneKind, params: SceneParams) -> Self {
surfaces::generate(kind, params)
}
pub fn nullspace(&self) -> Vec<Vector6<f64>> {
self.kind.nullspace()
}
pub fn nullspace_dimension(&self) -> usize {
self.kind.nullspace_dimension()
}
pub fn len(&self) -> usize {
self.cloud.len()
}
pub fn is_empty(&self) -> bool {
self.cloud.is_empty()
}
pub fn split_with_overlap(&self, overlap: f64, seed: u64) -> (PointCloud, PointCloud) {
let overlap = overlap.clamp(0.0, 1.0);
let exclusive = (1.0 - overlap) * 0.5;
let mut rng = rng::Rng::new(seed);
let mut source = PointCloud::with_origin(self.cloud.origin());
let mut target = PointCloud::with_origin(self.cloud.origin());
for i in 0..self.cloud.len() {
let point = self.cloud.point(i);
let draw = rng.unit();
if draw < overlap {
source.push(point);
target.push(point);
} else if draw < overlap + exclusive {
source.push(point);
} else {
target.push(point);
}
}
(source, target)
}
}