Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions crates/opencascade-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,22 @@ pub mod ffi {
pub fn SetScale(self: Pin<&mut gp_Trsf>, point: &gp_Pnt, scale: f64);
pub fn SetTranslation(self: Pin<&mut gp_Trsf>, point1: &gp_Pnt, point2: &gp_Pnt);
pub fn Value(self: &gp_Trsf, the_row: i32, the_col: i32) -> f64;
#[allow(clippy::too_many_arguments)]
pub fn SetValues(
self: Pin<&mut gp_Trsf>,
a11: f64,
a12: f64,
a13: f64,
a14: f64,
a21: f64,
a22: f64,
a23: f64,
a24: f64,
a31: f64,
a32: f64,
a33: f64,
a34: f64,
);

#[cxx_name = "SetTranslationPart"]
pub fn set_translation_vec(self: Pin<&mut gp_Trsf>, translation: &gp_Vec);
Expand Down
1 change: 1 addition & 0 deletions crates/opencascade/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod kicad;
pub mod mesh;
pub mod primitives;
pub mod section;
pub mod transform;
pub mod workplane;

mod law_function;
Expand Down
42 changes: 41 additions & 1 deletion crates/opencascade/src/primitives/shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
Error,
};
use cxx::UniquePtr;
use glam::{dvec2, dvec3, DVec3};
use glam::{dvec2, dvec3, DMat4, DVec3};
use opencascade_sys::ffi;
use std::path::Path;

Expand Down Expand Up @@ -631,6 +631,14 @@ impl Shape {
self.inner.pin_mut().set_global_translation(&location, false);
}

/// Copy `self` using the upper 3x4 matrix of `transform`.
pub fn transform(&self, transform: &DMat4) -> Self {
let t = crate::transform::gp_trsf(transform);
// NOTE: Setting the copy argument does not seem to have an effect.
let mut res = ffi::BRepBuilderAPI_Transform_ctor(&self.inner, &t, true);
Self::from_shape(res.pin_mut().Shape())
}

pub fn mesh(&self) -> Result<Mesh, Error> {
self.mesh_with_tolerance(0.01)
}
Expand Down Expand Up @@ -754,3 +762,35 @@ impl ChamferMaker {
Shape::from_shape(self.inner.pin_mut().Shape())
}
}

#[cfg(test)]
mod test {
use crate::{primitives::IntoShape, workplane::Workplane};
const TOLERANCE: f64 = 1e-10;

#[test]
fn transform_shape() {
let m = glam::dmat4(
glam::dvec4(0.0, 0.0, 1.0, 0.0),
glam::dvec4(1.0, 0.0, 0.0, 0.0),
glam::dvec4(0.0, 1.0, 0.0, 0.0),
glam::dvec4(5.0, 6.0, 7.0, 1.0),
);
let s = Workplane::xy().sketch().line_to(1.0, 2.0).wire().into_shape();
let t = s.transform(&m);

for p in s.edges() {
assert!(p.start_point().abs_diff_eq(glam::dvec3(0.0, 0.0, 0.0), TOLERANCE));
assert!(p.end_point().abs_diff_eq(glam::dvec3(1.0, 2.0, 0.0), TOLERANCE));
}

for p in t.edges() {
// The start point includes only offset
assert!(p.start_point().abs_diff_eq(glam::dvec3(5.0, 6.0, 7.0), TOLERANCE));
assert!(p
.end_point()
// The end point includes permutation and offset
.abs_diff_eq(glam::dvec3(2.0 + 5.0, 0.0 + 6.0, 1.0 + 7.0), TOLERANCE));
}
}
}
56 changes: 56 additions & 0 deletions crates/opencascade/src/transform.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use cxx::UniquePtr;
use glam::DMat4;
use opencascade_sys::ffi;

/// Create a `gp_Trsf` from a `DMat4`.
///
/// Note that OCC only allows setting values for the upper 3x4 matrix. I.e. the
/// XYZ components of each column.
///
/// Additionally, OCC ensures orthogonality of the matrix before the method
/// returns.
pub fn gp_trsf(mat: &DMat4) -> UniquePtr<ffi::gp_Trsf> {
let mut t = ffi::new_transform();
t.pin_mut().SetValues(
mat.x_axis.x,
mat.y_axis.x,
mat.z_axis.x,
mat.w_axis.x,
mat.x_axis.y,
mat.y_axis.y,
mat.z_axis.y,
mat.w_axis.y,
mat.x_axis.z,
mat.y_axis.z,
mat.z_axis.z,
mat.w_axis.z,
);
t
}

#[cfg(test)]
mod test {
use super::*;
#[test]
fn set_gp_trsf_values() {
// Matrix with permuted axes
let m = glam::dmat4(
glam::dvec4(0.0, 0.0, 1.0, 0.0),
glam::dvec4(1.0, 0.0, 0.0, 0.0),
glam::dvec4(0.0, 1.0, 0.0, 0.0),
glam::dvec4(0.0, 0.0, 0.0, 1.0),
);

let t = gp_trsf(&m);

// 3D diagonal is 0
assert_eq!(t.Value(1, 1), 0.0);
assert_eq!(t.Value(2, 2), 0.0);
assert_eq!(t.Value(3, 3), 0.0);

// Permuted axes are preserved
assert_eq!(t.Value(1, 2), 1.0);
assert_eq!(t.Value(3, 1), 1.0);
assert_eq!(t.Value(2, 3), 1.0);
}
}
Loading