microcad_core/geo3d/
align.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Builtin align for 3D geometries.
5
6use cgmath::ElementWise;
7
8use crate::*;
9
10/// Trait to align a 2D geometry collection with spacing along an axis.
11pub trait Align3D<T = Self> {
12    /// Align geometry.
13    fn align_3d(&self, direction: Vec3, spacing: Length) -> T;
14}
15
16impl Align3D for Geometries3D {
17    fn align_3d(&self, direction: Vec3, spacing: Length) -> Self {
18        Geometries3D::from_iter(self.iter().scan(0.0_f64, |pos, geo3d| {
19            use cgmath::InnerSpace;
20
21            let bounds = geo3d.calc_bounds_3d();
22            let dir = if direction.magnitude() > f64::EPSILON {
23                direction.normalize()
24            } else {
25                Vec3::new(0.0, 0.0, 0.0)
26            };
27            let dist = *bounds.distance_center_to_boundary(dir);
28            let c = bounds.center();
29
30            let d = (*pos + dist) * dir - dir.mul_element_wise(c);
31            *pos += 2.0 * dist + *spacing;
32
33            Some(std::rc::Rc::new(
34                geo3d.transformed_3d(&Mat4::from_translation(d)),
35            ))
36        }))
37    }
38}