mirror of
https://github.com/hannobraun/Fornjot
synced 2025-02-12 18:26:00 +00:00
Merge pull request #1596 from hannobraun/surface
Move reference to `Surface` from `Curve` to `HalfEdge`
This commit is contained in:
commit
abef26ea52
@ -13,13 +13,13 @@ use std::collections::BTreeMap;
|
||||
|
||||
use crate::{
|
||||
geometry::path::{GlobalPath, SurfacePath},
|
||||
objects::{Curve, GlobalCurve},
|
||||
objects::{Curve, GlobalCurve, Surface},
|
||||
storage::{Handle, ObjectId},
|
||||
};
|
||||
|
||||
use super::{path::RangeOnPath, Approx, ApproxPoint, Tolerance};
|
||||
|
||||
impl Approx for (&Handle<Curve>, RangeOnPath) {
|
||||
impl Approx for (&Handle<Curve>, &Surface, RangeOnPath) {
|
||||
type Approximation = CurveApprox;
|
||||
type Cache = CurveCache;
|
||||
|
||||
@ -28,13 +28,14 @@ impl Approx for (&Handle<Curve>, RangeOnPath) {
|
||||
tolerance: impl Into<Tolerance>,
|
||||
cache: &mut Self::Cache,
|
||||
) -> Self::Approximation {
|
||||
let (curve, range) = self;
|
||||
let (curve, surface, range) = self;
|
||||
|
||||
let global_curve = curve.global_form().clone();
|
||||
let global_curve_approx = match cache.get(global_curve.clone(), range) {
|
||||
Some(approx) => approx,
|
||||
None => {
|
||||
let approx = approx_global_curve(curve, range, tolerance);
|
||||
let approx =
|
||||
approx_global_curve(curve, surface, range, tolerance);
|
||||
cache.insert(global_curve, range, approx)
|
||||
}
|
||||
};
|
||||
@ -53,6 +54,7 @@ impl Approx for (&Handle<Curve>, RangeOnPath) {
|
||||
|
||||
fn approx_global_curve(
|
||||
curve: &Curve,
|
||||
surface: &Surface,
|
||||
range: RangeOnPath,
|
||||
tolerance: impl Into<Tolerance>,
|
||||
) -> GlobalCurveApprox {
|
||||
@ -62,7 +64,7 @@ fn approx_global_curve(
|
||||
// This will probably all be unified eventually, as `SurfacePath` and
|
||||
// `GlobalPath` grow APIs that are better suited to implementing this code
|
||||
// in a more abstract way.
|
||||
let points = match (curve.path(), curve.surface().geometry().u) {
|
||||
let points = match (curve.path(), surface.geometry().u) {
|
||||
(SurfacePath::Circle(_), GlobalPath::Circle(_)) => {
|
||||
todo!(
|
||||
"Approximating a circle on a curved surface not supported yet."
|
||||
@ -88,8 +90,7 @@ fn approx_global_curve(
|
||||
// surface point available, so it needs to be computed
|
||||
// later anyway, in the general case.
|
||||
|
||||
let point_global = curve
|
||||
.surface()
|
||||
let point_global = surface
|
||||
.geometry()
|
||||
.point_from_surface_coords(point_surface);
|
||||
(point_curve, point_global)
|
||||
@ -102,17 +103,15 @@ fn approx_global_curve(
|
||||
[curve.path().point_from_path_coords(point_curve).u]
|
||||
}));
|
||||
|
||||
let approx_u = (curve.surface().geometry().u, range_u)
|
||||
let approx_u = (surface.geometry().u, range_u)
|
||||
.approx_with_cache(tolerance, &mut ());
|
||||
|
||||
let mut points = Vec::new();
|
||||
for (u, _) in approx_u {
|
||||
let t = (u.t - line.origin().u) / line.direction().u;
|
||||
let point_surface = curve.path().point_from_path_coords([t]);
|
||||
let point_global = curve
|
||||
.surface()
|
||||
.geometry()
|
||||
.point_from_surface_coords(point_surface);
|
||||
let point_global =
|
||||
surface.geometry().point_from_surface_coords(point_surface);
|
||||
points.push((u, point_global));
|
||||
}
|
||||
|
||||
@ -211,7 +210,7 @@ impl GlobalCurveApprox {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::f64::consts::TAU;
|
||||
use std::{f64::consts::TAU, ops::Deref};
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
@ -220,7 +219,7 @@ mod tests {
|
||||
builder::{CurveBuilder, SurfaceBuilder},
|
||||
geometry::path::GlobalPath,
|
||||
insert::Insert,
|
||||
partial::{Partial, PartialCurve, PartialObject, PartialSurface},
|
||||
partial::{PartialCurve, PartialObject, PartialSurface},
|
||||
services::Services,
|
||||
};
|
||||
|
||||
@ -231,17 +230,14 @@ mod tests {
|
||||
let mut services = Services::new();
|
||||
|
||||
let surface = services.objects.surfaces.xz_plane();
|
||||
let mut curve = PartialCurve {
|
||||
surface: Partial::from(surface),
|
||||
..Default::default()
|
||||
};
|
||||
let mut curve = PartialCurve::default();
|
||||
curve.update_as_line_from_points([[1., 1.], [2., 1.]]);
|
||||
let curve = curve
|
||||
.build(&mut services.objects)
|
||||
.insert(&mut services.objects);
|
||||
let range = RangeOnPath::from([[0.], [1.]]);
|
||||
|
||||
let approx = (&curve, range).approx(1.);
|
||||
let approx = (&curve, surface.deref(), range).approx(1.);
|
||||
|
||||
assert_eq!(approx, CurveApprox::empty());
|
||||
}
|
||||
@ -256,17 +252,14 @@ mod tests {
|
||||
)
|
||||
.build(&mut services.objects)
|
||||
.insert(&mut services.objects);
|
||||
let mut curve = PartialCurve {
|
||||
surface: Partial::from(surface),
|
||||
..Default::default()
|
||||
};
|
||||
let mut curve = PartialCurve::default();
|
||||
curve.update_as_line_from_points([[1., 1.], [1., 2.]]);
|
||||
let curve = curve
|
||||
.build(&mut services.objects)
|
||||
.insert(&mut services.objects);
|
||||
let range = RangeOnPath::from([[0.], [1.]]);
|
||||
|
||||
let approx = (&curve, range).approx(1.);
|
||||
let approx = (&curve, surface.deref(), range).approx(1.);
|
||||
|
||||
assert_eq!(approx, CurveApprox::empty());
|
||||
}
|
||||
@ -279,10 +272,7 @@ mod tests {
|
||||
let surface = PartialSurface::from_axes(path, [0., 0., 1.])
|
||||
.build(&mut services.objects)
|
||||
.insert(&mut services.objects);
|
||||
let mut curve = PartialCurve {
|
||||
surface: Partial::from(surface.clone()),
|
||||
..Default::default()
|
||||
};
|
||||
let mut curve = PartialCurve::default();
|
||||
curve.update_as_line_from_points([[0., 1.], [1., 1.]]);
|
||||
let curve = curve
|
||||
.build(&mut services.objects)
|
||||
@ -291,7 +281,7 @@ mod tests {
|
||||
let range = RangeOnPath::from([[0.], [TAU]]);
|
||||
let tolerance = 1.;
|
||||
|
||||
let approx = (&curve, range).approx(tolerance);
|
||||
let approx = (&curve, surface.deref(), range).approx(tolerance);
|
||||
|
||||
let expected_approx = (path, range)
|
||||
.approx(tolerance)
|
||||
@ -312,10 +302,7 @@ mod tests {
|
||||
let mut services = Services::new();
|
||||
|
||||
let surface = services.objects.surfaces.xz_plane();
|
||||
let mut curve = PartialCurve {
|
||||
surface: Partial::from(surface),
|
||||
..Default::default()
|
||||
};
|
||||
let mut curve = PartialCurve::default();
|
||||
curve.update_as_circle_from_radius(1.);
|
||||
let curve = curve
|
||||
.build(&mut services.objects)
|
||||
@ -323,16 +310,14 @@ mod tests {
|
||||
|
||||
let range = RangeOnPath::from([[0.], [TAU]]);
|
||||
let tolerance = 1.;
|
||||
let approx = (&curve, range).approx(tolerance);
|
||||
let approx = (&curve, surface.deref(), range).approx(tolerance);
|
||||
|
||||
let expected_approx = (curve.path(), range)
|
||||
.approx(tolerance)
|
||||
.into_iter()
|
||||
.map(|(_, point_surface)| {
|
||||
let point_global = curve
|
||||
.surface()
|
||||
.geometry()
|
||||
.point_from_surface_coords(point_surface);
|
||||
let point_global =
|
||||
surface.geometry().point_from_surface_coords(point_surface);
|
||||
ApproxPoint::new(point_surface, point_global)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -5,6 +5,8 @@
|
||||
//! approximations are usually used to build cycle approximations, and this way,
|
||||
//! the caller doesn't have to call with duplicate vertices.
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::{objects::HalfEdge, storage::Handle};
|
||||
|
||||
use super::{
|
||||
@ -30,8 +32,8 @@ impl Approx for &Handle<HalfEdge> {
|
||||
self.start_vertex().global_form().position(),
|
||||
)
|
||||
.with_source((self.clone(), self.boundary()[0]));
|
||||
let curve_approx =
|
||||
(self.curve(), range).approx_with_cache(tolerance, cache);
|
||||
let curve_approx = (self.curve(), self.surface().deref(), range)
|
||||
.approx_with_cache(tolerance, cache);
|
||||
|
||||
HalfEdgeApprox {
|
||||
first,
|
||||
|
@ -87,10 +87,7 @@ mod tests {
|
||||
let mut services = Services::new();
|
||||
|
||||
let surface = Partial::from(services.objects.surfaces.xy_plane());
|
||||
let mut curve = PartialCurve {
|
||||
surface: surface.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut curve = PartialCurve::default();
|
||||
curve.update_as_u_axis();
|
||||
let curve = curve.build(&mut services.objects);
|
||||
let half_edge = {
|
||||
@ -118,10 +115,7 @@ mod tests {
|
||||
let mut services = Services::new();
|
||||
|
||||
let surface = Partial::from(services.objects.surfaces.xy_plane());
|
||||
let mut curve = PartialCurve {
|
||||
surface: surface.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut curve = PartialCurve::default();
|
||||
curve.update_as_u_axis();
|
||||
let curve = curve.build(&mut services.objects);
|
||||
let half_edge = {
|
||||
@ -149,10 +143,7 @@ mod tests {
|
||||
let mut services = Services::new();
|
||||
|
||||
let surface = Partial::from(services.objects.surfaces.xy_plane());
|
||||
let mut curve = PartialCurve {
|
||||
surface: surface.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut curve = PartialCurve::default();
|
||||
curve.update_as_u_axis();
|
||||
let curve = curve.build(&mut services.objects);
|
||||
let half_edge = {
|
||||
@ -175,10 +166,7 @@ mod tests {
|
||||
let mut services = Services::new();
|
||||
|
||||
let surface = Partial::from(services.objects.surfaces.xy_plane());
|
||||
let mut curve = PartialCurve {
|
||||
surface: surface.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut curve = PartialCurve::default();
|
||||
curve.update_as_u_axis();
|
||||
let curve = curve.build(&mut services.objects);
|
||||
let half_edge = {
|
||||
|
@ -163,10 +163,7 @@ mod tests {
|
||||
|
||||
let surface = Partial::from(services.objects.surfaces.xy_plane());
|
||||
|
||||
let mut curve = PartialCurve {
|
||||
surface: surface.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let mut curve = PartialCurve::default();
|
||||
curve.update_as_line_from_points([[-3., 0.], [-2., 0.]]);
|
||||
let curve = curve.build(&mut services.objects);
|
||||
|
||||
|
@ -132,11 +132,8 @@ mod tests {
|
||||
let intersection =
|
||||
FaceFaceIntersection::compute([&a, &b], &mut services.objects);
|
||||
|
||||
let expected_curves = surfaces.map(|surface| {
|
||||
let mut curve = PartialCurve {
|
||||
surface: Partial::from(surface),
|
||||
..Default::default()
|
||||
};
|
||||
let expected_curves = surfaces.map(|_| {
|
||||
let mut curve = PartialCurve::default();
|
||||
curve.update_as_line_from_points([[0., 0.], [1., 0.]]);
|
||||
curve
|
||||
.build(&mut services.objects)
|
||||
|
@ -27,14 +27,10 @@ impl SurfaceSurfaceIntersection {
|
||||
// Adaptations were made to get the intersection curves in local
|
||||
// coordinates for each surface.
|
||||
|
||||
let surfaces_and_planes = surfaces.map(|surface| {
|
||||
let plane = plane_from_surface(&surface);
|
||||
(surface, plane)
|
||||
});
|
||||
let [a, b] = surfaces_and_planes.clone().map(|(_, plane)| plane);
|
||||
let planes = surfaces.map(|surface| plane_from_surface(&surface));
|
||||
|
||||
let (a_distance, a_normal) = a.constant_normal_form();
|
||||
let (b_distance, b_normal) = b.constant_normal_form();
|
||||
let [(a_distance, a_normal), (b_distance, b_normal)] =
|
||||
planes.map(|plane| plane.constant_normal_form());
|
||||
|
||||
let direction = a_normal.cross(&b_normal);
|
||||
|
||||
@ -57,11 +53,11 @@ impl SurfaceSurfaceIntersection {
|
||||
|
||||
let line = Line::from_origin_and_direction(origin, direction);
|
||||
|
||||
let curves = surfaces_and_planes.map(|(surface, plane)| {
|
||||
let curves = planes.map(|plane| {
|
||||
let path = SurfacePath::Line(plane.project_line(&line));
|
||||
let global_form = GlobalCurve.insert(objects);
|
||||
|
||||
Curve::new(surface, path, global_form).insert(objects)
|
||||
Curve::new(path, global_form).insert(objects)
|
||||
});
|
||||
|
||||
Some(Self {
|
||||
@ -92,7 +88,7 @@ mod tests {
|
||||
algorithms::transform::TransformObject,
|
||||
builder::CurveBuilder,
|
||||
insert::Insert,
|
||||
partial::{Partial, PartialCurve, PartialObject},
|
||||
partial::{PartialCurve, PartialObject},
|
||||
services::Services,
|
||||
};
|
||||
|
||||
@ -120,18 +116,13 @@ mod tests {
|
||||
None,
|
||||
);
|
||||
|
||||
let mut expected_xy = PartialCurve {
|
||||
surface: Partial::from(xy.clone()),
|
||||
..Default::default()
|
||||
};
|
||||
let mut expected_xy = PartialCurve::default();
|
||||
expected_xy.update_as_u_axis();
|
||||
let expected_xy = expected_xy
|
||||
.build(&mut services.objects)
|
||||
.insert(&mut services.objects);
|
||||
let mut expected_xz = PartialCurve {
|
||||
surface: Partial::from(xz.clone()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut expected_xz = PartialCurve::default();
|
||||
expected_xz.update_as_u_axis();
|
||||
let expected_xz = expected_xz
|
||||
.build(&mut services.objects)
|
||||
|
@ -19,6 +19,7 @@ impl Reverse for Handle<HalfEdge> {
|
||||
};
|
||||
|
||||
HalfEdge::new(
|
||||
self.surface().clone(),
|
||||
self.curve().clone(),
|
||||
vertices,
|
||||
self.global_form().clone(),
|
||||
|
@ -12,7 +12,7 @@ use crate::{
|
||||
|
||||
use super::{Sweep, SweepCache};
|
||||
|
||||
impl Sweep for Handle<Curve> {
|
||||
impl Sweep for (Handle<Curve>, &Surface) {
|
||||
type Swept = Handle<Surface>;
|
||||
|
||||
fn sweep_with_cache(
|
||||
@ -21,7 +21,9 @@ impl Sweep for Handle<Curve> {
|
||||
_: &mut SweepCache,
|
||||
objects: &mut Service<Objects>,
|
||||
) -> Self::Swept {
|
||||
match self.surface().geometry().u {
|
||||
let (curve, surface) = self;
|
||||
|
||||
match surface.geometry().u {
|
||||
GlobalPath::Circle(_) => {
|
||||
// Sweeping a `Curve` creates a `Surface`. The u-axis of that
|
||||
// `Surface` is a `GlobalPath`, which we are computing below.
|
||||
@ -45,32 +47,24 @@ impl Sweep for Handle<Curve> {
|
||||
}
|
||||
}
|
||||
|
||||
let u = match self.path() {
|
||||
let u = match curve.path() {
|
||||
SurfacePath::Circle(circle) => {
|
||||
let center = self
|
||||
.surface()
|
||||
let center = surface
|
||||
.geometry()
|
||||
.point_from_surface_coords(circle.center());
|
||||
let a = self
|
||||
.surface()
|
||||
.geometry()
|
||||
.vector_from_surface_coords(circle.a());
|
||||
let b = self
|
||||
.surface()
|
||||
.geometry()
|
||||
.vector_from_surface_coords(circle.b());
|
||||
let a =
|
||||
surface.geometry().vector_from_surface_coords(circle.a());
|
||||
let b =
|
||||
surface.geometry().vector_from_surface_coords(circle.b());
|
||||
|
||||
let circle = Circle::new(center, a, b);
|
||||
|
||||
GlobalPath::Circle(circle)
|
||||
}
|
||||
SurfacePath::Line(line) => {
|
||||
let origin = self
|
||||
.surface()
|
||||
.geometry()
|
||||
.point_from_surface_coords(line.origin());
|
||||
let direction = self
|
||||
.surface()
|
||||
let origin =
|
||||
surface.geometry().point_from_surface_coords(line.origin());
|
||||
let direction = surface
|
||||
.geometry()
|
||||
.vector_from_surface_coords(line.direction());
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
use fj_interop::{ext::ArrayExt, mesh::Color};
|
||||
use fj_math::{Point, Scalar, Vector};
|
||||
|
||||
@ -34,7 +36,8 @@ impl Sweep for (Handle<HalfEdge>, Color) {
|
||||
// be created by sweeping a curve, so let's sweep the curve of the edge
|
||||
// we're sweeping.
|
||||
face.exterior.write().surface = Partial::from(
|
||||
edge.curve().clone().sweep_with_cache(path, cache, objects),
|
||||
(edge.curve().clone(), edge.surface().deref())
|
||||
.sweep_with_cache(path, cache, objects),
|
||||
);
|
||||
|
||||
// Now we're ready to create the edges.
|
||||
@ -194,7 +197,7 @@ mod tests {
|
||||
};
|
||||
let side_up = {
|
||||
let mut side_up = PartialHalfEdge::default();
|
||||
side_up.curve.write().surface = surface.clone();
|
||||
side_up.replace_surface(surface.clone());
|
||||
|
||||
{
|
||||
let [back, front] = side_up
|
||||
@ -206,7 +209,6 @@ mod tests {
|
||||
|
||||
let mut front = front.write();
|
||||
front.position = Some([1., 1.].into());
|
||||
front.surface = surface.clone();
|
||||
}
|
||||
|
||||
side_up.infer_global_form();
|
||||
@ -216,7 +218,7 @@ mod tests {
|
||||
};
|
||||
let top = {
|
||||
let mut top = PartialHalfEdge::default();
|
||||
top.curve.write().surface = surface.clone();
|
||||
top.replace_surface(surface.clone());
|
||||
|
||||
{
|
||||
let [(back, back_surface), (front, front_surface)] =
|
||||
@ -228,7 +230,6 @@ mod tests {
|
||||
*front = Some(Point::from([0.]));
|
||||
let mut front_surface = front_surface.write();
|
||||
front_surface.position = Some([0., 1.].into());
|
||||
front_surface.surface = surface.clone();
|
||||
}
|
||||
|
||||
top.infer_global_form();
|
||||
@ -243,7 +244,7 @@ mod tests {
|
||||
};
|
||||
let side_down = {
|
||||
let mut side_down = PartialHalfEdge::default();
|
||||
side_down.curve.write().surface = surface;
|
||||
side_down.replace_surface(surface);
|
||||
|
||||
let [(back, back_surface), (front, front_surface)] =
|
||||
side_down.vertices.each_mut_ext();
|
||||
|
@ -18,16 +18,12 @@ impl TransformObject for Curve {
|
||||
// coordinates, and thus transforming `surface` takes care of it.
|
||||
let path = self.path();
|
||||
|
||||
let surface = self
|
||||
.surface()
|
||||
.clone()
|
||||
.transform_with_cache(transform, objects, cache);
|
||||
let global_form = self
|
||||
.global_form()
|
||||
.clone()
|
||||
.transform_with_cache(transform, objects, cache);
|
||||
|
||||
Self::new(surface, path, global_form)
|
||||
Self::new(path, global_form)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,10 @@ impl TransformObject for HalfEdge {
|
||||
objects: &mut Service<Objects>,
|
||||
cache: &mut TransformCache,
|
||||
) -> Self {
|
||||
let surface = self
|
||||
.surface()
|
||||
.clone()
|
||||
.transform_with_cache(transform, objects, cache);
|
||||
let curve = self
|
||||
.curve()
|
||||
.clone()
|
||||
@ -32,7 +36,7 @@ impl TransformObject for HalfEdge {
|
||||
.clone()
|
||||
.transform_with_cache(transform, objects, cache);
|
||||
|
||||
Self::new(curve, boundary, global_form)
|
||||
Self::new(surface, curve, boundary, global_form)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ impl HalfEdgeBuilder for PartialHalfEdge {
|
||||
fn replace_surface(&mut self, surface: impl Into<Partial<Surface>>) {
|
||||
let surface = surface.into();
|
||||
|
||||
self.curve.write().surface = surface.clone();
|
||||
self.surface = surface.clone();
|
||||
|
||||
for vertex in &mut self.vertices {
|
||||
vertex.1.write().surface = surface.clone();
|
||||
@ -134,14 +134,11 @@ impl HalfEdgeBuilder for PartialHalfEdge {
|
||||
surface: impl Into<Partial<Surface>>,
|
||||
points: [impl Into<Point<2>>; 2],
|
||||
) {
|
||||
let surface = surface.into();
|
||||
|
||||
self.curve.write().surface = surface.clone();
|
||||
self.replace_surface(surface.into());
|
||||
|
||||
for (vertex, point) in self.vertices.each_mut_ext().zip_ext(points) {
|
||||
let mut surface_form = vertex.1.write();
|
||||
surface_form.position = Some(point.into());
|
||||
surface_form.surface = surface.clone();
|
||||
}
|
||||
|
||||
self.update_as_line_segment()
|
||||
@ -196,7 +193,7 @@ impl HalfEdgeBuilder for PartialHalfEdge {
|
||||
|
||||
self.curve.write().path =
|
||||
other.read().curve.read().path.as_ref().and_then(|path| {
|
||||
match other.read().curve.read().surface.read().geometry {
|
||||
match other.read().surface.read().geometry {
|
||||
Some(surface) => {
|
||||
// We have information about the other edge's surface
|
||||
// available. We need to use that to interpret what the
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::{
|
||||
geometry::path::SurfacePath,
|
||||
objects::Surface,
|
||||
storage::{Handle, HandleWrapper},
|
||||
};
|
||||
|
||||
@ -8,19 +7,16 @@ use crate::{
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||
pub struct Curve {
|
||||
path: SurfacePath,
|
||||
surface: Handle<Surface>,
|
||||
global_form: HandleWrapper<GlobalCurve>,
|
||||
}
|
||||
|
||||
impl Curve {
|
||||
/// Construct a new instance of `Curve`
|
||||
pub fn new(
|
||||
surface: Handle<Surface>,
|
||||
path: SurfacePath,
|
||||
global_form: impl Into<HandleWrapper<GlobalCurve>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
surface,
|
||||
path,
|
||||
global_form: global_form.into(),
|
||||
}
|
||||
@ -31,11 +27,6 @@ impl Curve {
|
||||
self.path
|
||||
}
|
||||
|
||||
/// Access the surface that the curve is defined in
|
||||
pub fn surface(&self) -> &Handle<Surface> {
|
||||
&self.surface
|
||||
}
|
||||
|
||||
/// Access the global form of the curve
|
||||
pub fn global_form(&self) -> &Handle<GlobalCurve> {
|
||||
&self.global_form
|
||||
|
@ -39,7 +39,7 @@ impl Cycle {
|
||||
/// Access the surface that the cycle is in
|
||||
pub fn surface(&self) -> &Handle<Surface> {
|
||||
if let Some(half_edge) = self.half_edges.first() {
|
||||
return half_edge.curve().surface();
|
||||
return half_edge.surface();
|
||||
}
|
||||
|
||||
unreachable!(
|
||||
|
@ -4,13 +4,14 @@ use fj_interop::ext::ArrayExt;
|
||||
use fj_math::Point;
|
||||
|
||||
use crate::{
|
||||
objects::{Curve, GlobalCurve, GlobalVertex, SurfaceVertex},
|
||||
objects::{Curve, GlobalCurve, GlobalVertex, Surface, SurfaceVertex},
|
||||
storage::{Handle, HandleWrapper},
|
||||
};
|
||||
|
||||
/// A half-edge
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||
pub struct HalfEdge {
|
||||
surface: Handle<Surface>,
|
||||
curve: Handle<Curve>,
|
||||
boundary: [(Point<1>, Handle<SurfaceVertex>); 2],
|
||||
global_form: Handle<GlobalEdge>,
|
||||
@ -19,17 +20,24 @@ pub struct HalfEdge {
|
||||
impl HalfEdge {
|
||||
/// Create an instance of `HalfEdge`
|
||||
pub fn new(
|
||||
surface: Handle<Surface>,
|
||||
curve: Handle<Curve>,
|
||||
boundary: [(Point<1>, Handle<SurfaceVertex>); 2],
|
||||
global_form: Handle<GlobalEdge>,
|
||||
) -> Self {
|
||||
Self {
|
||||
surface,
|
||||
curve,
|
||||
boundary,
|
||||
global_form,
|
||||
}
|
||||
}
|
||||
|
||||
/// Access the surface that the half-edge is defined in
|
||||
pub fn surface(&self) -> &Handle<Surface> {
|
||||
&self.surface
|
||||
}
|
||||
|
||||
/// Access the curve that defines the half-edge's geometry
|
||||
pub fn curve(&self) -> &Handle<Curve> {
|
||||
&self.curve
|
||||
|
@ -2,7 +2,7 @@ use fj_math::Scalar;
|
||||
|
||||
use crate::{
|
||||
geometry::path::SurfacePath,
|
||||
objects::{Curve, GlobalCurve, Objects, Surface},
|
||||
objects::{Curve, GlobalCurve, Objects},
|
||||
partial::{FullToPartialCache, Partial, PartialObject},
|
||||
services::Service,
|
||||
};
|
||||
@ -13,9 +13,6 @@ pub struct PartialCurve {
|
||||
/// The path that defines the curve
|
||||
pub path: Option<MaybeSurfacePath>,
|
||||
|
||||
/// The surface the curve is defined in
|
||||
pub surface: Partial<Surface>,
|
||||
|
||||
/// The global form of the curve
|
||||
pub global_form: Partial<GlobalCurve>,
|
||||
}
|
||||
@ -26,7 +23,6 @@ impl PartialObject for PartialCurve {
|
||||
fn from_full(curve: &Self::Full, cache: &mut FullToPartialCache) -> Self {
|
||||
Self {
|
||||
path: Some(curve.path().into()),
|
||||
surface: Partial::from_full(curve.surface().clone(), cache),
|
||||
global_form: Partial::from_full(curve.global_form().clone(), cache),
|
||||
}
|
||||
}
|
||||
@ -40,10 +36,9 @@ impl PartialObject for PartialCurve {
|
||||
)
|
||||
}
|
||||
};
|
||||
let surface = self.surface.build(objects);
|
||||
let global_form = self.global_form.build(objects);
|
||||
|
||||
Curve::new(surface, path, global_form)
|
||||
Curve::new(path, global_form)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ use fj_math::Point;
|
||||
use crate::{
|
||||
objects::{
|
||||
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
||||
SurfaceVertex,
|
||||
Surface, SurfaceVertex,
|
||||
},
|
||||
partial::{
|
||||
FullToPartialCache, Partial, PartialObject, PartialSurfaceVertex,
|
||||
@ -17,6 +17,9 @@ use crate::{
|
||||
/// A partial [`HalfEdge`]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PartialHalfEdge {
|
||||
/// The surface that the half-edge is defined in
|
||||
pub surface: Partial<Surface>,
|
||||
|
||||
/// The curve that the half-edge is defined in
|
||||
pub curve: Partial<Curve>,
|
||||
|
||||
@ -35,6 +38,7 @@ impl PartialObject for PartialHalfEdge {
|
||||
cache: &mut FullToPartialCache,
|
||||
) -> Self {
|
||||
Self {
|
||||
surface: Partial::from_full(half_edge.surface().clone(), cache),
|
||||
curve: Partial::from_full(half_edge.curve().clone(), cache),
|
||||
vertices: half_edge
|
||||
.boundary()
|
||||
@ -53,6 +57,7 @@ impl PartialObject for PartialHalfEdge {
|
||||
}
|
||||
|
||||
fn build(self, objects: &mut Service<Objects>) -> Self::Full {
|
||||
let surface = self.surface.build(objects);
|
||||
let curve = self.curve.build(objects);
|
||||
let vertices = self.vertices.map(|mut vertex| {
|
||||
let position_surface = vertex.1.read().position;
|
||||
@ -76,10 +81,9 @@ impl PartialObject for PartialHalfEdge {
|
||||
// Infer global position, if not available.
|
||||
let position_global = vertex.1.read().global_form.read().position;
|
||||
if position_global.is_none() {
|
||||
let surface = curve.surface().geometry();
|
||||
|
||||
let position_global =
|
||||
surface.point_from_surface_coords(position_surface);
|
||||
let position_global = surface
|
||||
.geometry()
|
||||
.point_from_surface_coords(position_surface);
|
||||
vertex.1.write().global_form.write().position =
|
||||
Some(position_global);
|
||||
}
|
||||
@ -92,18 +96,18 @@ impl PartialObject for PartialHalfEdge {
|
||||
});
|
||||
let global_form = self.global_form.build(objects);
|
||||
|
||||
HalfEdge::new(curve, vertices, global_form)
|
||||
HalfEdge::new(surface, curve, vertices, global_form)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PartialHalfEdge {
|
||||
fn default() -> Self {
|
||||
let surface = Partial::new();
|
||||
|
||||
let curve = Partial::<Curve>::new();
|
||||
let vertices = array::from_fn(|_| {
|
||||
let surface = Partial::new();
|
||||
|
||||
let surface_form = Partial::from_partial(PartialSurfaceVertex {
|
||||
surface,
|
||||
surface: surface.clone(),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
@ -125,6 +129,7 @@ impl Default for PartialHalfEdge {
|
||||
});
|
||||
|
||||
Self {
|
||||
surface,
|
||||
curve,
|
||||
vertices,
|
||||
global_form,
|
||||
|
@ -165,13 +165,13 @@ impl HalfEdgeValidationError {
|
||||
half_edge: &HalfEdge,
|
||||
errors: &mut Vec<ValidationError>,
|
||||
) {
|
||||
let curve_surface = half_edge.curve().surface();
|
||||
let surface = half_edge.surface();
|
||||
let surface_form_surface = half_edge.start_vertex().surface();
|
||||
|
||||
if curve_surface.id() != surface_form_surface.id() {
|
||||
if surface.id() != surface_form_surface.id() {
|
||||
errors.push(
|
||||
Box::new(Self::SurfaceMismatch {
|
||||
curve_surface: curve_surface.clone(),
|
||||
curve_surface: surface.clone(),
|
||||
surface_form_surface: surface_form_surface.clone(),
|
||||
})
|
||||
.into(),
|
||||
@ -240,7 +240,12 @@ mod tests {
|
||||
.boundary()
|
||||
.zip_ext(valid.surface_vertices().map(Clone::clone));
|
||||
|
||||
HalfEdge::new(valid.curve().clone(), vertices, global_form)
|
||||
HalfEdge::new(
|
||||
valid.surface().clone(),
|
||||
valid.curve().clone(),
|
||||
vertices,
|
||||
global_form,
|
||||
)
|
||||
};
|
||||
|
||||
valid.validate_and_return_first_error()?;
|
||||
@ -282,7 +287,12 @@ mod tests {
|
||||
.boundary()
|
||||
.zip_ext(valid.surface_vertices().map(Clone::clone));
|
||||
|
||||
HalfEdge::new(valid.curve().clone(), vertices, global_form)
|
||||
HalfEdge::new(
|
||||
valid.surface().clone(),
|
||||
valid.curve().clone(),
|
||||
vertices,
|
||||
global_form,
|
||||
)
|
||||
};
|
||||
|
||||
valid.validate_and_return_first_error()?;
|
||||
@ -318,6 +328,7 @@ mod tests {
|
||||
});
|
||||
|
||||
HalfEdge::new(
|
||||
valid.surface().clone(),
|
||||
valid.curve().clone(),
|
||||
vertices,
|
||||
valid.global_form().clone(),
|
||||
@ -349,6 +360,7 @@ mod tests {
|
||||
});
|
||||
|
||||
HalfEdge::new(
|
||||
valid.surface().clone(),
|
||||
valid.curve().clone(),
|
||||
vertices,
|
||||
valid.global_form().clone(),
|
||||
|
@ -31,13 +31,7 @@ impl Shape for fj::Sketch {
|
||||
let surface = Partial::from(surface);
|
||||
|
||||
let mut half_edge = PartialHalfEdge::default();
|
||||
|
||||
half_edge.curve.write().surface = surface.clone();
|
||||
|
||||
for vertex in &mut half_edge.vertices {
|
||||
vertex.1.write().surface = surface.clone();
|
||||
}
|
||||
|
||||
half_edge.replace_surface(surface);
|
||||
half_edge.update_as_circle_from_radius(circle.radius());
|
||||
|
||||
Partial::from_partial(half_edge)
|
||||
|
Loading…
Reference in New Issue
Block a user