microcad_core/geo2d/
primitives.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! 2D primitives
5
6use geo::AffineOps;
7
8use crate::{geo2d::*, *};
9
10/// Line string.
11pub type LineString = geo::LineString<Scalar>;
12/// Multiple line strings.
13pub type MultiLineString = geo::MultiLineString<Scalar>;
14/// Polygon.
15pub type Polygon = geo::Polygon<Scalar>;
16/// Multiple polygons.
17pub type MultiPolygon = geo::MultiPolygon<Scalar>;
18/// Rectangle.
19pub type Rect = geo::Rect<Scalar>;
20/// Point.
21pub type Point = geo::Point<Scalar>;
22
23impl Transformed2D for LineString {
24    fn transformed_2d(&self, mat: &Mat3) -> Self {
25        self.affine_transform(&mat3_to_affine_transform(mat))
26    }
27}
28
29impl Transformed2D for MultiLineString {
30    fn transformed_2d(&self, mat: &Mat3) -> Self {
31        self.affine_transform(&mat3_to_affine_transform(mat))
32    }
33}
34
35impl Transformed2D for Polygon {
36    fn transformed_2d(&self, mat: &Mat3) -> Self {
37        self.affine_transform(&mat3_to_affine_transform(mat))
38    }
39}
40
41impl Transformed2D for MultiPolygon {
42    fn transformed_2d(&self, mat: &Mat3) -> Self {
43        self.affine_transform(&mat3_to_affine_transform(mat))
44    }
45}
46
47impl FetchPoints2D for Rect {
48    fn fetch_points_2d(&self) -> Vec<Vec2> {
49        let min = self.min();
50        let max = self.max();
51        vec![
52            Vec2::new(min.x, min.y),
53            Vec2::new(min.x, max.y),
54            Vec2::new(max.x, min.y),
55            Vec2::new(max.x, max.y),
56        ]
57    }
58}
59
60impl Transformed2D for Rect {
61    fn transformed_2d(&self, mat: &Mat3) -> Self {
62        self.affine_transform(&mat3_to_affine_transform(mat))
63    }
64}
65
66impl Transformed2D<Polygon> for Rect {
67    fn transformed_2d(&self, mat: &Mat3) -> Polygon {
68        self.to_polygon().transformed_2d(mat)
69    }
70}
71
72/// Convert a line string to a vector of [`Scalar`].
73pub fn line_string_to_vec(line_string: &LineString) -> Vec<Scalar> {
74    line_string
75        .points()
76        .flat_map(|point| vec![point.x(), point.y()])
77        .collect()
78}
79
80/// Convert a polygon to a vector of [`Scalar`].
81///
82/// Exterior polygon has CW winding order, interior polygon have CCW winding order.
83pub fn polygon_to_vec(polygon: &Polygon) -> Vec<Scalar> {
84    let mut vec = line_string_to_vec(polygon.exterior());
85    polygon.interiors().iter().for_each(|interior| {
86        vec.append(&mut line_string_to_vec(interior));
87    });
88    vec
89}
90
91/// Convert a multi polygon into a vector of coordinates.
92pub fn multi_polygon_to_vec(multi_polygon: &MultiPolygon) -> Vec<Vec<Scalar>> {
93    multi_polygon.0.iter().map(polygon_to_vec).collect()
94}