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
60 changes: 60 additions & 0 deletions src/constructors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::MeshBool;
use crate::common::{Polygons, Quality, SimplePolygon, cosd, sind};
use crate::disjoint_sets::DisjointSets;
use crate::meshboolimpl::{MeshBoolImpl, Shape};
use crate::parallel::{copy_if, gather};
use crate::polygon::{PolyVert, PolygonsIdx, SimplePolygonIdx, triangulate_idx};
use nalgebra::{Matrix2, Matrix3x4, Point2, Point3, Vector2, Vector3};

Expand Down Expand Up @@ -246,4 +248,62 @@ impl MeshBool {
meshbool_impl.mark_coplanar();
Self::from(meshbool_impl)
}

//
// This operation returns a vector of Manifolds that are topologically
// disconnected. If everything is connected, the vector is length one,
// containing a copy of the original. It is the inverse operation of Compose().
//
pub fn decompose(&self) -> Vec<Self> {
let uf = DisjointSets::new(self.num_vert() as u32);
// Graph graph;
let p_impl = &self.meshbool_impl;
for halfedge in p_impl.halfedge.iter() {
if halfedge.is_forward() {
uf.unite(halfedge.start_vert as u32, halfedge.end_vert as u32);
}
}
let mut component_indices: Vec<i32> = vec![];
let num_components = uf.connected_components(&mut component_indices);

if num_components == 1 {
return vec![self.clone()];
}
let vert_label: Vec<i32> = component_indices;

let num_vert = self.num_vert();
let mut meshes: Vec<Self> = vec![];
for i in 0..num_components {
let mut meshbool_impl = MeshBoolImpl::default();
// inherit original object's precision
meshbool_impl.epsilon = p_impl.epsilon;
meshbool_impl.tolerance = p_impl.tolerance;

let mut vert_new2old: Vec<i32> = vec![0; num_vert];
let n_vert = copy_if(0..num_vert as i32, &mut vert_new2old, |v| {
vert_label[v as usize] == i as i32
});
meshbool_impl.vert_pos.resize(n_vert, Default::default());
vert_new2old.resize(n_vert, Default::default());
gather(&vert_new2old, &p_impl.vert_pos, &mut meshbool_impl.vert_pos);

let mut face_new2old: Vec<i32> = vec![0; self.num_tri()];
let halfedge = &p_impl.halfedge;
let n_face = copy_if(0..self.num_tri() as i32, &mut face_new2old, |face| {
vert_label[halfedge[3 * face as usize].start_vert as usize] == i as i32
});

if n_face == 0 {
continue;
}
face_new2old.resize(n_face, Default::default());

meshbool_impl.gather_faces_with_old(p_impl, &face_new2old);
meshbool_impl.reindex_verts(&vert_new2old, p_impl.num_vert());
meshbool_impl.finish();

meshes.push(Self::from(meshbool_impl));
}
return meshes;
}
}
104 changes: 91 additions & 13 deletions src/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use crate::collider::Collider;
use crate::common::{AABB, LossyFrom};
use crate::disjoint_sets::DisjointSets;
use crate::meshboolimpl::MeshBoolImpl;
use crate::parallel::{inclusive_scan, scatter};
use crate::parallel::{gather, inclusive_scan, scatter};
use crate::shared::Halfedge;
use crate::utils::{K_PRECISION, permute};
use crate::vec::{vec_resize, vec_resize_nofill, vec_uninit};
use nalgebra::{Point3, Vector3};
Expand Down Expand Up @@ -160,6 +161,33 @@ where
return true;
}

struct ReindexFace<'a> {
halfedge: &'a mut [Halfedge],
// halfedge_tangent: &'a mut [Vector4<f64>],
old_halfedge: &'a [Halfedge],
// old_halfedge_tangent: &'a [Vector4<f64>],
face_new2old: &'a [i32],
face_old2new: &'a [i32],
}

impl ReindexFace<'_> {
fn call(&mut self, new_face: u32) {
let old_face = self.face_new2old[new_face as usize];
for i in 0..3 {
let old_edge = 3 * old_face + i;
let mut edge = self.old_halfedge[old_edge as usize];
let paired_face = edge.paired_halfedge / 3;
let offset = edge.paired_halfedge - 3 * paired_face;
edge.paired_halfedge = 3 * self.face_old2new[paired_face as usize] + offset;
let new_edge = 3 * new_face + i as u32;
self.halfedge[new_edge as usize] = edge;
// if !self.old_halfedge_tangent.is_empty() {
// self.halfedge_tangent[new_edge] = self.old_halfedge_tangent[old_edge];
// }
}
}
}

impl MeshBoolImpl {
///Once halfedge_ has been filled in, this function can be called to create the
///rest of the internal data structures. This function also removes the verts
Expand Down Expand Up @@ -236,7 +264,7 @@ impl MeshBoolImpl {
///Updates the halfedges to point to new vert indices based on a mapping,
///vertNew2Old. This may be a subset, so the total number of original verts is
///also given.
fn reindex_verts(&mut self, vert_new2old: &[i32], old_num_vert: usize) {
pub fn reindex_verts(&mut self, vert_new2old: &[i32], old_num_vert: usize) {
let mut vert_old2new: Vec<i32> = unsafe { vec_uninit(old_num_vert) };
scatter(0..self.num_vert() as i32, vert_new2old, &mut vert_old2new);
let has_prop = self.num_prop() > 0;
Expand Down Expand Up @@ -341,7 +369,7 @@ impl MeshBoolImpl {
///Creates the halfedge_ vector for this manifold by copying a set of faces from
///another manifold, given by oldHalfedge. Input faceNew2Old defines the old
///faces to gather into this.
fn gather_faces(&mut self, face_new2old: &[i32]) {
pub fn gather_faces(&mut self, face_new2old: &[i32]) {
let num_tri = face_new2old.len();
if self.mesh_relation.tri_ref.len() == self.num_tri() {
permute(&mut self.mesh_relation.tri_ref, face_new2old);
Expand All @@ -354,21 +382,71 @@ impl MeshBoolImpl {
let mut old_halfedge = unsafe { vec_uninit(3 * num_tri) };
mem::swap(&mut old_halfedge, &mut self.halfedge);

// let mut old_halfedge_tangent = unsafe { vec_uninit(3 * num_tri) };
// mem::swap(&mut old_halfedge_tangent, &mut self.halfedge_tangent);

let mut face_old2new = unsafe { vec_uninit(old_halfedge.len() / 3) };
scatter(0..num_tri as i32, face_new2old, &mut face_old2new);

let mut reindex_face = ReindexFace {
halfedge: &mut self.halfedge,
// halfedge_tangent: &mut self.halfedge_tangent,
old_halfedge: &old_halfedge,
// old_halfedge_tangent: &old_halfedge_tangent,
face_new2old: &face_new2old,
face_old2new: &face_old2new,
};
for new_face in 0..num_tri {
let new_face = new_face as i32;
let old_face = face_new2old[new_face as usize];
for i in 0..3 {
let old_edge = 3 * old_face + i;
let mut edge = old_halfedge[old_edge as usize];
let paired_face = edge.paired_halfedge / 3;
let offset = edge.paired_halfedge - 3 * paired_face;
edge.paired_halfedge = 3 * face_old2new[paired_face as usize] + offset;
let new_edge = 3 * new_face + i;
self.halfedge[new_edge as usize] = edge;
reindex_face.call(new_face as u32);
}
}

pub fn gather_faces_with_old(&mut self, old: &Self, face_new2old: &[i32]) {
let num_tri = face_new2old.len();

unsafe { vec_resize_nofill(&mut self.mesh_relation.tri_ref, num_tri) };

gather(
face_new2old,
&old.mesh_relation.tri_ref,
&mut self.mesh_relation.tri_ref,
);

for pair in old.mesh_relation.mesh_id_transform.iter() {
self.mesh_relation
.mesh_id_transform
.insert(*pair.0, pair.1.clone());
}

if old.num_prop() > 0 {
self.num_prop = old.num_prop;
self.properties = old.properties.clone();
}

if old.face_normal.len() == old.num_tri() {
unsafe {
vec_resize_nofill(&mut self.face_normal, num_tri);
}
gather(face_new2old, &old.face_normal, &mut self.face_normal);
}

let mut face_old2new = unsafe { vec_uninit(old.num_tri()) };
scatter(0..num_tri as i32, face_new2old, &mut face_old2new);

unsafe { vec_resize_nofill(&mut self.halfedge, 3 * num_tri) };
// if old.halfedge_tangent.len() != 0 {
// halfedgeTangent_.resize_nofill(3 * numTri);
// }
let mut reindex_face = ReindexFace {
halfedge: &mut self.halfedge,
// halfedge_tangent: &mut self.halfedge_tangent,
old_halfedge: &old.halfedge,
// old_halfedge_tangent: &old.halfedge_tangent,
face_new2old: &face_new2old,
face_old2new: &face_old2new,
};
for new_face in 0..num_tri {
reindex_face.call(new_face as u32);
}
}
}
Expand Down