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

Build circle-cycle out of multiple arcs #2375

Merged
merged 2 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
42 changes: 37 additions & 5 deletions crates/fj-core/src/operations/build/cycle.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use fj_math::{Point, Scalar};
use fj_math::{Point, Scalar, Vector};
use itertools::Itertools;

use crate::{
operations::{build::BuildHalfEdge, update::UpdateCycle},
operations::{build::BuildHalfEdge, insert::Insert, update::UpdateCycle},
storage::Handle,
topology::{Cycle, HalfEdge, Surface},
Core,
Expand All @@ -19,15 +19,47 @@ pub trait BuildCycle {
Cycle::new([])
}

/// Build a circle
/// # Build a circle
///
/// This circle is built out of 4 distinct arcs.
///
/// ## Implementation Note
///
/// The cycle can't be built out of a single half-edge. That would be
/// invalid although there's not validation check to document and enforce
/// that yet. Please refer to the following issue for more information:
/// <https://github.com/hannobraun/fornjot/issues/2374>
///
/// The cycle is built out of 4 arcs specifically, because that's easier to
/// implement than three, and building it out of two creates geometry that
/// the cycle winding code can't handle right now. The following issue has
/// more information on the cycle winding problems:
/// <https://github.com/hannobraun/fornjot/issues/2130>
fn circle(
center: impl Into<Point<2>>,
radius: impl Into<Scalar>,
surface: Handle<Surface>,
core: &mut Core,
) -> Cycle {
let circle = HalfEdge::circle(center, radius, surface, core);
Cycle::empty().add_half_edges([circle], core)
let center = center.into();
let radius = radius.into();

let radius_right = Vector::from([radius, Scalar::ZERO]);
let radius_up = Vector::from([Scalar::ZERO, radius]);

let a = center + radius_right;
let b = center + radius_up;
let c = center - radius_right;
let d = center - radius_up;

let angle = Scalar::TAU / 4.;

let ab = HalfEdge::arc(a, b, angle, surface.clone(), core).insert(core);
let bc = HalfEdge::arc(b, c, angle, surface.clone(), core).insert(core);
let cd = HalfEdge::arc(c, d, angle, surface.clone(), core).insert(core);
let da = HalfEdge::arc(d, a, angle, surface.clone(), core).insert(core);

Cycle::empty().add_half_edges([ab, bc, cd, da], core)
}

/// Build a polygon
Expand Down
29 changes: 0 additions & 29 deletions crates/fj-core/src/operations/build/half_edge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,35 +81,6 @@ pub trait BuildHalfEdge {
half_edge
}

/// Create a circle
fn circle(
center: impl Into<Point<2>>,
radius: impl Into<Scalar>,
surface: Handle<Surface>,
core: &mut Core,
) -> Handle<HalfEdge> {
let path = SurfacePath::circle_from_center_and_radius(center, radius);
let boundary =
[Scalar::ZERO, Scalar::TAU].map(|coord| Point::from([coord]));

let half_edge = HalfEdge::unjoined(core).insert(core);

core.layers.geometry.define_curve(
half_edge.curve().clone(),
surface,
LocalCurveGeom { path },
);
core.layers.geometry.define_half_edge(
half_edge.clone(),
HalfEdgeGeom {
path,
boundary: boundary.into(),
},
);

half_edge
}

/// Create a line segment
fn line_segment(
points_surface: [impl Into<Point<2>>; 2],
Expand Down
Loading