From 39b0274a92f119a763196cb38a74367cc0377639 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 6 Jun 2024 19:50:54 +0200 Subject: [PATCH] Build circle-cycle out of multiple arcs See the updated documentation for motivation. --- crates/fj-core/src/operations/build/cycle.rs | 42 +++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/crates/fj-core/src/operations/build/cycle.rs b/crates/fj-core/src/operations/build/cycle.rs index ca5b47f61..b36a3eee6 100644 --- a/crates/fj-core/src/operations/build/cycle.rs +++ b/crates/fj-core/src/operations/build/cycle.rs @@ -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, @@ -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: + /// + /// + /// 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: + /// fn circle( center: impl Into>, radius: impl Into, surface: Handle, 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