Merge pull request #2304 from hannobraun/geometry

Shorten names of geometry struct
This commit is contained in:
Hanno Braun 2024-03-27 12:34:33 +01:00 committed by GitHub
commit 4ad0844ced
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 56 additions and 59 deletions

View File

@ -6,7 +6,7 @@ use fj_math::Point;
use crate::{ use crate::{
geometry::{ geometry::{
CurveBoundary, Geometry, GlobalPath, HalfEdgeGeometry, SurfaceGeometry, CurveBoundary, Geometry, GlobalPath, HalfEdgeGeom, SurfaceGeom,
SurfacePath, SurfacePath,
}, },
storage::Handle, storage::Handle,
@ -15,7 +15,7 @@ use crate::{
use super::{Approx, ApproxPoint, Tolerance}; use super::{Approx, ApproxPoint, Tolerance};
impl Approx for (&Handle<Curve>, &HalfEdgeGeometry, &Handle<Surface>) { impl Approx for (&Handle<Curve>, &HalfEdgeGeom, &Handle<Surface>) {
type Approximation = CurveApprox; type Approximation = CurveApprox;
type Cache = CurveApproxCache; type Cache = CurveApproxCache;
@ -46,7 +46,7 @@ impl Approx for (&Handle<Curve>, &HalfEdgeGeometry, &Handle<Surface>) {
fn approx_curve( fn approx_curve(
path: &SurfacePath, path: &SurfacePath,
surface: &SurfaceGeometry, surface: &SurfaceGeom,
boundary: CurveBoundary<Point<1>>, boundary: CurveBoundary<Point<1>>,
tolerance: impl Into<Tolerance>, tolerance: impl Into<Tolerance>,
geometry: &Geometry, geometry: &Geometry,
@ -182,7 +182,7 @@ mod tests {
use crate::{ use crate::{
algorithms::approx::{Approx, ApproxPoint}, algorithms::approx::{Approx, ApproxPoint},
geometry::{CurveBoundary, GlobalPath, HalfEdgeGeometry, SurfacePath}, geometry::{CurveBoundary, GlobalPath, HalfEdgeGeom, SurfacePath},
operations::{build::BuildSurface, insert::Insert}, operations::{build::BuildSurface, insert::Insert},
topology::{Curve, Surface}, topology::{Curve, Surface},
Core, Core,
@ -196,7 +196,7 @@ mod tests {
let (path, boundary) = let (path, boundary) =
SurfacePath::line_from_points([[1., 1.], [2., 1.]]); SurfacePath::line_from_points([[1., 1.], [2., 1.]]);
let boundary = CurveBoundary::from(boundary); let boundary = CurveBoundary::from(boundary);
let half_edge = HalfEdgeGeometry { path, boundary }; let half_edge = HalfEdgeGeom { path, boundary };
let surface = core.layers.topology.surfaces.xz_plane(); let surface = core.layers.topology.surfaces.xz_plane();
let tolerance = 1.; let tolerance = 1.;
@ -214,7 +214,7 @@ mod tests {
let (path, boundary) = let (path, boundary) =
SurfacePath::line_from_points([[1., 1.], [2., 1.]]); SurfacePath::line_from_points([[1., 1.], [2., 1.]]);
let boundary = CurveBoundary::from(boundary); let boundary = CurveBoundary::from(boundary);
let half_edge = HalfEdgeGeometry { path, boundary }; let half_edge = HalfEdgeGeom { path, boundary };
let surface = Surface::from_uv( let surface = Surface::from_uv(
GlobalPath::circle_from_radius(1.), GlobalPath::circle_from_radius(1.),
[0., 0., 1.], [0., 0., 1.],
@ -239,7 +239,7 @@ mod tests {
([TAU], [TAU, 1.]), ([TAU], [TAU, 1.]),
]); ]);
let boundary = CurveBoundary::from([[0.], [TAU]]); let boundary = CurveBoundary::from([[0.], [TAU]]);
let half_edge = HalfEdgeGeometry { path, boundary }; let half_edge = HalfEdgeGeom { path, boundary };
let surface = Surface::from_uv(global_path, [0., 0., 1.], &mut core); let surface = Surface::from_uv(global_path, [0., 0., 1.], &mut core);
let tolerance = 1.; let tolerance = 1.;
@ -269,7 +269,7 @@ mod tests {
let curve = Curve::new().insert(&mut core); let curve = Curve::new().insert(&mut core);
let path = SurfacePath::circle_from_center_and_radius([0., 0.], 1.); let path = SurfacePath::circle_from_center_and_radius([0., 0.], 1.);
let boundary = CurveBoundary::from([[0.], [TAU]]); let boundary = CurveBoundary::from([[0.], [TAU]]);
let half_edge = HalfEdgeGeometry { path, boundary }; let half_edge = HalfEdgeGeom { path, boundary };
let surface = core.layers.topology.surfaces.xz_plane(); let surface = core.layers.topology.surfaces.xz_plane();
let tolerance = 1.; let tolerance = 1.;

View File

@ -7,12 +7,12 @@ use crate::{
topology::{HalfEdge, Surface, Topology}, topology::{HalfEdge, Surface, Topology},
}; };
use super::{GlobalPath, HalfEdgeGeometry, SurfaceGeometry}; use super::{GlobalPath, HalfEdgeGeom, SurfaceGeom};
/// Geometric data that is associated with topological objects /// Geometric data that is associated with topological objects
pub struct Geometry { pub struct Geometry {
half_edge: BTreeMap<Handle<HalfEdge>, HalfEdgeGeometry>, half_edge: BTreeMap<Handle<HalfEdge>, HalfEdgeGeom>,
surface: BTreeMap<Handle<Surface>, SurfaceGeometry>, surface: BTreeMap<Handle<Surface>, SurfaceGeom>,
xy_plane: Handle<Surface>, xy_plane: Handle<Surface>,
xz_plane: Handle<Surface>, xz_plane: Handle<Surface>,
@ -33,21 +33,21 @@ impl Geometry {
self_.define_surface_inner( self_.define_surface_inner(
self_.xy_plane.clone(), self_.xy_plane.clone(),
SurfaceGeometry { SurfaceGeom {
u: GlobalPath::x_axis(), u: GlobalPath::x_axis(),
v: Vector::unit_y(), v: Vector::unit_y(),
}, },
); );
self_.define_surface_inner( self_.define_surface_inner(
self_.xz_plane.clone(), self_.xz_plane.clone(),
SurfaceGeometry { SurfaceGeom {
u: GlobalPath::x_axis(), u: GlobalPath::x_axis(),
v: Vector::unit_z(), v: Vector::unit_z(),
}, },
); );
self_.define_surface_inner( self_.define_surface_inner(
self_.yz_plane.clone(), self_.yz_plane.clone(),
SurfaceGeometry { SurfaceGeom {
u: GlobalPath::y_axis(), u: GlobalPath::y_axis(),
v: Vector::unit_z(), v: Vector::unit_z(),
}, },
@ -59,7 +59,7 @@ impl Geometry {
pub(crate) fn define_half_edge_inner( pub(crate) fn define_half_edge_inner(
&mut self, &mut self,
half_edge: Handle<HalfEdge>, half_edge: Handle<HalfEdge>,
geometry: HalfEdgeGeometry, geometry: HalfEdgeGeom,
) { ) {
self.half_edge.insert(half_edge, geometry); self.half_edge.insert(half_edge, geometry);
} }
@ -67,7 +67,7 @@ impl Geometry {
pub(crate) fn define_surface_inner( pub(crate) fn define_surface_inner(
&mut self, &mut self,
surface: Handle<Surface>, surface: Handle<Surface>,
geometry: SurfaceGeometry, geometry: SurfaceGeom,
) { ) {
self.surface.insert(surface, geometry); self.surface.insert(surface, geometry);
} }
@ -77,10 +77,7 @@ impl Geometry {
/// ## Panics /// ## Panics
/// ///
/// Panics, if the geometry of the half-edge is not defined. /// Panics, if the geometry of the half-edge is not defined.
pub fn of_half_edge( pub fn of_half_edge(&self, half_edge: &Handle<HalfEdge>) -> &HalfEdgeGeom {
&self,
half_edge: &Handle<HalfEdge>,
) -> &HalfEdgeGeometry {
self.half_edge self.half_edge
.get(half_edge) .get(half_edge)
.expect("Expected geometry of half-edge to be defined") .expect("Expected geometry of half-edge to be defined")
@ -91,24 +88,24 @@ impl Geometry {
/// ## Panics /// ## Panics
/// ///
/// Panics, if the geometry of the surface is not defined. /// Panics, if the geometry of the surface is not defined.
pub fn of_surface(&self, surface: &Handle<Surface>) -> &SurfaceGeometry { pub fn of_surface(&self, surface: &Handle<Surface>) -> &SurfaceGeom {
self.surface self.surface
.get(surface) .get(surface)
.expect("Expected geometry of surface to be defined") .expect("Expected geometry of surface to be defined")
} }
/// Access the geometry of the xy-plane /// Access the geometry of the xy-plane
pub fn xy_plane(&self) -> &SurfaceGeometry { pub fn xy_plane(&self) -> &SurfaceGeom {
self.of_surface(&self.xy_plane) self.of_surface(&self.xy_plane)
} }
/// Access the geometry of the xz-plane /// Access the geometry of the xz-plane
pub fn xz_plane(&self) -> &SurfaceGeometry { pub fn xz_plane(&self) -> &SurfaceGeom {
self.of_surface(&self.xz_plane) self.of_surface(&self.xz_plane)
} }
/// Access the geometry of the yz-plane /// Access the geometry of the yz-plane
pub fn yz_plane(&self) -> &SurfaceGeometry { pub fn yz_plane(&self) -> &SurfaceGeom {
self.of_surface(&self.yz_plane) self.of_surface(&self.yz_plane)
} }
} }

View File

@ -4,7 +4,7 @@ use super::{CurveBoundary, SurfacePath};
/// The geometry of a half-edge /// The geometry of a half-edge
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct HalfEdgeGeometry { pub struct HalfEdgeGeom {
/// # The path of the half-edge /// # The path of the half-edge
/// ///
/// ## Implementation Note /// ## Implementation Note
@ -36,7 +36,7 @@ pub struct HalfEdgeGeometry {
pub boundary: CurveBoundary<Point<1>>, pub boundary: CurveBoundary<Point<1>>,
} }
impl HalfEdgeGeometry { impl HalfEdgeGeom {
/// Update the boundary /// Update the boundary
pub fn with_boundary( pub fn with_boundary(
mut self, mut self,

View File

@ -9,7 +9,7 @@ mod surface;
pub use self::{ pub use self::{
boundary::{CurveBoundary, CurveBoundaryElement}, boundary::{CurveBoundary, CurveBoundaryElement},
geometry::Geometry, geometry::Geometry,
half_edge::HalfEdgeGeometry, half_edge::HalfEdgeGeom,
path::{GlobalPath, SurfacePath}, path::{GlobalPath, SurfacePath},
surface::SurfaceGeometry, surface::SurfaceGeom,
}; };

View File

@ -6,7 +6,7 @@ use super::GlobalPath;
/// The geometry that defines a surface /// The geometry that defines a surface
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)] #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct SurfaceGeometry { pub struct SurfaceGeom {
/// The u-axis of the surface /// The u-axis of the surface
pub u: GlobalPath, pub u: GlobalPath,
@ -14,7 +14,7 @@ pub struct SurfaceGeometry {
pub v: Vector<3>, pub v: Vector<3>,
} }
impl SurfaceGeometry { impl SurfaceGeom {
/// Convert a point in surface coordinates to model coordinates /// Convert a point in surface coordinates to model coordinates
pub fn point_from_surface_coords( pub fn point_from_surface_coords(
&self, &self,
@ -64,11 +64,11 @@ mod tests {
use fj_math::{Line, Point, Vector}; use fj_math::{Line, Point, Vector};
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use crate::geometry::{GlobalPath, SurfaceGeometry}; use crate::geometry::{GlobalPath, SurfaceGeom};
#[test] #[test]
fn point_from_surface_coords() { fn point_from_surface_coords() {
let surface = SurfaceGeometry { let surface = SurfaceGeom {
u: GlobalPath::Line(Line::from_origin_and_direction( u: GlobalPath::Line(Line::from_origin_and_direction(
Point::from([1., 1., 1.]), Point::from([1., 1., 1.]),
Vector::from([0., 2., 0.]), Vector::from([0., 2., 0.]),
@ -84,7 +84,7 @@ mod tests {
#[test] #[test]
fn vector_from_surface_coords() { fn vector_from_surface_coords() {
let surface = SurfaceGeometry { let surface = SurfaceGeom {
u: GlobalPath::Line(Line::from_origin_and_direction( u: GlobalPath::Line(Line::from_origin_and_direction(
Point::from([1., 0., 0.]), Point::from([1., 0., 0.]),
Vector::from([0., 2., 0.]), Vector::from([0., 2., 0.]),

View File

@ -1,7 +1,7 @@
//! Layer infrastructure for [`Geometry`] //! Layer infrastructure for [`Geometry`]
use crate::{ use crate::{
geometry::{Geometry, HalfEdgeGeometry, SurfaceGeometry}, geometry::{Geometry, HalfEdgeGeom, SurfaceGeom},
storage::Handle, storage::Handle,
topology::{HalfEdge, Surface}, topology::{HalfEdge, Surface},
}; };
@ -13,7 +13,7 @@ impl Layer<Geometry> {
pub fn define_half_edge( pub fn define_half_edge(
&mut self, &mut self,
half_edge: Handle<HalfEdge>, half_edge: Handle<HalfEdge>,
geometry: HalfEdgeGeometry, geometry: HalfEdgeGeom,
) { ) {
let mut events = Vec::new(); let mut events = Vec::new();
self.process( self.process(
@ -29,7 +29,7 @@ impl Layer<Geometry> {
pub fn define_surface( pub fn define_surface(
&mut self, &mut self,
surface: Handle<Surface>, surface: Handle<Surface>,
geometry: SurfaceGeometry, geometry: SurfaceGeom,
) { ) {
let mut events = Vec::new(); let mut events = Vec::new();
self.process(DefineSurface { surface, geometry }, &mut events); self.process(DefineSurface { surface, geometry }, &mut events);
@ -39,7 +39,7 @@ impl Layer<Geometry> {
/// Define the geometry of a half-edge /// Define the geometry of a half-edge
pub struct DefineHalfEdge { pub struct DefineHalfEdge {
half_edge: Handle<HalfEdge>, half_edge: Handle<HalfEdge>,
geometry: HalfEdgeGeometry, geometry: HalfEdgeGeom,
} }
impl Command<Geometry> for DefineHalfEdge { impl Command<Geometry> for DefineHalfEdge {
@ -64,7 +64,7 @@ impl Event<Geometry> for DefineHalfEdge {
/// Define the geometry of a surface /// Define the geometry of a surface
pub struct DefineSurface { pub struct DefineSurface {
surface: Handle<Surface>, surface: Handle<Surface>,
geometry: SurfaceGeometry, geometry: SurfaceGeom,
} }
impl Command<Geometry> for DefineSurface { impl Command<Geometry> for DefineSurface {

View File

@ -2,7 +2,7 @@ use fj_interop::ext::ArrayExt;
use fj_math::{Arc, Point, Scalar}; use fj_math::{Arc, Point, Scalar};
use crate::{ use crate::{
geometry::{HalfEdgeGeometry, SurfacePath}, geometry::{HalfEdgeGeom, SurfacePath},
operations::{geometry::UpdateHalfEdgeGeometry, insert::Insert}, operations::{geometry::UpdateHalfEdgeGeometry, insert::Insert},
storage::Handle, storage::Handle,
topology::{Curve, HalfEdge, Vertex}, topology::{Curve, HalfEdge, Vertex},
@ -63,7 +63,7 @@ pub trait BuildHalfEdge {
let half_edge = HalfEdge::unjoined(core).insert(core); let half_edge = HalfEdge::unjoined(core).insert(core);
core.layers.geometry.define_half_edge( core.layers.geometry.define_half_edge(
half_edge.clone(), half_edge.clone(),
HalfEdgeGeometry { HalfEdgeGeom {
path, path,
boundary: boundary.into(), boundary: boundary.into(),
}, },
@ -85,7 +85,7 @@ pub trait BuildHalfEdge {
let half_edge = HalfEdge::unjoined(core).insert(core); let half_edge = HalfEdge::unjoined(core).insert(core);
core.layers.geometry.define_half_edge( core.layers.geometry.define_half_edge(
half_edge.clone(), half_edge.clone(),
HalfEdgeGeometry { HalfEdgeGeom {
path, path,
boundary: boundary.into(), boundary: boundary.into(),
}, },
@ -107,7 +107,7 @@ pub trait BuildHalfEdge {
); );
HalfEdge::unjoined(core).insert(core).set_geometry( HalfEdge::unjoined(core).insert(core).set_geometry(
HalfEdgeGeometry { HalfEdgeGeom {
path, path,
boundary: boundary.into(), boundary: boundary.into(),
}, },

View File

@ -1,7 +1,7 @@
use fj_math::{Point, Scalar, Vector}; use fj_math::{Point, Scalar, Vector};
use crate::{ use crate::{
geometry::{GlobalPath, SurfaceGeometry}, geometry::{GlobalPath, SurfaceGeom},
operations::insert::Insert, operations::insert::Insert,
storage::Handle, storage::Handle,
topology::Surface, topology::Surface,
@ -47,7 +47,7 @@ pub trait BuildSurface {
core.layers.geometry.define_surface( core.layers.geometry.define_surface(
surface.clone(), surface.clone(),
SurfaceGeometry { SurfaceGeom {
u: u.into(), u: u.into(),
v: v.into(), v: v.into(),
}, },

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
geometry::{Geometry, HalfEdgeGeometry}, geometry::{Geometry, HalfEdgeGeom},
layers::Layer, layers::Layer,
storage::Handle, storage::Handle,
topology::HalfEdge, topology::HalfEdge,
@ -10,7 +10,7 @@ pub trait UpdateHalfEdgeGeometry {
/// Set the path of the half-edge /// Set the path of the half-edge
fn set_geometry( fn set_geometry(
self, self,
geometry: HalfEdgeGeometry, geometry: HalfEdgeGeom,
layer: &mut Layer<Geometry>, layer: &mut Layer<Geometry>,
) -> Self; ) -> Self;
} }
@ -18,7 +18,7 @@ pub trait UpdateHalfEdgeGeometry {
impl UpdateHalfEdgeGeometry for Handle<HalfEdge> { impl UpdateHalfEdgeGeometry for Handle<HalfEdge> {
fn set_geometry( fn set_geometry(
self, self,
geometry: HalfEdgeGeometry, geometry: HalfEdgeGeom,
layer: &mut Layer<Geometry>, layer: &mut Layer<Geometry>,
) -> Self { ) -> Self {
layer.define_half_edge(self.clone(), geometry); layer.define_half_edge(self.clone(), geometry);

View File

@ -3,7 +3,7 @@ use std::ops::RangeInclusive;
use itertools::Itertools; use itertools::Itertools;
use crate::{ use crate::{
geometry::HalfEdgeGeometry, geometry::HalfEdgeGeom,
operations::{ operations::{
build::BuildHalfEdge, build::BuildHalfEdge,
geometry::UpdateHalfEdgeGeometry, geometry::UpdateHalfEdgeGeometry,
@ -21,7 +21,7 @@ pub trait JoinCycle {
#[must_use] #[must_use]
fn add_joined_edges<Es>(&self, edges: Es, core: &mut Core) -> Self fn add_joined_edges<Es>(&self, edges: Es, core: &mut Core) -> Self
where where
Es: IntoIterator<Item = (Handle<HalfEdge>, HalfEdgeGeometry)>, Es: IntoIterator<Item = (Handle<HalfEdge>, HalfEdgeGeom)>,
Es::IntoIter: Clone + ExactSizeIterator; Es::IntoIter: Clone + ExactSizeIterator;
/// Join the cycle to another /// Join the cycle to another
@ -78,7 +78,7 @@ pub trait JoinCycle {
impl JoinCycle for Cycle { impl JoinCycle for Cycle {
fn add_joined_edges<Es>(&self, edges: Es, core: &mut Core) -> Self fn add_joined_edges<Es>(&self, edges: Es, core: &mut Core) -> Self
where where
Es: IntoIterator<Item = (Handle<HalfEdge>, HalfEdgeGeometry)>, Es: IntoIterator<Item = (Handle<HalfEdge>, HalfEdgeGeom)>,
Es::IntoIter: Clone + ExactSizeIterator, Es::IntoIter: Clone + ExactSizeIterator,
{ {
let half_edges = edges let half_edges = edges

View File

@ -1,7 +1,7 @@
use fj_math::{Circle, Line, Vector}; use fj_math::{Circle, Line, Vector};
use crate::{ use crate::{
geometry::{GlobalPath, SurfaceGeometry, SurfacePath}, geometry::{GlobalPath, SurfaceGeom, SurfacePath},
operations::build::BuildSurface, operations::build::BuildSurface,
storage::Handle, storage::Handle,
topology::Surface, topology::Surface,
@ -26,7 +26,7 @@ pub trait SweepSurfacePath {
/// <https://github.com/hannobraun/fornjot/issues/1112> /// <https://github.com/hannobraun/fornjot/issues/1112>
fn sweep_surface_path( fn sweep_surface_path(
&self, &self,
surface: &SurfaceGeometry, surface: &SurfaceGeom,
path: impl Into<Vector<3>>, path: impl Into<Vector<3>>,
core: &mut Core, core: &mut Core,
) -> Handle<Surface>; ) -> Handle<Surface>;
@ -35,7 +35,7 @@ pub trait SweepSurfacePath {
impl SweepSurfacePath for SurfacePath { impl SweepSurfacePath for SurfacePath {
fn sweep_surface_path( fn sweep_surface_path(
&self, &self,
surface: &SurfaceGeometry, surface: &SurfaceGeom,
path: impl Into<Vector<3>>, path: impl Into<Vector<3>>,
core: &mut Core, core: &mut Core,
) -> Handle<Surface> { ) -> Handle<Surface> {

View File

@ -3,7 +3,7 @@ use std::{collections::BTreeMap, fmt};
use fj_math::{Point, Scalar}; use fj_math::{Point, Scalar};
use crate::{ use crate::{
geometry::{CurveBoundary, Geometry, SurfaceGeometry}, geometry::{CurveBoundary, Geometry, SurfaceGeom},
queries::{ queries::{
AllHalfEdgesWithSurface, BoundingVerticesOfHalfEdge, SiblingOfHalfEdge, AllHalfEdgesWithSurface, BoundingVerticesOfHalfEdge, SiblingOfHalfEdge,
}, },
@ -101,9 +101,9 @@ impl ShellValidationError {
fn compare_curve_coords( fn compare_curve_coords(
edge_a: &Handle<HalfEdge>, edge_a: &Handle<HalfEdge>,
surface_a: &SurfaceGeometry, surface_a: &SurfaceGeom,
edge_b: &Handle<HalfEdge>, edge_b: &Handle<HalfEdge>,
surface_b: &SurfaceGeometry, surface_b: &SurfaceGeom,
geometry: &Geometry, geometry: &Geometry,
config: &ValidationConfig, config: &ValidationConfig,
mismatches: &mut Vec<CurveCoordinateSystemMismatch>, mismatches: &mut Vec<CurveCoordinateSystemMismatch>,
@ -382,14 +382,14 @@ impl fmt::Display for CoincidentHalfEdgeVertices {
/// Returns an [`Iterator`] of the distance at each sample. /// Returns an [`Iterator`] of the distance at each sample.
fn distances( fn distances(
edge_a: Handle<HalfEdge>, edge_a: Handle<HalfEdge>,
surface_a: &SurfaceGeometry, surface_a: &SurfaceGeom,
edge_b: Handle<HalfEdge>, edge_b: Handle<HalfEdge>,
surface_b: &SurfaceGeometry, surface_b: &SurfaceGeom,
geometry: &Geometry, geometry: &Geometry,
) -> impl Iterator<Item = Scalar> { ) -> impl Iterator<Item = Scalar> {
fn sample( fn sample(
percent: f64, percent: f64,
(edge, surface): (&Handle<HalfEdge>, &SurfaceGeometry), (edge, surface): (&Handle<HalfEdge>, &SurfaceGeom),
geometry: &Geometry, geometry: &Geometry,
) -> Point<3> { ) -> Point<3> {
let [start, end] = geometry.of_half_edge(edge).boundary.inner; let [start, end] = geometry.of_half_edge(edge).boundary.inner;