Merge pull request #2149 from hannobraun/vertices-indices

Add operation for creating shell from vertices and indices
This commit is contained in:
Hanno Braun 2023-12-21 21:53:32 +01:00 committed by GitHub
commit 8f25f3b621
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 143 additions and 3 deletions

7
Cargo.lock generated
View File

@ -3513,6 +3513,13 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "vertices-indices"
version = "0.1.0"
dependencies = [
"fj",
]
[[package]]
name = "walkdir"
version = "2.4.0"

View File

@ -15,6 +15,7 @@ members = [
"models/spacer",
"models/split",
"models/star",
"models/vertices-indices",
"tools/autolib",
"tools/automator",

View File

@ -1,13 +1,19 @@
use std::collections::BTreeMap;
use fj_interop::ext::ArrayExt;
use fj_math::Point;
use crate::{
objects::{Face, Shell},
geometry::CurveBoundary,
objects::{Curve, Face, HalfEdge, Shell, Surface, Vertex},
operations::{
build::{BuildFace, Polygon},
build::{BuildFace, BuildHalfEdge, BuildSurface, Polygon},
insert::{Insert, IsInserted, IsInsertedNo, IsInsertedYes},
join::JoinCycle,
reverse::ReverseCurveCoordinateSystems,
update::{UpdateCycle, UpdateFace, UpdateRegion},
update::{
UpdateCycle, UpdateFace, UpdateHalfEdge, UpdateRegion, UpdateShell,
},
},
services::Services,
};
@ -23,6 +29,96 @@ pub trait BuildShell {
Shell::new([])
}
/// Build a polyhedron by specifying its vertices and indices
fn from_vertices_and_indices(
vertices: impl IntoIterator<Item = impl Into<Point<3>>>,
indices: impl IntoIterator<Item = [usize; 3]>,
services: &mut Services,
) -> Shell {
let vertices = vertices
.into_iter()
.enumerate()
.map(|(index, position)| {
let vertex = Vertex::new().insert(services);
let position = position.into();
(index, (vertex, position))
})
.collect::<BTreeMap<_, _>>();
let mut curves = BTreeMap::new();
let faces = indices
.into_iter()
.map(|indices| {
let [(a, a_pos), (b, b_pos), (c, c_pos)] = indices
.map(|index| vertices.get(&index).expect("Invalid index"));
let (surface, _) = Surface::plane_from_points(
[a_pos, b_pos, c_pos].map(Clone::clone),
);
let surface = surface.insert(services);
let curves_and_boundaries =
[[a, b], [b, c], [c, a]].map(|vertices| {
let vertices = vertices.map(Clone::clone);
let vertices = CurveBoundary::<Vertex>::from(vertices);
curves
.get(&vertices.clone().reverse())
.cloned()
.unwrap_or_else(|| {
let curve = Curve::new().insert(services);
let boundary =
CurveBoundary::<Point<1>>::from([
[0.],
[1.],
]);
curves.insert(
vertices,
(curve.clone(), boundary),
);
(curve, boundary.reverse())
})
});
let half_edges = {
let vertices = [a, b, c].map(Clone::clone);
let [a, b, c] = [[0., 0.], [1., 0.], [0., 1.]];
vertices
.zip_ext([[a, b], [b, c], [c, a]])
.zip_ext(curves_and_boundaries)
.map(|((vertex, positions), (curve, boundary))| {
HalfEdge::line_segment(
positions,
Some(boundary.reverse().inner),
services,
)
.update_start_vertex(|_| vertex)
.update_curve(|_| curve)
.insert(services)
})
};
Face::unbound(surface, services)
.update_region(|region| {
region
.update_exterior(|cycle| {
cycle
.add_half_edges(half_edges)
.insert(services)
})
.insert(services)
})
.insert(services)
})
.collect::<Vec<_>>();
Shell::empty().add_faces(faces)
}
/// Build a tetrahedron from the provided points
///
/// Accepts 4 points, naturally. For the purposes of the following

View File

@ -0,0 +1,7 @@
[package]
name = "vertices-indices"
version = "0.1.0"
edition = "2021"
[dependencies.fj]
path = "../../crates/fj"

View File

@ -0,0 +1,21 @@
use fj::core::{
objects::{Shell, Solid},
operations::{
build::{BuildShell, BuildSolid},
insert::Insert,
update::UpdateSolid,
},
services::Services,
storage::Handle,
};
pub fn model(services: &mut Services) -> Handle<Solid> {
Solid::empty()
.add_shells([Shell::from_vertices_and_indices(
[[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [0., 0., 1.]],
[[2, 1, 0], [0, 1, 3], [1, 2, 3], [2, 0, 3]],
services,
)
.insert(services)])
.insert(services)
}

View File

@ -0,0 +1,8 @@
use fj::{core::services::Services, handle_model};
fn main() -> fj::Result {
let mut services = Services::new();
let model = vertices_indices::model(&mut services);
handle_model(model, services)?;
Ok(())
}