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

Add PartialHalfEdge::start_position #1636

Merged
merged 10 commits into from
Mar 1, 2023
49 changes: 24 additions & 25 deletions crates/fj-kernel/src/algorithms/approx/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,12 @@ mod tests {

use crate::{
algorithms::approx::{path::RangeOnPath, Approx, ApproxPoint},
builder::{HalfEdgeBuilder, SurfaceBuilder},
builder::{CycleBuilder, HalfEdgeBuilder, SurfaceBuilder},
geometry::curve::GlobalPath,
insert::Insert,
partial::{PartialHalfEdge, PartialObject, PartialSurface},
partial::{
PartialCycle, PartialHalfEdge, PartialObject, PartialSurface,
},
services::Services,
};

Expand All @@ -244,17 +246,16 @@ mod tests {

let surface = services.objects.surfaces.xz_plane();
let half_edge = {
let mut half_edge = PartialHalfEdge::default();
let mut cycle = PartialCycle::default();

half_edge.update_as_line_segment_from_points(
[[1., 1.], [2., 1.]],
half_edge.end_vertex.clone(),
);
half_edge.infer_vertex_positions_if_necessary(
let [mut half_edge, next_half_edge, _] = cycle
.update_as_polygon_from_points([[1., 1.], [2., 1.], [1., 2.]]);
half_edge.write().infer_vertex_positions_if_necessary(
&surface.geometry(),
half_edge.end_vertex.clone(),
next_half_edge.read().start_vertex.clone(),
);

let half_edge = half_edge.read().clone();
half_edge
.build(&mut services.objects)
.insert(&mut services.objects)
Expand All @@ -277,17 +278,16 @@ mod tests {
.build(&mut services.objects)
.insert(&mut services.objects);
let half_edge = {
let mut half_edge = PartialHalfEdge::default();
let mut cycle = PartialCycle::default();

half_edge.update_as_line_segment_from_points(
[[1., 1.], [2., 1.]],
half_edge.end_vertex.clone(),
);
half_edge.infer_vertex_positions_if_necessary(
let [mut half_edge, next_half_edge, _] = cycle
.update_as_polygon_from_points([[1., 1.], [2., 1.], [1., 2.]]);
half_edge.write().infer_vertex_positions_if_necessary(
&surface.geometry(),
half_edge.end_vertex.clone(),
next_half_edge.read().start_vertex.clone(),
);

let half_edge = half_edge.read().clone();
half_edge
.build(&mut services.objects)
.insert(&mut services.objects)
Expand All @@ -310,21 +310,20 @@ mod tests {
.build(&mut services.objects)
.insert(&mut services.objects);
let half_edge = {
let mut half_edge = PartialHalfEdge::default();
let mut cycle = PartialCycle::default();

half_edge.update_as_line_segment_from_points(
[[0., 1.], [1., 1.]],
half_edge.end_vertex.clone(),
);
let [mut half_edge, next_half_edge, _] = cycle
.update_as_polygon_from_points([[0., 1.], [1., 1.], [1., 2.]]);

half_edge.boundary[0] = Some(range.boundary[0]);
half_edge.boundary[1] = Some(range.boundary[1]);
half_edge.write().boundary[0] = Some(range.boundary[0]);
half_edge.write().boundary[1] = Some(range.boundary[1]);

half_edge.infer_vertex_positions_if_necessary(
half_edge.write().infer_vertex_positions_if_necessary(
&surface.geometry(),
half_edge.end_vertex.clone(),
next_half_edge.read().start_vertex.clone(),
);

let half_edge = half_edge.read().clone();
half_edge
.build(&mut services.objects)
.insert(&mut services.objects)
Expand Down
64 changes: 34 additions & 30 deletions crates/fj-kernel/src/algorithms/intersect/curve_edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ mod tests {
use fj_math::Point;

use crate::{
builder::HalfEdgeBuilder,
builder::{CycleBuilder, HalfEdgeBuilder},
geometry::curve::Curve,
partial::{PartialHalfEdge, PartialObject},
partial::PartialCycle,
services::Services,
};

Expand All @@ -87,14 +87,13 @@ mod tests {
let surface = services.objects.surfaces.xy_plane();
let curve = Curve::u_axis();
let half_edge = {
let mut half_edge = PartialHalfEdge::default();
half_edge.update_as_line_segment_from_points(
[[1., -1.], [1., 1.]],
half_edge.end_vertex.clone(),
);
half_edge.infer_vertex_positions_if_necessary(
let mut cycle = PartialCycle::default();

let [mut half_edge, next_half_edge, _] = cycle
.update_as_polygon_from_points([[1., -1.], [1., 1.], [0., 1.]]);
half_edge.write().infer_vertex_positions_if_necessary(
&surface.geometry(),
half_edge.end_vertex.clone(),
next_half_edge.read().start_vertex.clone(),
);

half_edge.build(&mut services.objects)
Expand All @@ -117,14 +116,17 @@ mod tests {
let surface = services.objects.surfaces.xy_plane();
let curve = Curve::u_axis();
let half_edge = {
let mut half_edge = PartialHalfEdge::default();
half_edge.update_as_line_segment_from_points(
[[-1., -1.], [-1., 1.]],
half_edge.end_vertex.clone(),
);
half_edge.infer_vertex_positions_if_necessary(
let mut cycle = PartialCycle::default();

let [mut half_edge, next_half_edge, _] = cycle
.update_as_polygon_from_points([
[-1., -1.],
[-1., 1.],
[0., 1.],
]);
half_edge.write().infer_vertex_positions_if_necessary(
&surface.geometry(),
half_edge.end_vertex.clone(),
next_half_edge.read().start_vertex.clone(),
);

half_edge.build(&mut services.objects)
Expand All @@ -147,14 +149,17 @@ mod tests {
let surface = services.objects.surfaces.xy_plane();
let curve = Curve::u_axis();
let half_edge = {
let mut half_edge = PartialHalfEdge::default();
half_edge.update_as_line_segment_from_points(
[[-1., -1.], [1., -1.]],
half_edge.end_vertex.clone(),
);
half_edge.infer_vertex_positions_if_necessary(
let mut cycle = PartialCycle::default();

let [mut half_edge, next_half_edge, _] = cycle
.update_as_polygon_from_points([
[-1., -1.],
[1., -1.],
[1., 1.],
]);
half_edge.write().infer_vertex_positions_if_necessary(
&surface.geometry(),
half_edge.end_vertex.clone(),
next_half_edge.read().start_vertex.clone(),
);

half_edge.build(&mut services.objects)
Expand All @@ -172,14 +177,13 @@ mod tests {
let surface = services.objects.surfaces.xy_plane();
let curve = Curve::u_axis();
let half_edge = {
let mut half_edge = PartialHalfEdge::default();
half_edge.update_as_line_segment_from_points(
[[-1., 0.], [1., 0.]],
half_edge.end_vertex.clone(),
);
half_edge.infer_vertex_positions_if_necessary(
let mut cycle = PartialCycle::default();

let [mut half_edge, next_half_edge, _] = cycle
.update_as_polygon_from_points([[-1., 0.], [1., 0.], [1., 1.]]);
half_edge.write().infer_vertex_positions_if_necessary(
&surface.geometry(),
half_edge.end_vertex.clone(),
next_half_edge.read().start_vertex.clone(),
);

half_edge.build(&mut services.objects)
Expand Down
3 changes: 1 addition & 2 deletions crates/fj-kernel/src/algorithms/sweep/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,7 @@ impl Sweep for (Handle<HalfEdge>, &Handle<SurfaceVertex>, &Surface, Color) {
.into_iter()
.circular_tuple_windows()
{
edge.write()
.update_as_line_segment(next.read().start_vertex.clone());
edge.write().update_as_line_segment(next.clone());
}

// Finally, we can make sure that all edges refer to the correct global
Expand Down
4 changes: 1 addition & 3 deletions crates/fj-kernel/src/builder/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,7 @@ impl CycleBuilder for PartialCycle {
for (mut half_edge, next) in
self.half_edges.iter().cloned().circular_tuple_windows()
{
half_edge
.write()
.update_as_line_segment(next.read().start_vertex.clone());
half_edge.write().update_as_line_segment(next.clone());
}
}

Expand Down
61 changes: 22 additions & 39 deletions crates/fj-kernel/src/builder/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,13 @@ pub trait HalfEdgeBuilder {
fn update_as_arc(
&mut self,
angle_rad: impl Into<Scalar>,
next_vertex: Partial<SurfaceVertex>,
next_half_edge: Partial<HalfEdge>,
);

/// Update partial half-edge to be a line segment, from the given points
fn update_as_line_segment_from_points(
&mut self,
points: [impl Into<Point<2>>; 2],
next_vertex: Partial<SurfaceVertex>,
) -> Curve;

/// Update partial half-edge to be a line segment
fn update_as_line_segment(
&mut self,
next_vertex: Partial<SurfaceVertex>,
next_half_edge: Partial<HalfEdge>,
) -> Curve;

/// Infer the global form of the half-edge
Expand Down Expand Up @@ -104,17 +97,18 @@ impl HalfEdgeBuilder for PartialHalfEdge {
fn update_as_arc(
&mut self,
angle_rad: impl Into<Scalar>,
mut next_vertex: Partial<SurfaceVertex>,
mut next_half_edge: Partial<HalfEdge>,
) {
let angle_rad = angle_rad.into();
if angle_rad <= -Scalar::TAU || angle_rad >= Scalar::TAU {
panic!("arc angle must be in the range (-2pi, 2pi) radians");
}
let [start, end] = [&self.start_vertex, &next_vertex].map(|vertex| {
vertex
.read()
.position
.expect("Can't infer arc without surface position")
let [start, end] = [
&self.start_position(),
&next_half_edge.read().start_position(),
]
.map(|position| {
position.expect("Can't infer arc without surface position")
});

let arc = fj_math::Arc::from_endpoints_and_angle(start, end, angle_rad);
Expand All @@ -128,42 +122,31 @@ impl HalfEdgeBuilder for PartialHalfEdge {
for ((point_boundary, surface_vertex), point_curve) in self
.boundary
.each_mut_ext()
.zip_ext([&mut self.start_vertex, &mut next_vertex])
.zip_ext([
&mut self.start_vertex,
&mut next_half_edge.write().start_vertex,
])
.zip_ext([a_curve, b_curve])
{
*point_boundary = Some(point_curve);
surface_vertex.write().position =
Some(path.point_from_path_coords(point_curve));
}

self.infer_global_form(next_vertex);
}

fn update_as_line_segment_from_points(
&mut self,
points: [impl Into<Point<2>>; 2],
mut next_vertex: Partial<SurfaceVertex>,
) -> Curve {
for (vertex, point) in
[&mut self.start_vertex, &mut next_vertex].zip_ext(points)
{
let mut surface_form = vertex.write();
surface_form.position = Some(point.into());
}

self.update_as_line_segment(next_vertex)
self.infer_global_form(next_half_edge.read().start_vertex.clone());
}

fn update_as_line_segment(
&mut self,
next_vertex: Partial<SurfaceVertex>,
next_half_edge: Partial<HalfEdge>,
) -> Curve {
let boundary = self.boundary;
let points_surface = [&self.start_vertex, &next_vertex].map(|vertex| {
vertex
.read()
.position
.expect("Can't infer line segment without surface position")
let points_surface = [
&self.start_position(),
&next_half_edge.read().start_position(),
]
.map(|position| {
position.expect("Can't infer line segment without surface position")
});

let path = if let [Some(start), Some(end)] = boundary {
Expand All @@ -186,7 +169,7 @@ impl HalfEdgeBuilder for PartialHalfEdge {
path
};

self.infer_global_form(next_vertex);
self.infer_global_form(next_half_edge.read().start_vertex.clone());

path
}
Expand Down
31 changes: 15 additions & 16 deletions crates/fj-kernel/src/objects/full/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@ mod tests {
use pretty_assertions::assert_eq;

use crate::{
builder::HalfEdgeBuilder,
partial::{PartialHalfEdge, PartialObject},
builder::{CycleBuilder, HalfEdgeBuilder},
partial::PartialCycle,
services::Services,
};

Expand All @@ -190,29 +190,28 @@ mod tests {

let a = [0., 0.];
let b = [1., 0.];
let c = [0., 1.];

let a_to_b = {
let mut half_edge = PartialHalfEdge::default();
half_edge.update_as_line_segment_from_points(
[a, b],
half_edge.end_vertex.clone(),
);
half_edge.infer_vertex_positions_if_necessary(
let mut cycle = PartialCycle::default();

let [mut half_edge, next_half_edge, _] =
cycle.update_as_polygon_from_points([a, b, c]);
half_edge.write().infer_vertex_positions_if_necessary(
&surface.geometry(),
half_edge.end_vertex.clone(),
next_half_edge.read().start_vertex.clone(),
);

half_edge.build(&mut services.objects)
};
let b_to_a = {
let mut half_edge = PartialHalfEdge::default();
half_edge.update_as_line_segment_from_points(
[b, a],
half_edge.end_vertex.clone(),
);
half_edge.infer_vertex_positions_if_necessary(
let mut cycle = PartialCycle::default();

let [mut half_edge, next_half_edge, _] =
cycle.update_as_polygon_from_points([b, a, c]);
half_edge.write().infer_vertex_positions_if_necessary(
&surface.geometry(),
half_edge.end_vertex.clone(),
next_half_edge.read().start_vertex.clone(),
);

half_edge.build(&mut services.objects)
Expand Down
7 changes: 7 additions & 0 deletions crates/fj-kernel/src/partial/objects/edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ pub struct PartialHalfEdge {
pub global_form: Partial<GlobalEdge>,
}

impl PartialHalfEdge {
/// Compute the surface position where the half-edge starts
pub fn start_position(&self) -> Option<Point<2>> {
self.start_vertex.read().position
}
}

impl PartialObject for PartialHalfEdge {
type Full = HalfEdge;

Expand Down
Loading