mirror of https://github.com/hannobraun/Fornjot
Merge pull request #2375 from hannobraun/circle
Build circle-cycle out of multiple arcs
This commit is contained in:
commit
9033890a90
|
@ -1,8 +1,8 @@
|
||||||
use fj_math::{Point, Scalar};
|
use fj_math::{Point, Scalar, Vector};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
operations::{build::BuildHalfEdge, update::UpdateCycle},
|
operations::{build::BuildHalfEdge, insert::Insert, update::UpdateCycle},
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
topology::{Cycle, HalfEdge, Surface},
|
topology::{Cycle, HalfEdge, Surface},
|
||||||
Core,
|
Core,
|
||||||
|
@ -19,15 +19,47 @@ pub trait BuildCycle {
|
||||||
Cycle::new([])
|
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(
|
fn circle(
|
||||||
center: impl Into<Point<2>>,
|
center: impl Into<Point<2>>,
|
||||||
radius: impl Into<Scalar>,
|
radius: impl Into<Scalar>,
|
||||||
surface: Handle<Surface>,
|
surface: Handle<Surface>,
|
||||||
core: &mut Core,
|
core: &mut Core,
|
||||||
) -> Cycle {
|
) -> Cycle {
|
||||||
let circle = HalfEdge::circle(center, radius, surface, core);
|
let center = center.into();
|
||||||
Cycle::empty().add_half_edges([circle], core)
|
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
|
/// Build a polygon
|
||||||
|
|
|
@ -81,35 +81,6 @@ pub trait BuildHalfEdge {
|
||||||
half_edge
|
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
|
/// Create a line segment
|
||||||
fn line_segment(
|
fn line_segment(
|
||||||
points_surface: [impl Into<Point<2>>; 2],
|
points_surface: [impl Into<Point<2>>; 2],
|
||||||
|
|
Loading…
Reference in New Issue