use brep_ransac::{
constrain_cylinder_coaxial, constrain_plane_perpendicular_to_axis, reconstruct_surface,
synthetic, AnalyticSurface, CylinderSurface, PlaneSurface, RecognitionOptions, SamplingMode,
SurfaceHint, SurfaceType, Vec3,
};
fn options() -> RecognitionOptions {
RecognitionOptions {
distance_tolerance: 1.0e-6,
normal_tolerance: 0.1,
minimum_support: 4,
sampling: SamplingMode::Vertices,
..RecognitionOptions::default()
}
}
#[test]
fn cylinder_axis_can_be_constrained_to_an_existing_cylinder() {
let reference = AnalyticSurface::Cylinder(CylinderSurface {
axis_origin: Vec3::new(2.0, -1.0, 0.0),
axis: Vec3::Z,
radius: 8.0,
});
let truth = AnalyticSurface::Cylinder(CylinderSurface {
axis_origin: Vec3::new(2.0, -1.0, 10.0),
axis: Vec3::Z,
radius: 3.0,
});
let mesh = synthetic::partial(truth, 20);
let ids = (0..mesh.triangles.len()).collect::<Vec<_>>();
let hint = constrain_cylinder_coaxial(
CylinderSurface {
axis_origin: Vec3::new(2.1, -0.9, 3.0),
axis: Vec3::new(0.01, 0.0, 0.99995).normalized().unwrap(),
radius: 2.9,
},
reference,
)
.unwrap();
let fit = reconstruct_surface(&mesh, &ids, &hint, &options()).unwrap();
let AnalyticSurface::Cylinder(result) = fit.surface else {
unreachable!()
};
assert_eq!(result.axis, Vec3::Z);
assert!((result.axis_origin.x - 2.0).abs() < 1.0e-12);
assert!((result.axis_origin.y + 1.0).abs() < 1.0e-12);
assert!((result.radius - 3.0).abs() < 1.0e-8);
}
#[test]
fn plane_can_be_constrained_perpendicular_to_a_known_axis() {
let truth = AnalyticSurface::Plane(PlaneSurface {
origin: Vec3::new(0.0, 0.0, 4.0),
normal: Vec3::Z,
});
let mesh = synthetic::partial(truth, 16);
let ids = (0..mesh.triangles.len()).collect::<Vec<_>>();
let hint = constrain_plane_perpendicular_to_axis(
PlaneSurface {
origin: Vec3::new(0.0, 0.0, 3.9),
normal: Vec3::new(0.01, -0.02, 0.99975).normalized().unwrap(),
},
Vec3::Z,
)
.unwrap();
let SurfaceHint::Constrained { constraints, .. } = &hint else {
unreachable!()
};
assert!(constraints.fixed.axis_or_normal);
assert!(!constraints.fixed.origin_or_center);
let fit = reconstruct_surface(&mesh, &ids, &hint, &options()).unwrap();
assert_eq!(fit.surface.surface_type(), SurfaceType::Plane);
let AnalyticSurface::Plane(result) = fit.surface else {
unreachable!()
};
assert_eq!(result.normal, Vec3::Z);
assert!((result.origin.z - 4.0).abs() < 1.0e-12);
}