From efbe814cda19a03f8e0c172e18534c686dbd9931 Mon Sep 17 00:00:00 2001 From: Charles Thompson Date: Mon, 17 Nov 2025 05:07:10 -0500 Subject: [PATCH 1/7] Added origins to everything --- src/mesh/flatten_slice.rs | 2 ++ src/mesh/mod.rs | 9 +++++++++ src/mesh/vertex.rs | 6 ++++++ src/sketch/extrudes.rs | 2 ++ src/sketch/hershey.rs | 1 + src/sketch/mod.rs | 26 ++++++++++++++++++++++++++ src/sketch/offset.rs | 3 +++ src/sketch/shapes.rs | 1 + 8 files changed, 50 insertions(+) diff --git a/src/mesh/flatten_slice.rs b/src/mesh/flatten_slice.rs index 52b903a5..cb9f6900 100644 --- a/src/mesh/flatten_slice.rs +++ b/src/mesh/flatten_slice.rs @@ -69,6 +69,7 @@ impl Mesh { geometry: new_gc, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } @@ -154,6 +155,7 @@ impl Mesh { geometry: new_gc, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } } diff --git a/src/mesh/mod.rs b/src/mesh/mod.rs index 9db7e2b9..5b4c4109 100644 --- a/src/mesh/mod.rs +++ b/src/mesh/mod.rs @@ -57,6 +57,9 @@ pub struct Mesh { /// Metadata pub metadata: Option, + + /// Origin + pub origin: Vertex, } impl Mesh { @@ -80,6 +83,7 @@ impl Mesh { polygons: polys, bounding_box: std::sync::OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } } @@ -450,6 +454,7 @@ impl CSG for Mesh { polygons: Vec::new(), bounding_box: OnceLock::new(), metadata: None, + origin: Default::default(), } } @@ -492,6 +497,7 @@ impl CSG for Mesh { polygons: final_polys, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } @@ -546,6 +552,7 @@ impl CSG for Mesh { polygons: final_polys, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } @@ -578,6 +585,7 @@ impl CSG for Mesh { polygons: a.all_polygons(), bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } @@ -791,6 +799,7 @@ impl From> for Mesh { polygons: final_polygons, bounding_box: OnceLock::new(), metadata: None, + origin: sketch.origin, } } } diff --git a/src/mesh/vertex.rs b/src/mesh/vertex.rs index 22eb07e1..0790de7f 100644 --- a/src/mesh/vertex.rs +++ b/src/mesh/vertex.rs @@ -11,6 +11,12 @@ pub struct Vertex { pub normal: Vector3, } +impl Default for Vertex { + fn default() -> Self { + Vertex::new(Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 1.0)) + } +} + impl Vertex { /// Create a new [`Vertex`]. /// diff --git a/src/sketch/extrudes.rs b/src/sketch/extrudes.rs index 304a74b1..ebe94597 100644 --- a/src/sketch/extrudes.rs +++ b/src/sketch/extrudes.rs @@ -100,6 +100,7 @@ impl Sketch { polygons: out, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } @@ -810,6 +811,7 @@ impl Sketch { polygons: new_polygons, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, }) } diff --git a/src/sketch/hershey.rs b/src/sketch/hershey.rs index 564ccfc0..690bcd37 100644 --- a/src/sketch/hershey.rs +++ b/src/sketch/hershey.rs @@ -68,6 +68,7 @@ impl Sketch { geometry: geo_coll, bounding_box: OnceLock::new(), metadata, + origin: Default::default(), } } } diff --git a/src/sketch/mod.rs b/src/sketch/mod.rs index 4788ae41..c37be751 100644 --- a/src/sketch/mod.rs +++ b/src/sketch/mod.rs @@ -3,6 +3,7 @@ use crate::float_types::Real; use crate::float_types::parry3d::bounding_volume::Aabb; use crate::mesh::Mesh; +use crate::mesh::vertex::Vertex; use crate::traits::CSG; use geo::algorithm::winding_order::Winding; use geo::{ @@ -42,6 +43,9 @@ pub struct Sketch { /// Metadata pub metadata: Option, + + /// Origin of the sketch in 3D space + pub origin: Vertex, } impl Sketch { @@ -209,8 +213,23 @@ impl Sketch { geometry: GeometryCollection(oriented_geoms), bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } + + #[inline] + /// Set the origin of a Sketch + pub fn set_origin(&mut self, origin: Vertex) { + self.origin = origin; + } + + #[inline] + /// Specifies the origin during creation of a Sketch. + pub fn origin(mut self, origin: Vertex) -> Self { + self.set_origin(origin); + + self + } } impl CSG for Sketch { @@ -220,6 +239,7 @@ impl CSG for Sketch { geometry: GeometryCollection::default(), bounding_box: OnceLock::new(), metadata: None, + origin: Default::default(), } } @@ -271,6 +291,7 @@ impl CSG for Sketch { geometry: final_gc, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } @@ -312,6 +333,7 @@ impl CSG for Sketch { geometry: final_gc, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } @@ -359,6 +381,7 @@ impl CSG for Sketch { geometry: final_gc, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } @@ -406,6 +429,7 @@ impl CSG for Sketch { geometry: final_gc, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } @@ -538,6 +562,7 @@ impl CSG for Sketch { geometry: GeometryCollection(oriented_geoms), bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } } @@ -594,6 +619,7 @@ impl From> for Sketch { geometry: new_gc, bounding_box: OnceLock::new(), metadata: None, + origin: mesh.origin, } } } diff --git a/src/sketch/offset.rs b/src/sketch/offset.rs index a649025d..bb371a15 100644 --- a/src/sketch/offset.rs +++ b/src/sketch/offset.rs @@ -215,6 +215,7 @@ impl Sketch { geometry: new_collection, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } @@ -298,6 +299,7 @@ impl Sketch { geometry: new_collection, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } @@ -336,6 +338,7 @@ impl Sketch { geometry: new_collection, bounding_box: OnceLock::new(), metadata: self.metadata.clone(), + origin: self.origin, } } } diff --git a/src/sketch/shapes.rs b/src/sketch/shapes.rs index c590fb70..c458b43c 100644 --- a/src/sketch/shapes.rs +++ b/src/sketch/shapes.rs @@ -605,6 +605,7 @@ impl Sketch { geometry: shape.geometry, bounding_box: OnceLock::new(), metadata, + origin: Default::default(), } } From 0647fefa55836b9f2ed512014b0b6541021a380e Mon Sep 17 00:00:00 2001 From: Charles Thompson Date: Tue, 18 Nov 2025 05:17:26 -0500 Subject: [PATCH 2/7] Added POC origin transformation --- src/mesh/vertex.rs | 1 + src/sketch/extrudes.rs | 50 ++++++++++++++++++++++---------------- src/sketch/mod.rs | 55 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 78 insertions(+), 28 deletions(-) diff --git a/src/mesh/vertex.rs b/src/mesh/vertex.rs index 0790de7f..1332808e 100644 --- a/src/mesh/vertex.rs +++ b/src/mesh/vertex.rs @@ -11,6 +11,7 @@ pub struct Vertex { pub normal: Vector3, } +/// Default to a position of (0, 0, 0) facing +Z impl Default for Vertex { fn default() -> Self { Vertex::new(Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, 0.0, 1.0)) diff --git a/src/sketch/extrudes.rs b/src/sketch/extrudes.rs index ebe94597..5e819b42 100644 --- a/src/sketch/extrudes.rs +++ b/src/sketch/extrudes.rs @@ -5,7 +5,7 @@ use crate::float_types::{Real, tolerance}; use crate::mesh::Mesh; use crate::mesh::polygon::Polygon; use crate::mesh::vertex::Vertex; -use crate::sketch::Sketch; +use crate::sketch::{OriginTransformVecQuat, Sketch, apply_origin_tranform}; use crate::traits::CSG; use geo::{Area, CoordsIter, LineString, Polygon as GeoPolygon}; use nalgebra::{Point3, Vector3}; @@ -13,6 +13,7 @@ use std::fmt::Debug; use std::sync::OnceLock; impl Sketch { + #[inline] /// Linearly extrude this (2D) shape in the +Z direction by `height`. /// /// This is just a convenience wrapper around extrude_vector using Vector3::new(0.0, 0.0, height) @@ -89,11 +90,14 @@ impl Sketch { return Mesh::new(); } + // !TODO! Find a way to avoid re-allocating so much // Collect 3-D polygons generated from every `geo` geometry in the sketch let mut out: Vec> = Vec::new(); + let origin_tranform = self.prepare_origin_vec_and_quat(); + for geom in &self.geometry { - Self::extrude_geometry(geom, direction, &self.metadata, &mut out); + Self::extrude_geometry(geom, direction, &origin_tranform, &self.metadata, &mut out); } Mesh { @@ -108,6 +112,7 @@ impl Sketch { fn extrude_geometry( geom: &geo::Geometry, direction: Vector3, + origin_tranform: &OriginTransformVecQuat, metadata: &Option, out_polygons: &mut Vec>, ) { @@ -128,9 +133,9 @@ impl Sketch { // bottom for tri in &tris { - let v0 = Vertex::new(tri[2], -Vector3::z()); - let v1 = Vertex::new(tri[1], -Vector3::z()); - let v2 = Vertex::new(tri[0], -Vector3::z()); + let v0 = apply_origin_tranform(Vertex::new(tri[2], -Vector3::z()), origin_tranform); + let v1 = apply_origin_tranform(Vertex::new(tri[1], -Vector3::z()), origin_tranform); + let v2 = apply_origin_tranform(Vertex::new(tri[0], -Vector3::z()), origin_tranform); out_polygons.push(Polygon::new(vec![v0, v1, v2], metadata.clone())); } // top @@ -138,9 +143,9 @@ impl Sketch { let p0 = tri[0] + direction; let p1 = tri[1] + direction; let p2 = tri[2] + direction; - let v0 = Vertex::new(p0, Vector3::z()); - let v1 = Vertex::new(p1, Vector3::z()); - let v2 = Vertex::new(p2, Vector3::z()); + let v0 = apply_origin_tranform(Vertex::new(p0, Vector3::z()), origin_tranform); + let v1 = apply_origin_tranform(Vertex::new(p1, Vector3::z()), origin_tranform); + let v2 = apply_origin_tranform(Vertex::new(p2, Vector3::z()), origin_tranform); out_polygons.push(Polygon::new(vec![v0, v1, v2], metadata.clone())); } @@ -157,10 +162,10 @@ impl Sketch { let t_j = b_j + direction; out_polygons.push(Polygon::new( vec![ - Vertex::new(b_i, Vector3::zeros()), - Vertex::new(b_j, Vector3::zeros()), - Vertex::new(t_j, Vector3::zeros()), - Vertex::new(t_i, Vector3::zeros()), + apply_origin_tranform(Vertex::new(b_i, Vector3::zeros()), origin_tranform), + apply_origin_tranform(Vertex::new(b_j, Vector3::zeros()), origin_tranform), + apply_origin_tranform(Vertex::new(t_j, Vector3::zeros()), origin_tranform), + apply_origin_tranform(Vertex::new(t_i, Vector3::zeros()), origin_tranform), ], metadata.clone(), )); @@ -172,6 +177,7 @@ impl Sketch { Self::extrude_geometry( &geo::Geometry::Polygon(poly.clone()), direction, + origin_tranform, metadata, out_polygons, ); @@ -179,7 +185,7 @@ impl Sketch { }, geo::Geometry::GeometryCollection(gc) => { for sub in &gc.0 { - Self::extrude_geometry(sub, direction, metadata, out_polygons); + Self::extrude_geometry(sub, direction, origin_tranform, metadata, out_polygons); } }, geo::Geometry::LineString(ls) => { @@ -196,10 +202,10 @@ impl Sketch { let normal = (b_j - b_i).cross(&(t_i - b_i)).normalize(); out_polygons.push(Polygon::new( vec![ - Vertex::new(b_i, normal), - Vertex::new(b_j, normal), - Vertex::new(t_j, normal), - Vertex::new(t_i, normal), + apply_origin_tranform(Vertex::new(b_i, normal), origin_tranform), + apply_origin_tranform(Vertex::new(b_j, normal), origin_tranform), + apply_origin_tranform(Vertex::new(t_j, normal), origin_tranform), + apply_origin_tranform(Vertex::new(t_i, normal), origin_tranform), ], metadata.clone(), )); @@ -216,10 +222,10 @@ impl Sketch { let normal = (b1 - b0).cross(&(t0 - b0)).normalize(); out_polygons.push(Polygon::new( vec![ - Vertex::new(b0, normal), - Vertex::new(b1, normal), - Vertex::new(t1, normal), - Vertex::new(t0, normal), + apply_origin_tranform(Vertex::new(b0, normal), origin_tranform), + apply_origin_tranform(Vertex::new(b1, normal), origin_tranform), + apply_origin_tranform(Vertex::new(t1, normal), origin_tranform), + apply_origin_tranform(Vertex::new(t0, normal), origin_tranform), ], metadata.clone(), )); @@ -231,6 +237,7 @@ impl Sketch { Self::extrude_geometry( &geo::Geometry::Polygon(poly2d), direction, + origin_tranform, metadata, out_polygons, ); @@ -242,6 +249,7 @@ impl Sketch { Self::extrude_geometry( &geo::Geometry::Polygon(poly2d), direction, + origin_tranform, metadata, out_polygons, ); diff --git a/src/sketch/mod.rs b/src/sketch/mod.rs index c37be751..cd0d5c6f 100644 --- a/src/sketch/mod.rs +++ b/src/sketch/mod.rs @@ -11,7 +11,7 @@ use geo::{ Geometry, GeometryCollection, LineString, MultiPolygon, Orient, Polygon as GeoPolygon, Rect, orient::Direction, }; -use nalgebra::{Matrix4, Point3, partial_max, partial_min}; +use nalgebra::{Matrix4, Point3, UnitQuaternion, Vector3, partial_max, partial_min}; use std::fmt::Debug; use std::sync::OnceLock; @@ -33,6 +33,28 @@ pub mod offset; #[cfg(feature = "truetype-text")] pub mod truetype; +pub(crate) type OriginTransformVecQuat = (Vector3, (UnitQuaternion, Option>)); + +#[inline] +pub(crate) fn apply_origin_tranform(in_vertex: Vertex, origin_tranform: &OriginTransformVecQuat) -> Vertex { + let (pos_transform, rotation_quats) = origin_tranform; + let (quat1, quat2) = rotation_quats; + + let mut out_vertex = Vertex::default(); + + out_vertex.pos = in_vertex.pos + pos_transform; + + out_vertex.pos.coords = quat1 * in_vertex.pos.coords; + out_vertex.normal = quat1 * in_vertex.normal; + + if let Some(quat2) = quat2 { + out_vertex.pos.coords = quat2 * in_vertex.pos.coords; + out_vertex.normal = quat2 * in_vertex.normal; + } + + out_vertex +} + #[derive(Clone, Debug)] pub struct Sketch { /// 2D points, lines, polylines, polygons, and multipolygons @@ -218,17 +240,36 @@ impl Sketch { } #[inline] - /// Set the origin of a Sketch - pub fn set_origin(&mut self, origin: Vertex) { + /// Specifies the origin during creation of a Sketch. + pub fn origin(mut self, origin: Vertex) -> Self { self.origin = origin; + + self } #[inline] - /// Specifies the origin during creation of a Sketch. - pub fn origin(mut self, origin: Vertex) -> Self { - self.set_origin(origin); + /// Prepares the vector and quaternion needed to move all the points of + /// a mesh generated by this sketch to the origin + pub(crate) fn prepare_origin_vec_and_quat(&self) -> OriginTransformVecQuat { + let origin = &self.origin; + let default_origin = Vertex::default(); - self + let pos_transform = origin.pos - default_origin.pos; + + let rotation_quats = match UnitQuaternion::rotation_between(&default_origin.normal, &origin.normal) { + Some(quat) => (quat, None), + None => { + // Assumes the default normal is +Z. We'll do +Y + let inter_origin = Vector3::new(0.0, 1.0, 0.0); + + let quat1 = UnitQuaternion::rotation_between(&default_origin.normal, &inter_origin).unwrap(); + let quat2 = UnitQuaternion::rotation_between(&inter_origin, &origin.normal).unwrap(); + + (quat1, Some(quat2)) + } + }; + + (pos_transform, rotation_quats) } } From 0f1f57f077668f727122a07279a353ce7530debb Mon Sep 17 00:00:00 2001 From: Charles Thompson Date: Tue, 18 Nov 2025 05:22:12 -0500 Subject: [PATCH 3/7] Fixed transformation bug --- src/sketch/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sketch/mod.rs b/src/sketch/mod.rs index cd0d5c6f..51316564 100644 --- a/src/sketch/mod.rs +++ b/src/sketch/mod.rs @@ -42,8 +42,6 @@ pub(crate) fn apply_origin_tranform(in_vertex: Vertex, origin_tranform: &OriginT let mut out_vertex = Vertex::default(); - out_vertex.pos = in_vertex.pos + pos_transform; - out_vertex.pos.coords = quat1 * in_vertex.pos.coords; out_vertex.normal = quat1 * in_vertex.normal; @@ -51,6 +49,8 @@ pub(crate) fn apply_origin_tranform(in_vertex: Vertex, origin_tranform: &OriginT out_vertex.pos.coords = quat2 * in_vertex.pos.coords; out_vertex.normal = quat2 * in_vertex.normal; } + + out_vertex.pos.coords += pos_transform; out_vertex } From 724d9447dc9fddf8de750ce7aa9aa9bcb959bb04 Mon Sep 17 00:00:00 2001 From: Charles thompson Date: Tue, 18 Nov 2025 07:04:44 -0500 Subject: [PATCH 4/7] Integrated origin transform calculation into sketch struct --- src/mesh/flatten_slice.rs | 2 ++ src/sketch/extrudes.rs | 6 ++---- src/sketch/hershey.rs | 1 + src/sketch/mod.rs | 30 ++++++++++++++++++++++++------ src/sketch/offset.rs | 3 +++ src/sketch/shapes.rs | 1 + 6 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/mesh/flatten_slice.rs b/src/mesh/flatten_slice.rs index cb9f6900..0e8119f7 100644 --- a/src/mesh/flatten_slice.rs +++ b/src/mesh/flatten_slice.rs @@ -70,6 +70,7 @@ impl Mesh { bounding_box: OnceLock::new(), metadata: self.metadata.clone(), origin: self.origin, + origin_transform: Sketch::::prepare_origin_vec_and_quat(self.origin), } } @@ -156,6 +157,7 @@ impl Mesh { bounding_box: OnceLock::new(), metadata: self.metadata.clone(), origin: self.origin, + origin_transform: Sketch::::prepare_origin_vec_and_quat(self.origin), } } } diff --git a/src/sketch/extrudes.rs b/src/sketch/extrudes.rs index 5e819b42..81763004 100644 --- a/src/sketch/extrudes.rs +++ b/src/sketch/extrudes.rs @@ -94,10 +94,8 @@ impl Sketch { // Collect 3-D polygons generated from every `geo` geometry in the sketch let mut out: Vec> = Vec::new(); - let origin_tranform = self.prepare_origin_vec_and_quat(); - for geom in &self.geometry { - Self::extrude_geometry(geom, direction, &origin_tranform, &self.metadata, &mut out); + Self::extrude_geometry(geom, direction, self.origin_transform, &self.metadata, &mut out); } Mesh { @@ -112,7 +110,7 @@ impl Sketch { fn extrude_geometry( geom: &geo::Geometry, direction: Vector3, - origin_tranform: &OriginTransformVecQuat, + origin_tranform: OriginTransformVecQuat, metadata: &Option, out_polygons: &mut Vec>, ) { diff --git a/src/sketch/hershey.rs b/src/sketch/hershey.rs index 690bcd37..3b51df31 100644 --- a/src/sketch/hershey.rs +++ b/src/sketch/hershey.rs @@ -69,6 +69,7 @@ impl Sketch { bounding_box: OnceLock::new(), metadata, origin: Default::default(), + origin_transform: Sketch::::prepare_origin_vec_and_quat(Default::default()), } } } diff --git a/src/sketch/mod.rs b/src/sketch/mod.rs index 51316564..8db4a223 100644 --- a/src/sketch/mod.rs +++ b/src/sketch/mod.rs @@ -36,7 +36,7 @@ pub mod truetype; pub(crate) type OriginTransformVecQuat = (Vector3, (UnitQuaternion, Option>)); #[inline] -pub(crate) fn apply_origin_tranform(in_vertex: Vertex, origin_tranform: &OriginTransformVecQuat) -> Vertex { +pub(crate) fn apply_origin_tranform(in_vertex: Vertex, origin_tranform: OriginTransformVecQuat) -> Vertex { let (pos_transform, rotation_quats) = origin_tranform; let (quat1, quat2) = rotation_quats; @@ -66,8 +66,12 @@ pub struct Sketch { /// Metadata pub metadata: Option, - /// Origin of the sketch in 3D space - pub origin: Vertex, + /// Origin of the sketch in 3D space. + /// Not public due to needing to update the origin transform each time + /// the origin is set. + pub(crate) origin: Vertex, + + pub(crate) origin_transform: OriginTransformVecQuat, } impl Sketch { @@ -236,13 +240,21 @@ impl Sketch { bounding_box: OnceLock::new(), metadata: self.metadata.clone(), origin: self.origin, + origin_transform: self.origin_transform, } } + #[inline] + /// Set the origin of the sketch. + pub fn set_origin(&mut self, origin: Vertex) { + self.origin_transform = Self::prepare_origin_vec_and_quat(origin); + self.origin = origin; + } + #[inline] /// Specifies the origin during creation of a Sketch. pub fn origin(mut self, origin: Vertex) -> Self { - self.origin = origin; + self.set_origin(origin); self } @@ -250,8 +262,7 @@ impl Sketch { #[inline] /// Prepares the vector and quaternion needed to move all the points of /// a mesh generated by this sketch to the origin - pub(crate) fn prepare_origin_vec_and_quat(&self) -> OriginTransformVecQuat { - let origin = &self.origin; + pub(crate) fn prepare_origin_vec_and_quat(origin: Vertex) -> OriginTransformVecQuat { let default_origin = Vertex::default(); let pos_transform = origin.pos - default_origin.pos; @@ -281,6 +292,7 @@ impl CSG for Sketch { bounding_box: OnceLock::new(), metadata: None, origin: Default::default(), + origin_transform: Self::prepare_origin_vec_and_quat(Vertex::default()), } } @@ -333,6 +345,7 @@ impl CSG for Sketch { bounding_box: OnceLock::new(), metadata: self.metadata.clone(), origin: self.origin, + origin_transform: self.origin_transform, } } @@ -375,6 +388,7 @@ impl CSG for Sketch { bounding_box: OnceLock::new(), metadata: self.metadata.clone(), origin: self.origin, + origin_transform: self.origin_transform, } } @@ -423,6 +437,7 @@ impl CSG for Sketch { bounding_box: OnceLock::new(), metadata: self.metadata.clone(), origin: self.origin, + origin_transform: self.origin_transform, } } @@ -471,6 +486,7 @@ impl CSG for Sketch { bounding_box: OnceLock::new(), metadata: self.metadata.clone(), origin: self.origin, + origin_transform: self.origin_transform, } } @@ -604,6 +620,7 @@ impl CSG for Sketch { bounding_box: OnceLock::new(), metadata: self.metadata.clone(), origin: self.origin, + origin_transform: self.origin_transform, } } } @@ -661,6 +678,7 @@ impl From> for Sketch { bounding_box: OnceLock::new(), metadata: None, origin: mesh.origin, + origin_transform: Self::prepare_origin_vec_and_quat(mesh.origin), } } } diff --git a/src/sketch/offset.rs b/src/sketch/offset.rs index bb371a15..15de1647 100644 --- a/src/sketch/offset.rs +++ b/src/sketch/offset.rs @@ -216,6 +216,7 @@ impl Sketch { bounding_box: OnceLock::new(), metadata: self.metadata.clone(), origin: self.origin, + origin_transform: self.origin_transform, } } @@ -300,6 +301,7 @@ impl Sketch { bounding_box: OnceLock::new(), metadata: self.metadata.clone(), origin: self.origin, + origin_transform: self.origin_transform, } } @@ -339,6 +341,7 @@ impl Sketch { bounding_box: OnceLock::new(), metadata: self.metadata.clone(), origin: self.origin, + origin_transform: self.origin_transform, } } } diff --git a/src/sketch/shapes.rs b/src/sketch/shapes.rs index c458b43c..2014ca2a 100644 --- a/src/sketch/shapes.rs +++ b/src/sketch/shapes.rs @@ -606,6 +606,7 @@ impl Sketch { bounding_box: OnceLock::new(), metadata, origin: Default::default(), + origin_transform: Sketch::::prepare_origin_vec_and_quat(Default::default()), } } From c45f2359d4f5b65e1d056c2cc0bdb73c6fbb6d16 Mon Sep 17 00:00:00 2001 From: Charles thompson Date: Tue, 18 Nov 2025 07:18:06 -0500 Subject: [PATCH 5/7] Changed transform from inline function to macro and fixed typos --- src/sketch/extrudes.rs | 49 +++++++++++++++++++++--------------------- src/sketch/mod.rs | 32 +++++++++++++++------------ 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/sketch/extrudes.rs b/src/sketch/extrudes.rs index 81763004..350a5942 100644 --- a/src/sketch/extrudes.rs +++ b/src/sketch/extrudes.rs @@ -5,7 +5,8 @@ use crate::float_types::{Real, tolerance}; use crate::mesh::Mesh; use crate::mesh::polygon::Polygon; use crate::mesh::vertex::Vertex; -use crate::sketch::{OriginTransformVecQuat, Sketch, apply_origin_tranform}; +use crate::sketch::{OriginTransformVecQuat, Sketch}; +use crate::apply_origin_transform; use crate::traits::CSG; use geo::{Area, CoordsIter, LineString, Polygon as GeoPolygon}; use nalgebra::{Point3, Vector3}; @@ -110,7 +111,7 @@ impl Sketch { fn extrude_geometry( geom: &geo::Geometry, direction: Vector3, - origin_tranform: OriginTransformVecQuat, + origin_transform: OriginTransformVecQuat, metadata: &Option, out_polygons: &mut Vec>, ) { @@ -131,9 +132,9 @@ impl Sketch { // bottom for tri in &tris { - let v0 = apply_origin_tranform(Vertex::new(tri[2], -Vector3::z()), origin_tranform); - let v1 = apply_origin_tranform(Vertex::new(tri[1], -Vector3::z()), origin_tranform); - let v2 = apply_origin_tranform(Vertex::new(tri[0], -Vector3::z()), origin_tranform); + let v0 = apply_origin_transform!(Vertex::new(tri[2], -Vector3::z()), origin_transform); + let v1 = apply_origin_transform!(Vertex::new(tri[1], -Vector3::z()), origin_transform); + let v2 = apply_origin_transform!(Vertex::new(tri[0], -Vector3::z()), origin_transform); out_polygons.push(Polygon::new(vec![v0, v1, v2], metadata.clone())); } // top @@ -141,9 +142,9 @@ impl Sketch { let p0 = tri[0] + direction; let p1 = tri[1] + direction; let p2 = tri[2] + direction; - let v0 = apply_origin_tranform(Vertex::new(p0, Vector3::z()), origin_tranform); - let v1 = apply_origin_tranform(Vertex::new(p1, Vector3::z()), origin_tranform); - let v2 = apply_origin_tranform(Vertex::new(p2, Vector3::z()), origin_tranform); + let v0 = apply_origin_transform!(Vertex::new(p0, Vector3::z()), origin_transform); + let v1 = apply_origin_transform!(Vertex::new(p1, Vector3::z()), origin_transform); + let v2 = apply_origin_transform!(Vertex::new(p2, Vector3::z()), origin_transform); out_polygons.push(Polygon::new(vec![v0, v1, v2], metadata.clone())); } @@ -160,10 +161,10 @@ impl Sketch { let t_j = b_j + direction; out_polygons.push(Polygon::new( vec![ - apply_origin_tranform(Vertex::new(b_i, Vector3::zeros()), origin_tranform), - apply_origin_tranform(Vertex::new(b_j, Vector3::zeros()), origin_tranform), - apply_origin_tranform(Vertex::new(t_j, Vector3::zeros()), origin_tranform), - apply_origin_tranform(Vertex::new(t_i, Vector3::zeros()), origin_tranform), + apply_origin_transform!(Vertex::new(b_i, Vector3::zeros()), origin_transform), + apply_origin_transform!(Vertex::new(b_j, Vector3::zeros()), origin_transform), + apply_origin_transform!(Vertex::new(t_j, Vector3::zeros()), origin_transform), + apply_origin_transform!(Vertex::new(t_i, Vector3::zeros()), origin_transform), ], metadata.clone(), )); @@ -175,7 +176,7 @@ impl Sketch { Self::extrude_geometry( &geo::Geometry::Polygon(poly.clone()), direction, - origin_tranform, + origin_transform, metadata, out_polygons, ); @@ -183,7 +184,7 @@ impl Sketch { }, geo::Geometry::GeometryCollection(gc) => { for sub in &gc.0 { - Self::extrude_geometry(sub, direction, origin_tranform, metadata, out_polygons); + Self::extrude_geometry(sub, direction, origin_transform, metadata, out_polygons); } }, geo::Geometry::LineString(ls) => { @@ -200,10 +201,10 @@ impl Sketch { let normal = (b_j - b_i).cross(&(t_i - b_i)).normalize(); out_polygons.push(Polygon::new( vec![ - apply_origin_tranform(Vertex::new(b_i, normal), origin_tranform), - apply_origin_tranform(Vertex::new(b_j, normal), origin_tranform), - apply_origin_tranform(Vertex::new(t_j, normal), origin_tranform), - apply_origin_tranform(Vertex::new(t_i, normal), origin_tranform), + apply_origin_transform!(Vertex::new(b_i, normal), origin_transform), + apply_origin_transform!(Vertex::new(b_j, normal), origin_transform), + apply_origin_transform!(Vertex::new(t_j, normal), origin_transform), + apply_origin_transform!(Vertex::new(t_i, normal), origin_transform), ], metadata.clone(), )); @@ -220,10 +221,10 @@ impl Sketch { let normal = (b1 - b0).cross(&(t0 - b0)).normalize(); out_polygons.push(Polygon::new( vec![ - apply_origin_tranform(Vertex::new(b0, normal), origin_tranform), - apply_origin_tranform(Vertex::new(b1, normal), origin_tranform), - apply_origin_tranform(Vertex::new(t1, normal), origin_tranform), - apply_origin_tranform(Vertex::new(t0, normal), origin_tranform), + apply_origin_transform!(Vertex::new(b0, normal), origin_transform), + apply_origin_transform!(Vertex::new(b1, normal), origin_transform), + apply_origin_transform!(Vertex::new(t1, normal), origin_transform), + apply_origin_transform!(Vertex::new(t0, normal), origin_transform), ], metadata.clone(), )); @@ -235,7 +236,7 @@ impl Sketch { Self::extrude_geometry( &geo::Geometry::Polygon(poly2d), direction, - origin_tranform, + origin_transform, metadata, out_polygons, ); @@ -247,7 +248,7 @@ impl Sketch { Self::extrude_geometry( &geo::Geometry::Polygon(poly2d), direction, - origin_tranform, + origin_transform, metadata, out_polygons, ); diff --git a/src/sketch/mod.rs b/src/sketch/mod.rs index 8db4a223..c8a8a023 100644 --- a/src/sketch/mod.rs +++ b/src/sketch/mod.rs @@ -35,24 +35,28 @@ pub mod truetype; pub(crate) type OriginTransformVecQuat = (Vector3, (UnitQuaternion, Option>)); -#[inline] -pub(crate) fn apply_origin_tranform(in_vertex: Vertex, origin_tranform: OriginTransformVecQuat) -> Vertex { - let (pos_transform, rotation_quats) = origin_tranform; - let (quat1, quat2) = rotation_quats; +#[macro_export] +macro_rules! apply_origin_transform { + ($in_vertex:expr, $origin_transform:expr) => { + { + let (pos_transform, rotation_quats) = $origin_transform; + let (quat1, quat2) = rotation_quats; - let mut out_vertex = Vertex::default(); + let mut out_vertex = Vertex::default(); - out_vertex.pos.coords = quat1 * in_vertex.pos.coords; - out_vertex.normal = quat1 * in_vertex.normal; + out_vertex.pos.coords = quat1 * $in_vertex.pos.coords; + out_vertex.normal = quat1 * $in_vertex.normal; - if let Some(quat2) = quat2 { - out_vertex.pos.coords = quat2 * in_vertex.pos.coords; - out_vertex.normal = quat2 * in_vertex.normal; - } - - out_vertex.pos.coords += pos_transform; + if let Some(quat2) = quat2 { + out_vertex.pos.coords = quat2 * $in_vertex.pos.coords; + out_vertex.normal = quat2 * $in_vertex.normal; + } + + out_vertex.pos.coords += pos_transform; - out_vertex + out_vertex + } + }; } #[derive(Clone, Debug)] From acff8355c159f867fc0c7cb7674a562ac071142c Mon Sep 17 00:00:00 2001 From: Charles thompson Date: Tue, 18 Nov 2025 12:32:13 -0500 Subject: [PATCH 6/7] Added code to enable 3D rendering of sketches --- src/sketch/extrudes.rs | 88 ++++++++++++--- src/sketch/mod.rs | 239 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 284 insertions(+), 43 deletions(-) diff --git a/src/sketch/extrudes.rs b/src/sketch/extrudes.rs index 350a5942..894beb1c 100644 --- a/src/sketch/extrudes.rs +++ b/src/sketch/extrudes.rs @@ -1,12 +1,12 @@ //! Functions to extrude, revolve, loft, and otherwise transform 2D `Sketch`s into 3D `Mesh`s +use crate::apply_origin_transform; use crate::errors::ValidationError; use crate::float_types::{Real, tolerance}; use crate::mesh::Mesh; use crate::mesh::polygon::Polygon; use crate::mesh::vertex::Vertex; use crate::sketch::{OriginTransformVecQuat, Sketch}; -use crate::apply_origin_transform; use crate::traits::CSG; use geo::{Area, CoordsIter, LineString, Polygon as GeoPolygon}; use nalgebra::{Point3, Vector3}; @@ -96,7 +96,13 @@ impl Sketch { let mut out: Vec> = Vec::new(); for geom in &self.geometry { - Self::extrude_geometry(geom, direction, self.origin_transform, &self.metadata, &mut out); + Self::extrude_geometry( + geom, + direction, + self.origin_transform, + &self.metadata, + &mut out, + ); } Mesh { @@ -132,9 +138,18 @@ impl Sketch { // bottom for tri in &tris { - let v0 = apply_origin_transform!(Vertex::new(tri[2], -Vector3::z()), origin_transform); - let v1 = apply_origin_transform!(Vertex::new(tri[1], -Vector3::z()), origin_transform); - let v2 = apply_origin_transform!(Vertex::new(tri[0], -Vector3::z()), origin_transform); + let v0 = apply_origin_transform!( + Vertex::new(tri[2], -Vector3::z()), + origin_transform + ); + let v1 = apply_origin_transform!( + Vertex::new(tri[1], -Vector3::z()), + origin_transform + ); + let v2 = apply_origin_transform!( + Vertex::new(tri[0], -Vector3::z()), + origin_transform + ); out_polygons.push(Polygon::new(vec![v0, v1, v2], metadata.clone())); } // top @@ -142,9 +157,18 @@ impl Sketch { let p0 = tri[0] + direction; let p1 = tri[1] + direction; let p2 = tri[2] + direction; - let v0 = apply_origin_transform!(Vertex::new(p0, Vector3::z()), origin_transform); - let v1 = apply_origin_transform!(Vertex::new(p1, Vector3::z()), origin_transform); - let v2 = apply_origin_transform!(Vertex::new(p2, Vector3::z()), origin_transform); + let v0 = apply_origin_transform!( + Vertex::new(p0, Vector3::z()), + origin_transform + ); + let v1 = apply_origin_transform!( + Vertex::new(p1, Vector3::z()), + origin_transform + ); + let v2 = apply_origin_transform!( + Vertex::new(p2, Vector3::z()), + origin_transform + ); out_polygons.push(Polygon::new(vec![v0, v1, v2], metadata.clone())); } @@ -161,10 +185,22 @@ impl Sketch { let t_j = b_j + direction; out_polygons.push(Polygon::new( vec![ - apply_origin_transform!(Vertex::new(b_i, Vector3::zeros()), origin_transform), - apply_origin_transform!(Vertex::new(b_j, Vector3::zeros()), origin_transform), - apply_origin_transform!(Vertex::new(t_j, Vector3::zeros()), origin_transform), - apply_origin_transform!(Vertex::new(t_i, Vector3::zeros()), origin_transform), + apply_origin_transform!( + Vertex::new(b_i, Vector3::zeros()), + origin_transform + ), + apply_origin_transform!( + Vertex::new(b_j, Vector3::zeros()), + origin_transform + ), + apply_origin_transform!( + Vertex::new(t_j, Vector3::zeros()), + origin_transform + ), + apply_origin_transform!( + Vertex::new(t_i, Vector3::zeros()), + origin_transform + ), ], metadata.clone(), )); @@ -184,7 +220,13 @@ impl Sketch { }, geo::Geometry::GeometryCollection(gc) => { for sub in &gc.0 { - Self::extrude_geometry(sub, direction, origin_transform, metadata, out_polygons); + Self::extrude_geometry( + sub, + direction, + origin_transform, + metadata, + out_polygons, + ); } }, geo::Geometry::LineString(ls) => { @@ -201,10 +243,22 @@ impl Sketch { let normal = (b_j - b_i).cross(&(t_i - b_i)).normalize(); out_polygons.push(Polygon::new( vec![ - apply_origin_transform!(Vertex::new(b_i, normal), origin_transform), - apply_origin_transform!(Vertex::new(b_j, normal), origin_transform), - apply_origin_transform!(Vertex::new(t_j, normal), origin_transform), - apply_origin_transform!(Vertex::new(t_i, normal), origin_transform), + apply_origin_transform!( + Vertex::new(b_i, normal), + origin_transform + ), + apply_origin_transform!( + Vertex::new(b_j, normal), + origin_transform + ), + apply_origin_transform!( + Vertex::new(t_j, normal), + origin_transform + ), + apply_origin_transform!( + Vertex::new(t_i, normal), + origin_transform + ), ], metadata.clone(), )); diff --git a/src/sketch/mod.rs b/src/sketch/mod.rs index c8a8a023..2baf3a66 100644 --- a/src/sketch/mod.rs +++ b/src/sketch/mod.rs @@ -5,6 +5,7 @@ use crate::float_types::parry3d::bounding_volume::Aabb; use crate::mesh::Mesh; use crate::mesh::vertex::Vertex; use crate::traits::CSG; +use geo::Line; use geo::algorithm::winding_order::Winding; use geo::{ AffineOps, AffineTransform, BooleanOps as GeoBooleanOps, BoundingRect, Coord, CoordsIter, @@ -33,30 +34,93 @@ pub mod offset; #[cfg(feature = "truetype-text")] pub mod truetype; -pub(crate) type OriginTransformVecQuat = (Vector3, (UnitQuaternion, Option>)); +pub(crate) type OriginTransformVecQuat = ( + Vector3, + (UnitQuaternion, Option>), +); #[macro_export] macro_rules! apply_origin_transform { - ($in_vertex:expr, $origin_transform:expr) => { - { - let (pos_transform, rotation_quats) = $origin_transform; - let (quat1, quat2) = rotation_quats; + ($in_vertex:expr, $origin_transform:expr) => {{ + let (pos_transform, rotation_quats) = $origin_transform; + let (quat1, quat2) = rotation_quats; - let mut out_vertex = Vertex::default(); + let mut out_vertex = Vertex::default(); - out_vertex.pos.coords = quat1 * $in_vertex.pos.coords; - out_vertex.normal = quat1 * $in_vertex.normal; + out_vertex.pos.coords = quat1 * $in_vertex.pos.coords; + out_vertex.normal = quat1 * $in_vertex.normal; - if let Some(quat2) = quat2 { - out_vertex.pos.coords = quat2 * $in_vertex.pos.coords; - out_vertex.normal = quat2 * $in_vertex.normal; - } - - out_vertex.pos.coords += pos_transform; + if let Some(quat2) = quat2 { + out_vertex.pos.coords = quat2 * $in_vertex.pos.coords; + out_vertex.normal = quat2 * $in_vertex.normal; + } + + out_vertex.pos.coords += pos_transform; + + out_vertex + }}; +} + +macro_rules! apply_origin_transform_graphicpoint { + ($in_point:expr, $origin_transform:expr) => {{ + let (pos_transform, rotation_quats) = $origin_transform; + let (quat1, quat2) = rotation_quats; + + let mut out_point = Point3::new(0.0, 0.0, 0.0); + + out_point.coords = quat1 * $in_point.coords; + + if let Some(quat2) = quat2 { + out_point.coords = quat2 * $in_point.coords; + } + + out_point.coords += pos_transform; + + out_point + }}; +} + +#[derive(Debug, Clone)] +/// String of line points for rendering in 3D space +pub struct GraphicLineString { + pub points: Vec<[f32; 3]>, +} + +impl GraphicLineString { + /// Get the total number of individual lines that can be made with the + /// line string + pub fn line_count(&self) -> usize { + let point_count = self.points.len(); + + if point_count == 0 { + return 0; + } + + let line_count = point_count - 1; + + line_count + } +} - out_vertex +#[derive(Debug, Clone)] +/// Collection of independent graphic line strings +pub struct GraphicLineStrings { + pub line_strings: Vec, +} + +impl GraphicLineStrings { + /// Get the total number of individual lines that can be made with all of + /// the line strings. Iterates through each line string stored so can get + /// expensive + pub fn total_line_count(&self) -> usize { + let mut total_line_count = 0; + + for line_string in &self.line_strings { + total_line_count += line_string.line_count(); } - }; + + total_line_count + } } #[derive(Clone, Debug)] @@ -263,7 +327,6 @@ impl Sketch { self } - #[inline] /// Prepares the vector and quaternion needed to move all the points of /// a mesh generated by this sketch to the origin pub(crate) fn prepare_origin_vec_and_quat(origin: Vertex) -> OriginTransformVecQuat { @@ -271,20 +334,144 @@ impl Sketch { let pos_transform = origin.pos - default_origin.pos; - let rotation_quats = match UnitQuaternion::rotation_between(&default_origin.normal, &origin.normal) { - Some(quat) => (quat, None), - None => { - // Assumes the default normal is +Z. We'll do +Y - let inter_origin = Vector3::new(0.0, 1.0, 0.0); + let rotation_quats = + match UnitQuaternion::rotation_between(&default_origin.normal, &origin.normal) { + Some(quat) => (quat, None), + None => { + // Assumes the default normal is +Z. We'll do +Y + let inter_origin = Vector3::new(0.0, 1.0, 0.0); + + let quat1 = UnitQuaternion::rotation_between( + &default_origin.normal, + &inter_origin, + ) + .unwrap(); + let quat2 = + UnitQuaternion::rotation_between(&inter_origin, &origin.normal) + .unwrap(); + + (quat1, Some(quat2)) + }, + }; + + (pos_transform, rotation_quats) + } + + /// Create graphic line strings from the edges of the sketch + pub fn build_graphic_line_strings(&self) -> GraphicLineStrings { + let mut graphic_line_strings = Vec::new(); + for geometry in &self.geometry { + match geometry { + Geometry::Polygon(polygon) => { + graphic_line_strings + .push(self.line_string_to_graphic_line_string(polygon.exterior())); + }, + Geometry::Line(line) => { + let start_point = + Point3::new(line.start.x as f32, line.start.y as f32, 0.0); + let end_point = Point3::new(line.end.x as f32, line.end.y as f32, 0.0); + let graphic_line_string = GraphicLineString { + points: vec![ + start_point.coords.cast::().into(), + end_point.coords.cast::().into(), + ], + }; + + graphic_line_strings.push(graphic_line_string) + }, + Geometry::LineString(line_string) => { + graphic_line_strings + .push(self.line_string_to_graphic_line_string(&line_string)); + }, + Geometry::MultiLineString(line_strings) => { + for line_string in line_strings.into_iter() { + graphic_line_strings + .push(self.line_string_to_graphic_line_string(line_string)); + } + }, + Geometry::MultiPolygon(polygons) => { + for polygon in polygons.into_iter() { + graphic_line_strings + .push(self.line_string_to_graphic_line_string(polygon.exterior())); + } + }, + Geometry::Rect(rect) => { + let line_string = Self::lines_to_line_string(&rect.to_lines()); - let quat1 = UnitQuaternion::rotation_between(&default_origin.normal, &inter_origin).unwrap(); - let quat2 = UnitQuaternion::rotation_between(&inter_origin, &origin.normal).unwrap(); + graphic_line_strings + .push(self.line_string_to_graphic_line_string(&line_string)); + }, + Geometry::Triangle(triangle) => { + let line_string = Self::lines_to_line_string(&triangle.to_lines()); + + graphic_line_strings + .push(self.line_string_to_graphic_line_string(&line_string)); + }, + Geometry::GeometryCollection(geometry_collection) => { + let child_sketch = Self { + geometry: geometry_collection.clone(), + bounding_box: self.bounding_box.clone(), + metadata: self.metadata.clone(), + origin: self.origin.clone(), + origin_transform: self.origin_transform.clone(), + }; + + let line_strings = child_sketch.build_graphic_line_strings(); - (quat1, Some(quat2)) + graphic_line_strings.extend_from_slice(&line_strings.line_strings); + }, + // Don't render points + _ => {}, } + } + + GraphicLineStrings { + line_strings: graphic_line_strings, + } + } + + fn lines_to_line_string(lines: &[Line]) -> LineString { + let mut coord_vec = Vec::with_capacity(lines.len() + 1); + let mut lines_iter = lines.into_iter(); + + let first_line = match lines_iter.next() { + Some(line) => line, + None => { + return LineString::empty(); + }, }; - (pos_transform, rotation_quats) + coord_vec.push(first_line.start); + coord_vec.push(first_line.end); + + for line in lines_iter { + coord_vec.push(line.end); + } + + LineString::new(coord_vec) + } + + fn line_string_to_graphic_line_string( + &self, + line_string: &LineString, + ) -> GraphicLineString { + let points_vec = line_string + .coords() + .map(|coord| { + let point = Point3::new(coord.x, coord.y, 0.0); + + let point_transformed = + apply_origin_transform_graphicpoint!(point, self.origin_transform); + + let graphics_point: [f32; 3] = point_transformed.coords.cast::().into(); + + graphics_point + }) + .collect(); + + let graphic_line_string = GraphicLineString { points: points_vec }; + + graphic_line_string } } From 5f53fe48c6e8ea5256c55494401ef937f3b2e5cb Mon Sep 17 00:00:00 2001 From: Charles Thompson Date: Wed, 19 Nov 2025 19:35:38 -0500 Subject: [PATCH 7/7] Removed redundant quats --- src/sketch/mod.rs | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/src/sketch/mod.rs b/src/sketch/mod.rs index 2baf3a66..e3abd17b 100644 --- a/src/sketch/mod.rs +++ b/src/sketch/mod.rs @@ -34,26 +34,19 @@ pub mod offset; #[cfg(feature = "truetype-text")] pub mod truetype; -pub(crate) type OriginTransformVecQuat = ( - Vector3, - (UnitQuaternion, Option>), -); +/// Position transform, rotation quaternion +pub(crate) type OriginTransformVecQuat = (Vector3, UnitQuaternion); #[macro_export] macro_rules! apply_origin_transform { ($in_vertex:expr, $origin_transform:expr) => {{ let (pos_transform, rotation_quats) = $origin_transform; - let (quat1, quat2) = rotation_quats; + let quat = rotation_quats; let mut out_vertex = Vertex::default(); - out_vertex.pos.coords = quat1 * $in_vertex.pos.coords; - out_vertex.normal = quat1 * $in_vertex.normal; - - if let Some(quat2) = quat2 { - out_vertex.pos.coords = quat2 * $in_vertex.pos.coords; - out_vertex.normal = quat2 * $in_vertex.normal; - } + out_vertex.pos.coords = quat * $in_vertex.pos.coords; + out_vertex.normal = quat * $in_vertex.normal; out_vertex.pos.coords += pos_transform; @@ -64,15 +57,11 @@ macro_rules! apply_origin_transform { macro_rules! apply_origin_transform_graphicpoint { ($in_point:expr, $origin_transform:expr) => {{ let (pos_transform, rotation_quats) = $origin_transform; - let (quat1, quat2) = rotation_quats; + let quat = rotation_quats; let mut out_point = Point3::new(0.0, 0.0, 0.0); - out_point.coords = quat1 * $in_point.coords; - - if let Some(quat2) = quat2 { - out_point.coords = quat2 * $in_point.coords; - } + out_point.coords = quat * $in_point.coords; out_point.coords += pos_transform; @@ -334,9 +323,9 @@ impl Sketch { let pos_transform = origin.pos - default_origin.pos; - let rotation_quats = + let rotation_quat = match UnitQuaternion::rotation_between(&default_origin.normal, &origin.normal) { - Some(quat) => (quat, None), + Some(quat) => quat, None => { // Assumes the default normal is +Z. We'll do +Y let inter_origin = Vector3::new(0.0, 1.0, 0.0); @@ -350,11 +339,11 @@ impl Sketch { UnitQuaternion::rotation_between(&inter_origin, &origin.normal) .unwrap(); - (quat1, Some(quat2)) + quat2 * quat1 }, }; - (pos_transform, rotation_quats) + (pos_transform, rotation_quat) } /// Create graphic line strings from the edges of the sketch