Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename HalfEdge to Edge #2000

Merged
merged 97 commits into from
Aug 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
a53193b
Rename `HalfEdge` to `Edge`
hannobraun Aug 18, 2023
79bb93e
Update comment
hannobraun Aug 18, 2023
f70a2b0
Rename `HalfEdgeApprox` to `EdgeApprox`
hannobraun Aug 18, 2023
5251f20
Update panic message
hannobraun Aug 18, 2023
70598b1
Update doc comment
hannobraun Aug 18, 2023
748233b
Refactor to not rely on iterator being cloneable
hannobraun Aug 18, 2023
79e6f99
Remove `HalfEdgesOfCycle`
hannobraun Aug 18, 2023
b5eac35
Update documentation of `Edge`
hannobraun Aug 18, 2023
dbf7f99
Update comment
hannobraun Aug 18, 2023
c47ee5d
Update struct field name
hannobraun Aug 18, 2023
ccf92a9
Refactor to restore alphabetical ordering
hannobraun Aug 18, 2023
179a8a8
Rename `BuildHalfEdge` to `BuildEdge`
hannobraun Aug 18, 2023
03cfc0a
Rename `UpdateHalfEdge` to `UpdateEdge`
hannobraun Aug 18, 2023
a8f44ec
Update doc comment
hannobraun Aug 18, 2023
288674b
Update error messages
hannobraun Aug 18, 2023
85dcc98
Update validation error name
hannobraun Aug 18, 2023
b83eeb7
Update doc comment
hannobraun Aug 18, 2023
fcbbac7
Update validation error name
hannobraun Aug 18, 2023
3d57918
Rename `HalfEdgeValidationError`
hannobraun Aug 18, 2023
baa9e07
Update error message
hannobraun Aug 18, 2023
bd184c3
Update doc comment
hannobraun Aug 18, 2023
f6c1c0a
Update error message
hannobraun Aug 18, 2023
3688291
Rename `ValidationError::HalfEdge` to `Edge`
hannobraun Aug 18, 2023
e2fe4a2
Refactor to restore alphabetic ordering
hannobraun Aug 18, 2023
d7e4ef5
Update error messages
hannobraun Aug 18, 2023
6126ae2
Update struct field name
hannobraun Aug 18, 2023
cb173fb
Update argument name
hannobraun Aug 18, 2023
4fd9a42
Update method name
hannobraun Aug 18, 2023
ad1d4da
Update method name
hannobraun Aug 18, 2023
432377a
Update method name
hannobraun Aug 18, 2023
8854dde
Update method name
hannobraun Aug 18, 2023
230f35c
Update argument name
hannobraun Aug 18, 2023
befa025
Rename argument to prepare for follow-on change
hannobraun Aug 18, 2023
d949190
Update argument name
hannobraun Aug 18, 2023
a4b4a9c
Update argument name
hannobraun Aug 18, 2023
12e1874
Update struct field name
hannobraun Aug 18, 2023
0bb4e26
Update argument name
hannobraun Aug 18, 2023
334cb34
Update variable name
hannobraun Aug 18, 2023
423efa5
Update variable names
hannobraun Aug 18, 2023
69ae5bd
Update variable name
hannobraun Aug 18, 2023
a564daf
Update argument name
hannobraun Aug 18, 2023
5ce49c6
Update variable names
hannobraun Aug 18, 2023
6a58579
Update variable name
hannobraun Aug 18, 2023
cc3325c
Update variable name
hannobraun Aug 18, 2023
7373225
Update variable name
hannobraun Aug 18, 2023
9082041
Update variable name
hannobraun Aug 18, 2023
d8477a7
Update argument names
hannobraun Aug 18, 2023
c39026e
Update argument names
hannobraun Aug 18, 2023
70a6c32
Update variable name
hannobraun Aug 18, 2023
b39f457
Update variable names
hannobraun Aug 18, 2023
4ad08a3
Update trait method name
hannobraun Aug 18, 2023
e595b3b
Update argument name
hannobraun Aug 18, 2023
ff0b0b7
Update trait method name
hannobraun Aug 18, 2023
9a63951
Update trait method name
hannobraun Aug 18, 2023
862ee1c
Update variable name
hannobraun Aug 18, 2023
f082e4b
Update variable name
hannobraun Aug 18, 2023
491b18e
Update argument name
hannobraun Aug 18, 2023
12e8708
Update variable name
hannobraun Aug 18, 2023
2b29367
Update argument name
hannobraun Aug 18, 2023
a9dd5d7
Update variable name
hannobraun Aug 18, 2023
ca4ec58
Update variable name
hannobraun Aug 18, 2023
42f9f08
Update argument name
hannobraun Aug 18, 2023
b9ecdbf
Update variable name
hannobraun Aug 18, 2023
b7f8ab4
Update variable name
hannobraun Aug 18, 2023
31f08e3
Update variable name
hannobraun Aug 18, 2023
9e4e701
Update argument names
hannobraun Aug 18, 2023
6cb29ab
Update argument name
hannobraun Aug 18, 2023
650727d
Update variable name
hannobraun Aug 18, 2023
2411f67
Update variable name
hannobraun Aug 18, 2023
e2a1d50
Update argument name
hannobraun Aug 18, 2023
44bb3a9
Update method name
hannobraun Aug 18, 2023
977dc62
Update method name
hannobraun Aug 18, 2023
30946cc
Update field name
hannobraun Aug 18, 2023
8dd00b6
Update test name
hannobraun Aug 18, 2023
8dd6043
Update variable names
hannobraun Aug 18, 2023
bcec284
Update argument name
hannobraun Aug 18, 2023
80de38a
Update field name
hannobraun Aug 18, 2023
0154f69
Update argument name
hannobraun Aug 18, 2023
3152cf3
Update test name
hannobraun Aug 18, 2023
9dfee87
Update variable name
hannobraun Aug 18, 2023
53ff325
Update argument name
hannobraun Aug 18, 2023
16bc07f
Update argument name
hannobraun Aug 18, 2023
cbacb46
Update documentation of `Object`
hannobraun Aug 18, 2023
04192fe
Update documentation of `Cycle`
hannobraun Aug 18, 2023
a986cdf
Update panic message
hannobraun Aug 18, 2023
f3a604a
Update documentation of `Edge`
hannobraun Aug 18, 2023
cccf703
Update documentation of `BuildEdge`
hannobraun Aug 18, 2023
ac09efc
Update panic message
hannobraun Aug 18, 2023
2801c1d
Update documentation of `JoinCycle`
hannobraun Aug 18, 2023
fd078a1
Update documentation of `UpdateCycle`
hannobraun Aug 18, 2023
c3e00fe
Update panic messages
hannobraun Aug 18, 2023
6bde9f0
Update documentation of `UpdateEdge`
hannobraun Aug 18, 2023
ac75a5f
Update documentation of `CycleValidationError`
hannobraun Aug 18, 2023
4ca75f5
Update documentation of `EdgeValidationError`
hannobraun Aug 18, 2023
207576f
Update comments
hannobraun Aug 18, 2023
c6df4c9
Update documentation of `ShellValidationError`
hannobraun Aug 18, 2023
93bac19
Update panic message
hannobraun Aug 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions crates/fj-core/src/algorithms/approx/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use fj_math::Segment;
use crate::objects::{Cycle, Surface};

use super::{
edge::{EdgeCache, HalfEdgeApprox},
edge::{EdgeApprox, EdgeCache},
Approx, ApproxPoint, Tolerance,
};

Expand All @@ -25,30 +25,30 @@ impl Approx for (&Cycle, &Surface) {
let (cycle, surface) = self;
let tolerance = tolerance.into();

let half_edges = cycle
.half_edges()
.map(|half_edge| {
(half_edge.deref(), surface).approx_with_cache(tolerance, cache)
let edges = cycle
.edges()
.map(|edge| {
(edge.deref(), surface).approx_with_cache(tolerance, cache)
})
.collect();

CycleApprox { half_edges }
CycleApprox { edges }
}
}

/// An approximation of a [`Cycle`]
#[derive(Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct CycleApprox {
/// The approximated edges that make up the approximated cycle
pub half_edges: Vec<HalfEdgeApprox>,
pub edges: Vec<EdgeApprox>,
}

impl CycleApprox {
/// Compute the points that approximate the cycle
pub fn points(&self) -> Vec<ApproxPoint<2>> {
let mut points = Vec::new();

for approx in &self.half_edges {
for approx in &self.edges {
points.extend(approx.points());
}

Expand Down
97 changes: 47 additions & 50 deletions crates/fj-core/src/algorithms/approx/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,65 +11,63 @@ use fj_math::Point;

use crate::{
geometry::{CurveBoundary, GlobalPath, SurfacePath},
objects::{Curve, HalfEdge, Surface, Vertex},
objects::{Curve, Edge, Surface, Vertex},
storage::{Handle, HandleWrapper},
};

use super::{curve::CurveApproxSegment, Approx, ApproxPoint, Tolerance};

impl Approx for (&HalfEdge, &Surface) {
type Approximation = HalfEdgeApprox;
impl Approx for (&Edge, &Surface) {
type Approximation = EdgeApprox;
type Cache = EdgeCache;

fn approx_with_cache(
self,
tolerance: impl Into<Tolerance>,
cache: &mut Self::Cache,
) -> Self::Approximation {
let (half_edge, surface) = self;
let (edge, surface) = self;

let position_surface = half_edge.start_position();
let position_global = match cache.get_position(half_edge.start_vertex())
{
let position_surface = edge.start_position();
let position_global = match cache.get_position(edge.start_vertex()) {
Some(position) => position,
None => {
let position_global = surface
.geometry()
.point_from_surface_coords(position_surface);
cache.insert_position(half_edge.start_vertex(), position_global)
cache.insert_position(edge.start_vertex(), position_global)
}
};

let first = ApproxPoint::new(position_surface, position_global);

let points = {
// We cache approximated `HalfEdge`s using the `Curve`s they
// reference and their boundary on that curve as the key. That bakes
// in the undesirable assumption that all coincident `HalfEdge`s are
// also congruent. Let me explain.
// We cache approximated `Edge`s using the `Curve`s they reference
// and their boundary on that curve as the key. That bakes in the
// undesirable assumption that all coincident `Edge`s are also
// congruent. Let me explain.
//
// When two `HalfEdge`s are coincident, we need to make sure their
// When two `Edge`s are coincident, we need to make sure their
// approximations are identical where they overlap. Otherwise, we'll
// get an invalid triangle mesh in the end. Hence, we cache
// approximations.
//
// Caching works like this: We check whether there already is a
// cache entry for the curve/boundary. If there isn't, we create the
// 3D approximation from the 2D `HalfEdge`. Next time we check for a
// coincident `HalfEdge`, we'll find the cache and use that, getting
// 3D approximation from the 2D `Edge`. Next time we check for a
// coincident `Edge`, we'll find the cache and use that, getting
// the exact same 3D approximation, instead of generating a slightly
// different one from the different 2D `HalfEdge`.
// different one from the different 2D `Edge`.
//
// So what if we had two coincident `HalfEdge`s that aren't
// congruent? Meaning, they overlap partially, but not fully. Then
// obviously, they wouldn't refer to the same combination of curve
// and boundary. And since those are the key in our cache, those
// `HalfEdge`s would not share an approximation where they overlap,
// leading to exactly the problems that the cache is supposed to
// prevent.
// So what if we had two coincident `fEdge`s that aren't congruent?
// Meaning, they overlap partially, but not fully. Then obviously,
// they wouldn't refer to the same combination of curve and
// boundary. And since those are the key in our cache, those `Edge`s
// would not share an approximation where they overlap, leading to
// exactly the problems that the cache is supposed to prevent.
//
// As of this writing, it is a documented (but not validated)
// limitation, that coincident `HalfEdge`s must always be congruent.
// limitation, that coincident `Edge`s must always be congruent.
// However, we're going to need to lift this limitation going
// forward, as it is, well, too limiting. This means things here
// will need to change.
Expand All @@ -80,19 +78,19 @@ impl Approx for (&HalfEdge, &Surface) {
// able to deliver partial results for a given boundary, then
// generating (and caching) the rest of it on the fly.
let cached_approx =
cache.get_edge(half_edge.curve().clone(), half_edge.boundary());
cache.get_edge(edge.curve().clone(), edge.boundary());
let approx = match cached_approx {
Some(approx) => approx,
None => {
let approx = approx_edge(
&half_edge.path(),
&edge.path(),
surface,
half_edge.boundary(),
edge.boundary(),
tolerance,
);
cache.insert_edge(
half_edge.curve().clone(),
half_edge.boundary(),
edge.curve().clone(),
edge.boundary(),
approx,
)
}
Expand All @@ -102,30 +100,29 @@ impl Approx for (&HalfEdge, &Surface) {
.points
.into_iter()
.map(|point| {
let point_surface = half_edge
.path()
.point_from_path_coords(point.local_form);
let point_surface =
edge.path().point_from_path_coords(point.local_form);

ApproxPoint::new(point_surface, point.global_form)
})
.collect()
};

HalfEdgeApprox { first, points }
EdgeApprox { first, points }
}
}

/// An approximation of an [`HalfEdge`]
/// An approximation of an [`Edge`]
#[derive(Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct HalfEdgeApprox {
pub struct EdgeApprox {
/// The point that approximates the first vertex of the edge
pub first: ApproxPoint<2>,

/// The approximation of the edge
pub points: Vec<ApproxPoint<2>>,
}

impl HalfEdgeApprox {
impl EdgeApprox {
/// Compute the points that approximate the edge
pub fn points(&self) -> Vec<ApproxPoint<2>> {
let mut points = Vec::new();
Expand Down Expand Up @@ -287,8 +284,8 @@ mod tests {
use crate::{
algorithms::approx::{Approx, ApproxPoint},
geometry::{CurveBoundary, GlobalPath, SurfaceGeometry},
objects::{HalfEdge, Surface},
operations::BuildHalfEdge,
objects::{Edge, Surface},
operations::BuildEdge,
services::Services,
};

Expand All @@ -297,11 +294,11 @@ mod tests {
let mut services = Services::new();

let surface = services.objects.surfaces.xz_plane();
let half_edge =
HalfEdge::line_segment([[1., 1.], [2., 1.]], None, &mut services);
let edge =
Edge::line_segment([[1., 1.], [2., 1.]], None, &mut services);

let tolerance = 1.;
let approx = (&half_edge, surface.deref()).approx(tolerance);
let approx = (&edge, surface.deref()).approx(tolerance);

assert_eq!(approx.points, Vec::new());
}
Expand All @@ -314,11 +311,11 @@ mod tests {
u: GlobalPath::circle_from_radius(1.),
v: [0., 0., 1.].into(),
});
let half_edge =
HalfEdge::line_segment([[1., 1.], [2., 1.]], None, &mut services);
let edge =
Edge::line_segment([[1., 1.], [2., 1.]], None, &mut services);

let tolerance = 1.;
let approx = (&half_edge, &surface).approx(tolerance);
let approx = (&edge, &surface).approx(tolerance);

assert_eq!(approx.points, Vec::new());
}
Expand All @@ -334,21 +331,21 @@ mod tests {
u: path,
v: [0., 0., 1.].into(),
});
let half_edge = HalfEdge::line_segment(
let edge = Edge::line_segment(
[[0., 1.], [TAU, 1.]],
Some(boundary.inner),
&mut services,
);

let tolerance = 1.;
let approx = (&half_edge, &surface).approx(tolerance);
let approx = (&edge, &surface).approx(tolerance);

let expected_approx = (path, boundary)
.approx(tolerance)
.into_iter()
.map(|(point_local, _)| {
let point_surface =
half_edge.path().point_from_path_coords(point_local);
edge.path().point_from_path_coords(point_local);
let point_global =
surface.geometry().point_from_surface_coords(point_surface);
ApproxPoint::new(point_surface, point_global)
Expand All @@ -362,13 +359,13 @@ mod tests {
let mut services = Services::new();

let surface = services.objects.surfaces.xz_plane();
let half_edge = HalfEdge::circle([0., 0.], 1., &mut services);
let edge = Edge::circle([0., 0.], 1., &mut services);

let tolerance = 1.;
let approx = (&half_edge, surface.deref()).approx(tolerance);
let approx = (&edge, surface.deref()).approx(tolerance);

let expected_approx =
(&half_edge.path(), CurveBoundary::from([[0.], [TAU]]))
(&edge.path(), CurveBoundary::from([[0.], [TAU]]))
.approx(tolerance)
.into_iter()
.map(|(_, point_surface)| {
Expand Down
6 changes: 2 additions & 4 deletions crates/fj-core/src/algorithms/bounding_volume/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ impl super::BoundingVolume<2> for Cycle {
fn aabb(&self) -> Option<Aabb<2>> {
let mut aabb: Option<Aabb<2>> = None;

for half_edge in self.half_edges() {
let new_aabb = half_edge
.aabb()
.expect("`HalfEdge` can always compute AABB");
for edge in self.edges() {
let new_aabb = edge.aabb().expect("`Edge` can always compute AABB");
aabb = Some(aabb.map_or(new_aabb, |aabb| aabb.merged(&new_aabb)));
}

Expand Down
4 changes: 2 additions & 2 deletions crates/fj-core/src/algorithms/bounding_volume/edge.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use fj_math::{Aabb, Vector};

use crate::{geometry::SurfacePath, objects::HalfEdge};
use crate::{geometry::SurfacePath, objects::Edge};

impl super::BoundingVolume<2> for HalfEdge {
impl super::BoundingVolume<2> for Edge {
fn aabb(&self) -> Option<Aabb<2>> {
match self.path() {
SurfacePath::Circle(circle) => {
Expand Down
Loading