mirror of
https://github.com/Theaninova/Bampy.git
synced 2026-01-10 20:12:52 +00:00
feat: testing
This commit is contained in:
177
;
Normal file
177
;
Normal file
@@ -0,0 +1,177 @@
|
||||
use super::{
|
||||
axis::Axis,
|
||||
base_slices::BaseSlice,
|
||||
line::Line3,
|
||||
slice_path::{SlicePath, SurfacePathIterator},
|
||||
triangle::Triangle,
|
||||
FloatValue,
|
||||
};
|
||||
use bvh::{
|
||||
aabb::Aabb,
|
||||
bvh::{Bvh, BvhNode},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Mesh {
|
||||
pub aabb: Aabb<FloatValue, 3>,
|
||||
pub bvh: Bvh<FloatValue, 3>,
|
||||
pub triangles: Vec<Triangle>,
|
||||
}
|
||||
|
||||
impl From<Vec<Triangle>> for Mesh {
|
||||
fn from(mut triangles: Vec<Triangle>) -> Self {
|
||||
Self {
|
||||
aabb: triangles
|
||||
.get(0)
|
||||
.map(|triangle| {
|
||||
let mut aabb = triangle.aabb;
|
||||
for triangle in triangles.iter().skip(1) {
|
||||
aabb.join_mut(&triangle.aabb);
|
||||
}
|
||||
aabb
|
||||
})
|
||||
.unwrap_or_else(|| Aabb::empty()),
|
||||
bvh: Bvh::build(&mut triangles),
|
||||
triangles,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mesh {
|
||||
pub fn slice_paths<'a>(
|
||||
self: &'a Mesh,
|
||||
axis: Axis,
|
||||
slice_height: FloatValue,
|
||||
) -> impl Iterator<Item = Vec<SlicePath>> + 'a {
|
||||
self.slice_base_slices(axis, slice_height)
|
||||
.map(|slice| slice.find_paths())
|
||||
.filter(|paths| !paths.is_empty())
|
||||
}
|
||||
|
||||
pub fn slice_surface(&self, axis: Axis, nozzle_width: FloatValue) -> SurfacePathIterator {
|
||||
SurfacePathIterator::new(self, axis, nozzle_width)
|
||||
}
|
||||
|
||||
pub fn slice_base_slices<'a>(
|
||||
self: &'a Mesh,
|
||||
axis: Axis,
|
||||
slice_height: FloatValue,
|
||||
) -> impl Iterator<Item = BaseSlice> + 'a {
|
||||
let layer_count = ((self.aabb.max[axis as usize] - self.aabb.min[axis as usize])
|
||||
/ slice_height)
|
||||
.floor() as usize;
|
||||
|
||||
(0..layer_count).map(move |i| {
|
||||
let layer = i as FloatValue * slice_height + self.aabb.min[axis as usize];
|
||||
let mut base_slice = BaseSlice {
|
||||
i,
|
||||
d: layer,
|
||||
axis,
|
||||
lines: vec![],
|
||||
};
|
||||
|
||||
let mut stack = Vec::<usize>::with_capacity(self.bvh.nodes.len());
|
||||
stack.push(0);
|
||||
while let Some(i) = stack.pop() {
|
||||
match self.bvh.nodes[i] {
|
||||
BvhNode::Node {
|
||||
parent_index: _,
|
||||
child_l_index,
|
||||
child_l_aabb,
|
||||
child_r_index,
|
||||
child_r_aabb,
|
||||
} => {
|
||||
assert!(child_l_aabb.min[axis as usize] <= child_l_aabb.max[axis as usize]);
|
||||
assert!(child_r_aabb.min[axis as usize] <= child_r_aabb.max[axis as usize]);
|
||||
if layer >= child_l_aabb.min[axis as usize]
|
||||
&& layer <= child_l_aabb.max[axis as usize]
|
||||
{
|
||||
stack.push(child_l_index);
|
||||
}
|
||||
if layer >= child_r_aabb.min[axis as usize]
|
||||
&& layer <= child_r_aabb.max[axis as usize]
|
||||
{
|
||||
stack.push(child_r_index);
|
||||
}
|
||||
}
|
||||
BvhNode::Leaf {
|
||||
parent_index: _,
|
||||
shape_index,
|
||||
} => {
|
||||
for line in self.triangles[shape_index].intersect(layer, axis as usize) {
|
||||
base_slice.lines.push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base_slice
|
||||
})
|
||||
}
|
||||
|
||||
pub fn outline_base_slice(&self, axis: Axis) -> BaseSlice {
|
||||
let mut base_slice = BaseSlice {
|
||||
i: 0,
|
||||
d: 0.0,
|
||||
axis,
|
||||
lines: vec![],
|
||||
};
|
||||
'triangle: for (i, triangle) in self.triangles.iter().enumerate() {
|
||||
let mut stack = Vec::<usize>::with_capacity(self.bvh.nodes.len());
|
||||
stack.push(0);
|
||||
let mut ab = false;
|
||||
let mut ac = false;
|
||||
let mut bc = false;
|
||||
while let Some(i) = stack.pop() {
|
||||
match self.bvh.nodes[i] {
|
||||
BvhNode::Node {
|
||||
parent_index: _,
|
||||
child_l_index,
|
||||
child_l_aabb,
|
||||
child_r_index,
|
||||
child_r_aabb,
|
||||
} => {
|
||||
let coords = [triangle.a, triangle.b, triangle.c];
|
||||
macro_rules! match_aabb {
|
||||
($side:expr) => {
|
||||
coords
|
||||
.iter()
|
||||
.map(|point| {
|
||||
$side.approx_contains_eps(point, FloatValue::EPSILON) as i32
|
||||
})
|
||||
.sum::<i32>()
|
||||
>= 2
|
||||
};
|
||||
}
|
||||
if match_aabb!(child_l_aabb) {
|
||||
stack.push(child_l_index);
|
||||
}
|
||||
if match_aabb!(child_r_aabb) {
|
||||
stack.push(child_r_index);
|
||||
}
|
||||
}
|
||||
BvhNode::Leaf {
|
||||
parent_index: _,
|
||||
shape_index,
|
||||
} => {
|
||||
if i == shape_index {
|
||||
continue;
|
||||
}
|
||||
let other = &self.triangles[shape_index];
|
||||
let a = triangle.has_point(other.a);
|
||||
let b = triangle.has_point(other.b);
|
||||
let c = triangle.has_point(other.c);
|
||||
ab = ab || (a && b);
|
||||
ac = ac || (a && c);
|
||||
bc = bc || (b && c);
|
||||
|
||||
if ab && ac && bc {
|
||||
continue 'triangle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
base_slice
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user