Skip to content

Commit

Permalink
Merge pull request #2149 from hannobraun/vertices-indices
Browse files Browse the repository at this point in the history
Add operation for creating shell from vertices and indices
  • Loading branch information
hannobraun authored Dec 21, 2023
2 parents 9d56ada + 29051fa commit 8f25f3b
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 3 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ members = [
"models/spacer",
"models/split",
"models/star",
"models/vertices-indices",

"tools/autolib",
"tools/automator",
Expand Down
102 changes: 99 additions & 3 deletions crates/fj-core/src/operations/build/shell.rs
Original file line number Diff line number Diff line change
@@ -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,
};
Expand All @@ -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
Expand Down
7 changes: 7 additions & 0 deletions models/vertices-indices/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "vertices-indices"
version = "0.1.0"
edition = "2021"

[dependencies.fj]
path = "../../crates/fj"
21 changes: 21 additions & 0 deletions models/vertices-indices/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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)
}
8 changes: 8 additions & 0 deletions models/vertices-indices/src/main.rs
Original file line number Diff line number Diff line change
@@ -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(())
}

0 comments on commit 8f25f3b

Please sign in to comment.