Skip to content
Merged
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
35 changes: 8 additions & 27 deletions src/boolean3.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::collider::Recorder;
use crate::collider::{Recorder, SimpleRecorder};
use crate::common::{AABB, AABBOverlap, OpType};
use crate::disjoint_sets::DisjointSets;
use crate::meshboolimpl::MeshBoolImpl;
Expand Down Expand Up @@ -517,25 +517,6 @@ fn intersect12(
(p1q2, x12, v12)
}

struct Winding03Recorder<'a, 'b> {
w03: &'a mut [i32],
k02: &'a Kernel02<'b>,
verts: &'a [u32],
forward: bool,
}

impl<'a, 'b> Recorder for Winding03Recorder<'a, 'b> {
fn record(&mut self, query_idx: i32, leaf_idx: i32) {
let (s02, z02) = self
.k02
.call(self.verts[query_idx as usize] as usize, leaf_idx as usize);
if z02.is_finite() {
self.w03[self.verts[query_idx as usize] as usize] +=
s02 * (if !self.forward { -1 } else { 1 })
}
}
}

fn winding03(
in_p: &MeshBoolImpl,
in_q: &MeshBoolImpl,
Expand Down Expand Up @@ -578,16 +559,16 @@ fn winding03(
vert_normal_p: &in_p.vert_normal,
forward,
};

let mut recorder = Winding03Recorder {
w03: &mut w03,
k02: &k02,
verts: &verts,
forward,
let mut recorderf = |query_idx: i32, leaf_idx: i32| {
let (s02, z02) = k02.call(verts[query_idx as usize] as usize, leaf_idx as usize);
if z02.is_finite() {
w03[verts[query_idx as usize] as usize] += s02 * (if !forward { -1 } else { 1 });
}
};
let mut recorder = SimpleRecorder::new(&mut recorderf);
let f = |i| a.vert_pos[verts[i as usize] as usize];
b.collider
.collisions_from_fn::<_, _, Winding03Recorder>(f, verts.len(), &mut recorder);
.collisions_from_fn::<_, _, SimpleRecorder<'_>>(f, verts.len(), &mut recorder);
// flood fill
for i in 0..w03.len() {
let root = u_a.find(i as u32) as usize;
Expand Down
10 changes: 5 additions & 5 deletions src/boolean_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ fn reorder_halfedges(halfedges: &mut [Halfedge]) {
}

impl<'a> Boolean3<'a> {
pub fn result(self, op: OpType) -> MeshBoolImpl {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed this change here while fixing some merge conflicts for my project. Consuming self was intentional here: Manifold establishes a pattern in this function of freeing memory as early as possible to avoid running out of RAM during very large mesh boolean operations. Was this a tidying task or was something else not working?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would have to use .clone() here otherwise. It's only thing that that change is used for if I remember. Probably could have been better to put it in #20 so the reason for that change was in the same PR.

pub fn result(&self, op: OpType) -> MeshBoolImpl {
debug_assert!(
(self.expand_p > 0.0) == (op == OpType::Add),
"Result op type not compatible with constructor op type."
Expand Down Expand Up @@ -878,10 +878,10 @@ impl<'a> Boolean3<'a> {
let invert_q = op == OpType::Subtract;

// Convert winding numbers to inclusion values based on operation type.
let i12: Vec<_> = self.x12.into_iter().map(|v| c3 * v).collect();
let i21: Vec<_> = self.x21.into_iter().map(|v| c3 * v).collect();
let i03: Vec<_> = self.w03.into_iter().map(|v| c1 + c3 * v).collect();
let i30: Vec<_> = self.w30.into_iter().map(|v| c2 + c3 * v).collect();
let i12: Vec<_> = self.x12.iter().copied().map(|v| c3 * v).collect();
let i21: Vec<_> = self.x21.iter().copied().map(|v| c3 * v).collect();
let i03: Vec<_> = self.w03.iter().copied().map(|v| c1 + c3 * v).collect();
let i30: Vec<_> = self.w30.iter().copied().map(|v| c2 + c3 * v).collect();

let v_p2r = exclusive_scan_transformed(&i03, 0, &abs_sum);
let mut num_vert_r = v_p2r.last().unwrap().abs() + i03.last().unwrap().abs();
Expand Down
16 changes: 16 additions & 0 deletions src/collider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,22 @@ pub trait Recorder {
fn record(&mut self, query_idx: i32, leaf_idx: i32);
}

pub struct SimpleRecorder<'a> {
pub f: &'a mut dyn FnMut(i32, i32),
}

impl<'a> SimpleRecorder<'a> {
pub fn new(f: &'a mut dyn FnMut(i32, i32)) -> Self {
Self { f }
}
}

impl<'a> Recorder for SimpleRecorder<'a> {
fn record(&mut self, query_idx: i32, leaf_idx: i32) {
(self.f)(query_idx, leaf_idx);
}
}

#[derive(Clone, Default, Debug)]
pub struct Collider {
node_bbox: Vec<AABB>,
Expand Down
37 changes: 37 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,3 +328,40 @@ pub fn sun_acos(x: f64) -> f64 {
pub fn lerp(a: f64, b: f64, t: f64) -> f64 {
a * (1.0 - t) + b * t
}

///Sine function where multiples of 90 degrees come out exact.
///
///@param x Angle in degrees.
#[inline]
pub fn sind(mut x: f64) -> f64 {
if !x.is_finite() {
return x.sin();
}
if x < 0.0 {
return -sind(-x);
}
let quo: i32;
(x, quo) = remquo(x.abs(), 90.0);
match quo % 4 {
0 => x.to_radians().sin(),
1 => x.to_radians().cos(),
2 => -x.to_radians().sin(),
3 => -x.to_radians().cos(),
_ => 0.0,
}
}

///Cosine function where multiples of 90 degrees come out exact.
///
///@param x Angle in degrees.
#[inline]
pub fn cosd(x: f64) -> f64 {
sind(x + 90.0)
}

#[inline]
fn remquo(x: f64, y: f64) -> (f64, i32) {
let r = x.rem_euclid(y); // IEEE remainder
let q = ((x - r) / y).round() as i32;
(r, q)
}
13 changes: 4 additions & 9 deletions src/constructors.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::MeshBool;
use crate::common::{Polygons, Quality, SimplePolygon};
use crate::common::{Polygons, Quality, SimplePolygon, cosd, sind};
use crate::meshboolimpl::{MeshBoolImpl, Shape};
use crate::polygon::{PolyVert, PolygonsIdx, SimplePolygonIdx, triangulate_idx};
use nalgebra::{Matrix2, Matrix3x4, Point2, Point3, Vector2, Vector3};
Expand Down Expand Up @@ -77,8 +77,8 @@ impl MeshBool {
let d_phi = 360.0 / (n as f64);
for i in 0..n {
circle[i as usize] = Point2::<f64>::new(
radius_low * (d_phi * i as f64).to_radians().cos(),
radius_low * (d_phi * i as f64).to_radians().sin(),
radius_low * cosd(d_phi * i as f64),
radius_low * sind(d_phi * i as f64),
);
}

Expand Down Expand Up @@ -183,12 +183,7 @@ impl MeshBool {
let alpha = (i as f64) / (n_divisions as f64);
let phi = alpha * twist_degrees;
let scale = Vector2::new(1.0, 1.0).lerp(&scale_top, alpha);
let rotation = Matrix2::new(
phi.to_radians().cos(),
-phi.to_radians().sin(),
phi.to_radians().sin(),
phi.to_radians().cos(),
);
let rotation = Matrix2::new(cosd(phi), -sind(phi), sind(phi), cosd(phi));
let transform = Matrix2::new(scale.x, 0.0, 0.0, scale.y) * rotation;
let mut j = 0;
let mut idx = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ impl MeshBool {
pub fn set_properties(
&self,
num_prop: i32,
prop_func: Option<fn(new_prop: &mut [f64], position: Point3<f64>, old_prop: &[f64])>,
prop_func: Option<impl Fn(&mut [f64], Point3<f64>, &[f64])>,
) -> Self {
let mut meshbool_impl = self.meshbool_impl.clone();
let old_num_prop = self.num_prop();
Expand Down
2 changes: 1 addition & 1 deletion src/meshboolimpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ impl MeshBoolImpl {
ids[i as usize] = i;
}

ids.sort_unstable_by_key(|&i| {
ids[start as usize..end as usize].sort_unstable_by_key(|&i| {
let entry = &entries[i as usize];
(entry.large_vert, entry.tri)
});
Expand Down