Add Face and use it for top/bottom faces

This is one more (significant!) step in the direction of a real b-rep
representation.
This commit is contained in:
Hanno Braun 2025-01-10 19:13:53 +01:00
parent b1f718a705
commit dea2699188
3 changed files with 107 additions and 17 deletions

View File

@ -1,11 +1,14 @@
use itertools::Itertools;
use crate::{
geometry::{Shape, Sketch, Triangle},
math::{Bivector, Plane, Point, Vector},
storage::Store,
topology::Vertex,
topology::{Face, Vertex},
};
pub fn model(shape: &mut Shape) {
let mut faces = Store::<Face>::new();
let mut surfaces = Store::<Plane>::new();
let mut vertices = Store::<Vertex>::new();
let mut triangles = Store::<Triangle>::new();
@ -28,18 +31,18 @@ pub fn model(shape: &mut Shape) {
let sketch =
Sketch::from([[-0.5, -0.5], [0.5, -0.5], [0.5, 0.5], [-0.5, 0.5]]);
let (a, b, c, d, e, f, g, h) = shape
.extend_with(&mut vertices)
.add(bottom.point_from_local(sketch.points[0]))
.add(bottom.point_from_local(sketch.points[1]))
.add(bottom.point_from_local(sketch.points[2]))
.add(bottom.point_from_local(sketch.points[3]))
.add(top.point_from_local(sketch.points[0]))
.add(top.point_from_local(sketch.points[1]))
.add(top.point_from_local(sketch.points[2]))
.add(top.point_from_local(sketch.points[3]))
let [bottom, top] =
[bottom, top].map(|plane| Face::new(&sketch, plane, &mut vertices));
let (bottom, top) = shape
.extend_with(&mut faces)
.add(bottom)
.add(top)
.get_added();
let [a, b, c, d] = bottom.vertices.iter().collect_array().unwrap();
let [e, f, g, h] = top.vertices.iter().collect_array().unwrap();
let [a, b, c, d, e, f, g, h] =
[a, b, c, d, e, f, g, h].map(|vertex| vertex.point);
@ -52,9 +55,5 @@ pub fn model(shape: &mut Shape) {
.add([d, c, f]) // front
.add([d, f, e])
.add([a, g, b]) // back
.add([a, h, g])
.add([d, a, c]) // bottom
.add([c, a, b])
.add([e, f, g]) // top
.add([e, g, h]);
.add([a, h, g]);
}

View File

@ -0,0 +1,90 @@
use std::fmt;
use spade::Triangulation;
use crate::{
geometry::{AnyOp, Handle, Operation, Sketch, Triangle},
math::{Plane, Point},
storage::Store,
};
use super::Vertex;
pub struct Face {
pub surface: Handle<Plane>,
pub vertices: Vec<Handle<Vertex>>,
}
impl Face {
pub fn new(
sketch: &Sketch,
surface: Handle<Plane>,
vertices: &mut Store<Vertex>,
) -> Self {
let vertices = sketch
.points
.iter()
.copied()
.map(|point| {
let point = surface.point_from_local(point);
let vertex = Vertex::from(point);
vertices.insert(vertex)
})
.collect();
Self { surface, vertices }
}
}
impl fmt::Display for Face {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "face")
}
}
impl Operation for Face {
fn vertices(&self, vertices: &mut Vec<Vertex>) {
vertices.extend(self.vertices.iter().map(|vertex| **vertex));
}
fn triangles(&self, triangles: &mut Vec<Triangle>) {
// This is a placeholder implementation that only supports convex faces.
let mut triangulation =
spade::ConstrainedDelaunayTriangulation::<_>::new();
triangulation
.add_constraint_edges(
self.vertices.iter().map(|vertex| TriangulationPoint {
point_surface: self.surface.project_point(vertex.point),
point_vertex: vertex.point,
}),
true,
)
.unwrap();
triangles.extend(triangulation.inner_faces().map(|triangle| {
let vertices =
triangle.vertices().map(|vertex| vertex.data().point_vertex);
Triangle { vertices }
}));
}
fn children(&self) -> Vec<AnyOp> {
self.vertices.iter().map(|vertex| vertex.to_any()).collect()
}
}
struct TriangulationPoint {
point_surface: Point<2>,
point_vertex: Point<3>,
}
impl spade::HasPosition for TriangulationPoint {
type Scalar = f64;
fn position(&self) -> spade::Point2<Self::Scalar> {
let [x, y] = self.point_surface.coords.components.map(|s| s.value());
spade::Point2 { x, y }
}
}

View File

@ -1,3 +1,4 @@
mod face;
mod vertex;
pub use self::vertex::Vertex;
pub use self::{face::Face, vertex::Vertex};