Skip to content

Commit

Permalink
Merge pull request #734 from hannobraun/ops
Browse files Browse the repository at this point in the history
Reduce `fj-operations`' reliance on `Shape`
  • Loading branch information
hannobraun authored Jun 28, 2022
2 parents 79ccdef + a28fb7d commit c08da0d
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 90 deletions.
32 changes: 16 additions & 16 deletions crates/fj-operations/src/circle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,31 @@ impl ToShape for fj::Circle {
config: &ValidationConfig,
_: Tolerance,
_: &mut DebugInfo,
) -> Result<Validated<Shape>, ValidationError> {
let mut shape = Shape::new();
) -> Result<Validated<Vec<Face>>, ValidationError> {
let mut tmp = Shape::new();

// Circles have just a single round edge with no vertices. So none need
// to be added here.

let edge = Edge::builder(&mut shape)
let edge = Edge::builder(&mut tmp)
.build_circle(Scalar::from_f64(self.radius()));

let cycle_local = Cycle {
edges: vec![edge.clone()],
};
let cycle_canonical = shape.insert(Cycle::new(vec![edge.canonical()]));

let surface = shape.insert(Surface::xy_plane());
shape.insert(Face::new(
surface,
vec![LocalForm::new(cycle_local, cycle_canonical)],
Vec::new(),
self.color(),
));

let shape = validate(shape, config)?;

Ok(shape)
let cycle_canonical = tmp.insert(Cycle::new(vec![edge.canonical()]));

let surface = tmp.insert(Surface::xy_plane());
let face = tmp
.insert(Face::new(
surface,
vec![LocalForm::new(cycle_local, cycle_canonical)],
Vec::new(),
self.color(),
))
.get();

validate(vec![face], config)
}

fn bounding_volume(&self) -> Aabb<3> {
Expand Down
38 changes: 18 additions & 20 deletions crates/fj-operations/src/difference_2d.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use fj_interop::debug::DebugInfo;
use fj_kernel::{
algorithms::Tolerance,
iter::ObjectIters,
objects::{Cycle, Edge, Face},
shape::{LocalForm, Shape},
validation::{validate, Validated, ValidationConfig, ValidationError},
Expand All @@ -15,11 +16,11 @@ impl ToShape for fj::Difference2d {
config: &ValidationConfig,
tolerance: Tolerance,
debug_info: &mut DebugInfo,
) -> Result<Validated<Shape>, ValidationError> {
) -> Result<Validated<Vec<Face>>, ValidationError> {
// This method assumes that `b` is fully contained within `a`:
// https://github.com/hannobraun/Fornjot/issues/92

let mut difference = Shape::new();
let mut difference = Vec::new();

let mut exteriors = Vec::new();
let mut interiors = Vec::new();
Expand All @@ -32,13 +33,12 @@ impl ToShape for fj::Difference2d {
[a, b].map(|shape| shape.to_shape(config, tolerance, debug_info));
let [a, b] = [a?, b?];

if let Some(face) = a.faces().next() {
if let Some(face) = a.face_iter().next() {
// If there's at least one face to subtract from, we can proceed.

let surface = face.get().brep().surface.clone();
let surface = face.brep().surface.clone();

for face in a.faces() {
let face = face.get();
for face in a.face_iter() {
let face = face.brep();

assert_eq!(
Expand All @@ -48,17 +48,16 @@ impl ToShape for fj::Difference2d {
);

for cycle in face.exteriors.as_local_form().cloned() {
let cycle = add_cycle(cycle, &mut difference, false);
let cycle = add_cycle(cycle, false);
exteriors.push(cycle);
}
for cycle in face.interiors.as_local_form().cloned() {
let cycle = add_cycle(cycle, &mut difference, true);
let cycle = add_cycle(cycle, true);
interiors.push(cycle);
}
}

for face in b.faces() {
let face = face.get();
for face in b.face_iter() {
let face = face.brep();

assert_eq!(
Expand All @@ -68,22 +67,20 @@ impl ToShape for fj::Difference2d {
);

for cycle in face.exteriors.as_local_form().cloned() {
let cycle = add_cycle(cycle, &mut difference, true);
let cycle = add_cycle(cycle, true);
interiors.push(cycle);
}
}

difference.merge(Face::new(
difference.push(Face::new(
surface,
exteriors,
interiors,
self.color(),
));
}

let difference = validate(difference, config)?;

Ok(difference)
validate(difference, config)
}

fn bounding_volume(&self) -> Aabb<3> {
Expand All @@ -96,9 +93,10 @@ impl ToShape for fj::Difference2d {

fn add_cycle(
cycle: LocalForm<Cycle<2>, Cycle<3>>,
shape: &mut Shape,
reverse: bool,
) -> LocalForm<Cycle<2>, Cycle<3>> {
let mut tmp = Shape::new();

let mut edges = Vec::new();
for edge in cycle.local().edges.clone() {
let curve_local = *edge.local().curve.local();
Expand All @@ -114,7 +112,7 @@ fn add_cycle(
} else {
curve_canonical
};
let curve_canonical = shape.insert(curve_canonical);
let curve_canonical = tmp.insert(curve_canonical);

let vertices = if reverse {
edge.local().vertices.clone().reverse()
Expand All @@ -126,7 +124,7 @@ fn add_cycle(
curve: LocalForm::new(curve_local, curve_canonical.clone()),
vertices: vertices.clone(),
};
let edge_canonical = shape.merge(Edge {
let edge_canonical = tmp.merge(Edge {
curve: LocalForm::canonical_only(curve_canonical),
vertices,
});
Expand All @@ -141,8 +139,8 @@ fn add_cycle(
let cycle_local = Cycle {
edges: edges.clone(),
};
let cycle_canonical = shape
.insert(Cycle::new(edges.into_iter().map(|edge| edge.canonical())));
let cycle_canonical =
tmp.insert(Cycle::new(edges.into_iter().map(|edge| edge.canonical())));

LocalForm::new(cycle_local, cycle_canonical)
}
14 changes: 6 additions & 8 deletions crates/fj-operations/src/group.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use fj_interop::debug::DebugInfo;
use fj_kernel::{
algorithms::Tolerance,
shape::Shape,
objects::Face,
validation::{validate, Validated, ValidationConfig, ValidationError},
};
use fj_math::Aabb;
Expand All @@ -14,18 +14,16 @@ impl ToShape for fj::Group {
config: &ValidationConfig,
tolerance: Tolerance,
debug_info: &mut DebugInfo,
) -> Result<Validated<Shape>, ValidationError> {
let mut shape = Shape::new();
) -> Result<Validated<Vec<Face>>, ValidationError> {
let mut shape = Vec::new();

let a = self.a.to_shape(config, tolerance, debug_info)?;
let b = self.b.to_shape(config, tolerance, debug_info)?;

shape.merge_shape(&a);
shape.merge_shape(&b);
shape.extend(a.into_inner());
shape.extend(b.into_inner());

let shape = validate(shape, config)?;

Ok(shape)
validate(shape, config)
}

fn bounding_volume(&self) -> Aabb<3> {
Expand Down
6 changes: 3 additions & 3 deletions crates/fj-operations/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ mod transform;
use fj_interop::debug::DebugInfo;
use fj_kernel::{
algorithms::Tolerance,
shape::Shape,
objects::Face,
validation::{Validated, ValidationConfig, ValidationError},
};
use fj_math::Aabb;
Expand All @@ -41,7 +41,7 @@ pub trait ToShape {
config: &ValidationConfig,
tolerance: Tolerance,
debug_info: &mut DebugInfo,
) -> Result<Validated<Shape>, ValidationError>;
) -> Result<Validated<Vec<Face>>, ValidationError>;

/// Access the axis-aligned bounding box of a shape
///
Expand Down Expand Up @@ -94,6 +94,6 @@ dispatch! {
config: &ValidationConfig,
tolerance: Tolerance,
debug_info: &mut DebugInfo,
) -> Result<Validated<Shape>, ValidationError>;
) -> Result<Validated<Vec<Face>>, ValidationError>;
bounding_volume() -> Aabb<3>;
}
8 changes: 2 additions & 6 deletions crates/fj-operations/src/shape_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,8 @@ impl ShapeProcessor {

let config = ValidationConfig::default();
let mut debug_info = DebugInfo::new();
let shape = shape
.to_shape(&config, tolerance, &mut debug_info)?
.faces()
.map(|handle| handle.get())
.collect();
let mesh = triangulate(shape, tolerance, &mut debug_info);
let shape = shape.to_shape(&config, tolerance, &mut debug_info)?;
let mesh = triangulate(shape.into_inner(), tolerance, &mut debug_info);

Ok(ProcessedShape {
aabb,
Expand Down
13 changes: 6 additions & 7 deletions crates/fj-operations/src/sketch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,19 @@ impl ToShape for fj::Sketch {
config: &ValidationConfig,
_: Tolerance,
_: &mut DebugInfo,
) -> Result<Validated<Shape>, ValidationError> {
let mut shape = Shape::new();
) -> Result<Validated<Vec<Face>>, ValidationError> {
let mut tmp = Shape::new();

let surface = Surface::xy_plane();
let points = self.to_points().into_iter().map(Point::from);

Face::builder(surface, &mut shape)
let sketch = Face::builder(surface, &mut tmp)
.with_exterior_polygon(points)
.with_color(self.color())
.build();
.build()
.get();

let shape = validate(shape, config)?;

Ok(shape)
validate(vec![sketch], config)
}

fn bounding_volume(&self) -> Aabb<3> {
Expand Down
19 changes: 5 additions & 14 deletions crates/fj-operations/src/sweep.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use fj_interop::debug::DebugInfo;
use fj_kernel::{
algorithms::{sweep, Tolerance},
iter::ObjectIters,
shape::Shape,
objects::Face,
validation::{validate, Validated, ValidationConfig, ValidationError},
};
use fj_math::{Aabb, Vector};
Expand All @@ -15,22 +14,14 @@ impl ToShape for fj::Sweep {
config: &ValidationConfig,
tolerance: Tolerance,
debug_info: &mut DebugInfo,
) -> Result<Validated<Shape>, ValidationError> {
let shape = self.shape().to_shape(config, tolerance, debug_info)?;
) -> Result<Validated<Vec<Face>>, ValidationError> {
let sketch = self.shape().to_shape(config, tolerance, debug_info)?;
let path = Vector::from(self.path());
let color = self.shape().color();

let shape = shape.face_iter().collect::<Vec<_>>();
let swept = sweep(shape, path, tolerance, color);
let solid = sweep(sketch.into_inner(), path, tolerance, color);

let mut shape = Shape::new();
for face in swept {
shape.merge(face);
}

let swept = validate(shape, config)?;

Ok(swept)
validate(solid, config)
}

fn bounding_volume(&self) -> Aabb<3> {
Expand Down
20 changes: 4 additions & 16 deletions crates/fj-operations/src/transform.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use fj_interop::debug::DebugInfo;
use fj_kernel::{
algorithms::{transform, Tolerance},
iter::ObjectIters,
shape::Shape,
objects::Face,
validation::{validate, Validated, ValidationConfig, ValidationError},
};
use fj_math::{Aabb, Transform, Vector};
Expand All @@ -15,21 +14,10 @@ impl ToShape for fj::Transform {
config: &ValidationConfig,
tolerance: Tolerance,
debug_info: &mut DebugInfo,
) -> Result<Validated<Shape>, ValidationError> {
) -> Result<Validated<Vec<Face>>, ValidationError> {
let shape = self.shape.to_shape(config, tolerance, debug_info)?;
let shape = shape.into_inner();

let shape = shape.face_iter().collect::<Vec<_>>();
let faces = transform(&shape, &make_transform(self));

let mut target = Shape::new();
for face in faces {
target.merge(face);
}

let shape = validate(target, config)?;

Ok(shape)
let faces = transform(&shape.into_inner(), &make_transform(self));
validate(faces, config)
}

fn bounding_volume(&self) -> Aabb<3> {
Expand Down

0 comments on commit c08da0d

Please sign in to comment.