microcad_core/geo2d/
mod.rs

1// Copyright © 2024-2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! 2D Geometry
5
6mod align;
7mod bounds;
8mod circle;
9mod collection;
10mod geometry;
11mod line;
12mod primitives;
13mod reflect;
14mod size;
15
16use crate::*;
17
18pub use align::*;
19pub use bounds::*;
20pub use circle::*;
21pub use collection::*;
22use geo::AffineTransform;
23pub use geometry::*;
24pub use line::*;
25pub use primitives::*;
26pub use reflect::*;
27pub use size::*;
28
29/// Trait to return all points of 2D geometry.
30pub trait FetchPoints2D {
31    /// Returns all points.
32    fn fetch_points_2d(&self) -> Vec<Vec2>;
33}
34
35/// Transformed version of a 2D geometry.
36pub trait Transformed2D<T = Self> {
37    /// Transform from matrix.
38    fn transformed_2d(&self, mat: &Mat3) -> T;
39}
40
41/// Convert a [`Mat3`]` into an affine transform.
42pub(crate) fn mat3_to_affine_transform(mat: &Mat3) -> AffineTransform {
43    geo::AffineTransform::new(mat.x.x, mat.y.x, mat.z.x, mat.x.y, mat.y.y, mat.z.y)
44}
45
46/// Iterator over `n` points of a regular convex polygon (Ngon).
47pub struct NgonIterator {
48    /// Number of points.
49    n: u32,
50    /// Current point.
51    i: u32,
52}
53
54impl NgonIterator {
55    /// Create new iterator.
56    pub fn new(n: u32) -> Self {
57        Self { n, i: 0 }
58    }
59}
60
61impl Iterator for NgonIterator {
62    type Item = geo::Coord<Scalar>;
63
64    fn next(&mut self) -> Option<Self::Item> {
65        if self.i < self.n {
66            use std::f64::consts::PI;
67            let angle = 2.0 * PI * (self.i as f64) / (self.n as f64);
68            self.i += 1;
69            Some(geo::coord! {x: angle.cos(), y: angle.sin() })
70        } else {
71            None
72        }
73    }
74}
75
76/// An iterator that iterates over grid cells of a rectangle.
77pub struct GridCells {
78    rect: Rect,
79    rows: Integer,
80    columns: Integer,
81    current: Integer,
82}
83
84impl GridCells {
85    /// Construct new grid cell iterator.
86    pub fn new(rect: Rect, rows: Integer, columns: Integer) -> Self {
87        Self {
88            rect,
89            rows,
90            columns,
91            current: 0,
92        }
93    }
94}
95
96impl Iterator for GridCells {
97    type Item = Rect;
98
99    fn next(&mut self) -> Option<Self::Item> {
100        if self.current >= self.rows * self.columns {
101            return None;
102        }
103
104        let cell_width = self.rect.width() / self.columns as Scalar;
105        let cell_height = self.rect.height() / self.rows as Scalar;
106
107        let row = self.current / self.columns;
108        let col = self.current % self.columns;
109        let x = self.rect.min().x + col as Scalar * cell_width;
110        let y = self.rect.min().y + row as Scalar * cell_height;
111
112        self.current += 1;
113
114        Some(Rect::new(
115            geo::coord! {x: x, y: y},
116            geo::coord! {x: x + cell_width, y: y + cell_height},
117        ))
118    }
119}