Skip to content

Commit

Permalink
Merge pull request #1238 from hannobraun/vertex
Browse files Browse the repository at this point in the history
Fix all known `GlobalVertex` duplication issues
  • Loading branch information
hannobraun authored Oct 19, 2022
2 parents 20f9719 + 052c1d1 commit 23de8d4
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 62 deletions.
5 changes: 3 additions & 2 deletions crates/fj-kernel/src/algorithms/sweep/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ use crate::{
storage::Handle,
};

use super::Sweep;
use super::{Sweep, SweepCache};

impl Sweep for Handle<Curve> {
type Swept = Handle<Surface>;

fn sweep(
fn sweep_with_cache(
self,
path: impl Into<Vector<3>>,
_: &mut SweepCache,
objects: &Objects,
) -> Self::Swept {
match self.surface().u() {
Expand Down
15 changes: 8 additions & 7 deletions crates/fj-kernel/src/algorithms/sweep/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,22 @@ use crate::{
path::SurfacePath,
};

use super::Sweep;
use super::{Sweep, SweepCache};

impl Sweep for (HalfEdge, Color) {
type Swept = Face;

fn sweep(
fn sweep_with_cache(
self,
path: impl Into<Vector<3>>,
cache: &mut SweepCache,
objects: &Objects,
) -> Self::Swept {
let (edge, color) = self;
let path = path.into();

let surface = edge.curve().clone().sweep(path, objects);
let surface =
edge.curve().clone().sweep_with_cache(path, cache, objects);

// We can't use the edge we're sweeping from as the bottom edge, as that
// is not defined in the right surface. Let's create a new bottom edge,
Expand Down Expand Up @@ -82,10 +84,9 @@ impl Sweep for (HalfEdge, Color) {
HalfEdge::new(vertices, edge.global_form().clone())
};

let side_edges = bottom_edge
.vertices()
.clone()
.map(|vertex| (vertex, surface.clone()).sweep(path, objects));
let side_edges = bottom_edge.vertices().clone().map(|vertex| {
(vertex, surface.clone()).sweep_with_cache(path, cache, objects)
});

let top_edge = {
let bottom_vertices = bottom_edge.vertices();
Expand Down
8 changes: 5 additions & 3 deletions crates/fj-kernel/src/algorithms/sweep/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ use crate::{
path::GlobalPath,
};

use super::Sweep;
use super::{Sweep, SweepCache};

impl Sweep for Face {
type Swept = Shell;

fn sweep(
fn sweep_with_cache(
self,
path: impl Into<Vector<3>>,
cache: &mut SweepCache,
objects: &Objects,
) -> Self::Swept {
let path = path.into();
Expand Down Expand Up @@ -64,7 +65,8 @@ impl Sweep for Face {
half_edge.clone()
};

let face = (half_edge, self.color()).sweep(path, objects);
let face = (half_edge, self.color())
.sweep_with_cache(path, cache, objects);

faces.push(face);
}
Expand Down
29 changes: 27 additions & 2 deletions crates/fj-kernel/src/algorithms/sweep/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ mod face;
mod sketch;
mod vertex;

use std::collections::BTreeMap;

use fj_math::Vector;

use crate::objects::Objects;
use crate::{
objects::{GlobalVertex, Objects},
storage::{Handle, ObjectId},
};

/// Sweep an object along a path to create another object
pub trait Sweep {
pub trait Sweep: Sized {
/// The object that is created by sweeping the implementing object
type Swept;

Expand All @@ -20,5 +25,25 @@ pub trait Sweep {
self,
path: impl Into<Vector<3>>,
objects: &Objects,
) -> Self::Swept {
let mut cache = SweepCache::default();
self.sweep_with_cache(path, &mut cache, objects)
}

/// Sweep the object along the given path, using the provided cache
fn sweep_with_cache(
self,
path: impl Into<Vector<3>>,
cache: &mut SweepCache,
objects: &Objects,
) -> Self::Swept;
}

/// A cache used for sweeping
///
/// See [`Sweep`].
#[derive(Default)]
pub struct SweepCache {
/// Cache for global vertices
pub global_vertex: BTreeMap<ObjectId, Handle<GlobalVertex>>,
}
7 changes: 4 additions & 3 deletions crates/fj-kernel/src/algorithms/sweep/sketch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ use fj_math::Vector;

use crate::objects::{Objects, Sketch, Solid};

use super::Sweep;
use super::{Sweep, SweepCache};

impl Sweep for Sketch {
type Swept = Solid;

fn sweep(
fn sweep_with_cache(
self,
path: impl Into<Vector<3>>,
cache: &mut SweepCache,
objects: &Objects,
) -> Self::Swept {
let path = path.into();

let mut shells = Vec::new();
for face in self.into_faces() {
let shell = face.sweep(path, objects);
let shell = face.sweep_with_cache(path, cache, objects);
shells.push(shell);
}

Expand Down
26 changes: 19 additions & 7 deletions crates/fj-kernel/src/algorithms/sweep/vertex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ use crate::{
storage::Handle,
};

use super::Sweep;
use super::{Sweep, SweepCache};

impl Sweep for (Vertex, Handle<Surface>) {
type Swept = HalfEdge;

fn sweep(
fn sweep_with_cache(
self,
path: impl Into<Vector<3>>,
cache: &mut SweepCache,
objects: &Objects,
) -> Self::Swept {
let (vertex, surface) = self;
Expand Down Expand Up @@ -57,8 +58,10 @@ impl Sweep for (Vertex, Handle<Surface>) {
// With that out of the way, let's start by creating the `GlobalEdge`,
// as that is the most straight-forward part of this operations, and
// we're going to need it soon anyway.
let (edge_global, vertices_global) =
vertex.global_form().clone().sweep(path, objects);
let (edge_global, vertices_global) = vertex
.global_form()
.clone()
.sweep_with_cache(path, cache, objects);

// Next, let's compute the surface coordinates of the two vertices of
// the output `Edge`, as we're going to need these for the rest of this
Expand Down Expand Up @@ -120,16 +123,25 @@ impl Sweep for (Vertex, Handle<Surface>) {
impl Sweep for Handle<GlobalVertex> {
type Swept = (GlobalEdge, [Handle<GlobalVertex>; 2]);

fn sweep(
fn sweep_with_cache(
self,
path: impl Into<Vector<3>>,
cache: &mut SweepCache,
objects: &Objects,
) -> Self::Swept {
let curve = GlobalCurve::new(objects);

let a = self.clone();
let b =
GlobalVertex::from_position(self.position() + path.into(), objects);
let b = cache
.global_vertex
.entry(self.id())
.or_insert_with(|| {
GlobalVertex::from_position(
self.position() + path.into(),
objects,
)
})
.clone();

let vertices = [a, b];
let global_edge = GlobalEdge::new(curve, vertices.clone());
Expand Down
31 changes: 22 additions & 9 deletions crates/fj-kernel/src/objects/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ impl HalfEdge {

let curve = a.curve();

let (vertices_in_normalized_order, _) = VerticesInNormalizedOrder::new(
[&a, &b].map(|vertex| vertex.global_form().clone()),
);

// Make sure `curve` and `vertices` match `global_form`.
assert_eq!(
curve.global_form().id(),
Expand All @@ -47,10 +51,15 @@ impl HalfEdge {
the half-edge's global form"
);
assert_eq!(
&VerticesInNormalizedOrder::new(
[&a, &b].map(|vertex| vertex.global_form().clone())
),
global_form.vertices(),
vertices_in_normalized_order
.access_in_normalized_order()
.clone()
.map(|global_vertex| global_vertex.id()),
global_form
.vertices()
.access_in_normalized_order()
.clone()
.map(|global_vertex| global_vertex.id()),
"The global forms of a half-edge's vertices must match the \
vertices of the half-edge's global form"
);
Expand Down Expand Up @@ -130,7 +139,7 @@ impl GlobalEdge {
vertices: [Handle<GlobalVertex>; 2],
) -> Self {
let curve = curve.into();
let vertices = VerticesInNormalizedOrder::new(vertices);
let (vertices, _) = VerticesInNormalizedOrder::new(vertices);
Self { curve, vertices }
}

Expand Down Expand Up @@ -166,10 +175,14 @@ pub struct VerticesInNormalizedOrder([Handle<GlobalVertex>; 2]);
impl VerticesInNormalizedOrder {
/// Construct a new instance of `VerticesInNormalizedOrder`
///
/// The provided vertices can be in any order.
pub fn new([a, b]: [Handle<GlobalVertex>; 2]) -> Self {
let vertices = if a < b { [a, b] } else { [b, a] };
Self(vertices)
/// The provided vertices can be in any order. The returned `bool` value
/// indicates whether the normalization changed the order of the vertices.
pub fn new([a, b]: [Handle<GlobalVertex>; 2]) -> (Self, bool) {
if a < b {
(Self([a, b]), false)
} else {
(Self([b, a]), true)
}
}

/// Access the vertices
Expand Down
14 changes: 12 additions & 2 deletions crates/fj-kernel/src/partial/maybe_partial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use fj_math::Point;

use crate::{
objects::{
Curve, GlobalCurve, GlobalEdge, HalfEdge, Objects, Surface,
SurfaceVertex, Vertex,
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
Surface, SurfaceVertex, Vertex,
},
storage::Handle,
};
Expand Down Expand Up @@ -102,6 +102,16 @@ impl MaybePartial<GlobalEdge> {
}
}
}

/// Access the vertices
pub fn vertices(&self) -> Option<&[Handle<GlobalVertex>; 2]> {
match self {
Self::Full(full) => {
Some(full.vertices().access_in_normalized_order())
}
Self::Partial(partial) => partial.vertices.as_ref(),
}
}
}

impl MaybePartial<HalfEdge> {
Expand Down
Loading

0 comments on commit 23de8d4

Please sign in to comment.