mirror of
https://github.com/hannobraun/Fornjot
synced 2025-01-30 20:05:55 +00:00
Merge pull request #1607 from hannobraun/curve
Remove reference to `GlobalCurve` from `Curve`
This commit is contained in:
commit
89e2e93ac3
@ -19,7 +19,7 @@ use crate::{
|
|||||||
|
|
||||||
use super::{path::RangeOnPath, Approx, ApproxPoint, Tolerance};
|
use super::{path::RangeOnPath, Approx, ApproxPoint, Tolerance};
|
||||||
|
|
||||||
impl Approx for (&Handle<Curve>, &Surface, RangeOnPath) {
|
impl Approx for (&Handle<Curve>, &Surface, Handle<GlobalCurve>, RangeOnPath) {
|
||||||
type Approximation = CurveApprox;
|
type Approximation = CurveApprox;
|
||||||
type Cache = CurveCache;
|
type Cache = CurveCache;
|
||||||
|
|
||||||
@ -28,9 +28,8 @@ impl Approx for (&Handle<Curve>, &Surface, RangeOnPath) {
|
|||||||
tolerance: impl Into<Tolerance>,
|
tolerance: impl Into<Tolerance>,
|
||||||
cache: &mut Self::Cache,
|
cache: &mut Self::Cache,
|
||||||
) -> Self::Approximation {
|
) -> Self::Approximation {
|
||||||
let (curve, surface, range) = self;
|
let (curve, surface, global_curve, range) = self;
|
||||||
|
|
||||||
let global_curve = curve.global_form().clone();
|
|
||||||
let global_curve_approx = match cache.get(global_curve.clone(), range) {
|
let global_curve_approx = match cache.get(global_curve.clone(), range) {
|
||||||
Some(approx) => approx,
|
Some(approx) => approx,
|
||||||
None => {
|
None => {
|
||||||
@ -219,6 +218,7 @@ mod tests {
|
|||||||
builder::{CurveBuilder, SurfaceBuilder},
|
builder::{CurveBuilder, SurfaceBuilder},
|
||||||
geometry::path::GlobalPath,
|
geometry::path::GlobalPath,
|
||||||
insert::Insert,
|
insert::Insert,
|
||||||
|
objects::GlobalCurve,
|
||||||
partial::{PartialCurve, PartialObject, PartialSurface},
|
partial::{PartialCurve, PartialObject, PartialSurface},
|
||||||
services::Services,
|
services::Services,
|
||||||
};
|
};
|
||||||
@ -235,9 +235,10 @@ mod tests {
|
|||||||
let curve = curve
|
let curve = curve
|
||||||
.build(&mut services.objects)
|
.build(&mut services.objects)
|
||||||
.insert(&mut services.objects);
|
.insert(&mut services.objects);
|
||||||
|
let global_curve = GlobalCurve.insert(&mut services.objects);
|
||||||
let range = RangeOnPath::from([[0.], [1.]]);
|
let range = RangeOnPath::from([[0.], [1.]]);
|
||||||
|
|
||||||
let approx = (&curve, surface.deref(), range).approx(1.);
|
let approx = (&curve, surface.deref(), global_curve, range).approx(1.);
|
||||||
|
|
||||||
assert_eq!(approx, CurveApprox::empty());
|
assert_eq!(approx, CurveApprox::empty());
|
||||||
}
|
}
|
||||||
@ -257,9 +258,10 @@ mod tests {
|
|||||||
let curve = curve
|
let curve = curve
|
||||||
.build(&mut services.objects)
|
.build(&mut services.objects)
|
||||||
.insert(&mut services.objects);
|
.insert(&mut services.objects);
|
||||||
|
let global_curve = GlobalCurve.insert(&mut services.objects);
|
||||||
let range = RangeOnPath::from([[0.], [1.]]);
|
let range = RangeOnPath::from([[0.], [1.]]);
|
||||||
|
|
||||||
let approx = (&curve, surface.deref(), range).approx(1.);
|
let approx = (&curve, surface.deref(), global_curve, range).approx(1.);
|
||||||
|
|
||||||
assert_eq!(approx, CurveApprox::empty());
|
assert_eq!(approx, CurveApprox::empty());
|
||||||
}
|
}
|
||||||
@ -277,11 +279,13 @@ mod tests {
|
|||||||
let curve = curve
|
let curve = curve
|
||||||
.build(&mut services.objects)
|
.build(&mut services.objects)
|
||||||
.insert(&mut services.objects);
|
.insert(&mut services.objects);
|
||||||
|
let global_curve = GlobalCurve.insert(&mut services.objects);
|
||||||
|
|
||||||
let range = RangeOnPath::from([[0.], [TAU]]);
|
let range = RangeOnPath::from([[0.], [TAU]]);
|
||||||
let tolerance = 1.;
|
let tolerance = 1.;
|
||||||
|
|
||||||
let approx = (&curve, surface.deref(), range).approx(tolerance);
|
let approx =
|
||||||
|
(&curve, surface.deref(), global_curve, range).approx(tolerance);
|
||||||
|
|
||||||
let expected_approx = (path, range)
|
let expected_approx = (path, range)
|
||||||
.approx(tolerance)
|
.approx(tolerance)
|
||||||
@ -307,10 +311,12 @@ mod tests {
|
|||||||
let curve = curve
|
let curve = curve
|
||||||
.build(&mut services.objects)
|
.build(&mut services.objects)
|
||||||
.insert(&mut services.objects);
|
.insert(&mut services.objects);
|
||||||
|
let global_curve = GlobalCurve.insert(&mut services.objects);
|
||||||
|
|
||||||
let range = RangeOnPath::from([[0.], [TAU]]);
|
let range = RangeOnPath::from([[0.], [TAU]]);
|
||||||
let tolerance = 1.;
|
let tolerance = 1.;
|
||||||
let approx = (&curve, surface.deref(), range).approx(tolerance);
|
let approx =
|
||||||
|
(&curve, surface.deref(), global_curve, range).approx(tolerance);
|
||||||
|
|
||||||
let expected_approx = (curve.path(), range)
|
let expected_approx = (curve.path(), range)
|
||||||
.approx(tolerance)
|
.approx(tolerance)
|
||||||
|
@ -35,7 +35,12 @@ impl Approx for (&Handle<HalfEdge>, &Surface) {
|
|||||||
half_edge.start_vertex().global_form().position(),
|
half_edge.start_vertex().global_form().position(),
|
||||||
)
|
)
|
||||||
.with_source((half_edge.clone(), half_edge.boundary()[0]));
|
.with_source((half_edge.clone(), half_edge.boundary()[0]));
|
||||||
let curve_approx = (half_edge.curve(), surface, range)
|
let curve_approx = (
|
||||||
|
half_edge.curve(),
|
||||||
|
surface,
|
||||||
|
half_edge.global_form().curve().clone(),
|
||||||
|
range,
|
||||||
|
)
|
||||||
.approx_with_cache(tolerance, cache);
|
.approx_with_cache(tolerance, cache);
|
||||||
|
|
||||||
HalfEdgeApprox {
|
HalfEdgeApprox {
|
||||||
|
@ -3,7 +3,7 @@ use fj_math::{Line, Plane, Point, Scalar};
|
|||||||
use crate::{
|
use crate::{
|
||||||
geometry::path::{GlobalPath, SurfacePath},
|
geometry::path::{GlobalPath, SurfacePath},
|
||||||
insert::Insert,
|
insert::Insert,
|
||||||
objects::{Curve, GlobalCurve, Objects, Surface},
|
objects::{Curve, Objects, Surface},
|
||||||
services::Service,
|
services::Service,
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
};
|
};
|
||||||
@ -55,9 +55,7 @@ impl SurfaceSurfaceIntersection {
|
|||||||
|
|
||||||
let curves = planes.map(|plane| {
|
let curves = planes.map(|plane| {
|
||||||
let path = SurfacePath::Line(plane.project_line(&line));
|
let path = SurfacePath::Line(plane.project_line(&line));
|
||||||
let global_form = GlobalCurve.insert(objects);
|
Curve::new(path).insert(objects)
|
||||||
|
|
||||||
Curve::new(path, global_form).insert(objects)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Some(Self {
|
Some(Self {
|
||||||
|
@ -134,11 +134,7 @@ impl Sweep for (Handle<HalfEdge>, &Surface, Color) {
|
|||||||
[edge_bottom.write(), edge_up.write(), edge_down.write()]
|
[edge_bottom.write(), edge_up.write(), edge_down.write()]
|
||||||
.zip_ext(global_edges)
|
.zip_ext(global_edges)
|
||||||
.map(|(mut half_edge, global_edge)| {
|
.map(|(mut half_edge, global_edge)| {
|
||||||
let global_edge = Partial::from(global_edge);
|
half_edge.global_form = Partial::from(global_edge);
|
||||||
|
|
||||||
half_edge.curve.write().global_form =
|
|
||||||
global_edge.read().curve.clone();
|
|
||||||
half_edge.global_form = global_edge;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// And we're done creating the face! All that's left to do is build our
|
// And we're done creating the face! All that's left to do is build our
|
||||||
|
@ -10,20 +10,15 @@ use super::{TransformCache, TransformObject};
|
|||||||
impl TransformObject for Curve {
|
impl TransformObject for Curve {
|
||||||
fn transform_with_cache(
|
fn transform_with_cache(
|
||||||
self,
|
self,
|
||||||
transform: &Transform,
|
_: &Transform,
|
||||||
objects: &mut Service<Objects>,
|
_: &mut Service<Objects>,
|
||||||
cache: &mut TransformCache,
|
_: &mut TransformCache,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// Don't need to transform path, as that's defined in surface
|
// Don't need to transform path, as that's defined in surface
|
||||||
// coordinates, and thus transforming `surface` takes care of it.
|
// coordinates, and thus transforming `surface` takes care of it.
|
||||||
let path = self.path();
|
let path = self.path();
|
||||||
|
|
||||||
let global_form = self
|
Self::new(path)
|
||||||
.global_form()
|
|
||||||
.clone()
|
|
||||||
.transform_with_cache(transform, objects, cache);
|
|
||||||
|
|
||||||
Self::new(path, global_form)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,6 @@ impl HalfEdgeBuilder for PartialHalfEdge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn infer_global_form(&mut self) -> Partial<GlobalEdge> {
|
fn infer_global_form(&mut self) -> Partial<GlobalEdge> {
|
||||||
self.global_form.write().curve = self.curve.read().global_form.clone();
|
|
||||||
self.global_form.write().vertices = self
|
self.global_form.write().vertices = self
|
||||||
.vertices
|
.vertices
|
||||||
.each_ref_ext()
|
.each_ref_ext()
|
||||||
@ -224,8 +223,7 @@ impl HalfEdgeBuilder for PartialHalfEdge {
|
|||||||
other: &Partial<HalfEdge>,
|
other: &Partial<HalfEdge>,
|
||||||
surface: &SurfaceGeometry,
|
surface: &SurfaceGeometry,
|
||||||
) {
|
) {
|
||||||
let global_curve = other.read().curve.read().global_form.clone();
|
let global_curve = other.read().global_form.read().curve.clone();
|
||||||
self.curve.write().global_form = global_curve.clone();
|
|
||||||
self.global_form.write().curve = global_curve;
|
self.global_form.write().curve = global_curve;
|
||||||
|
|
||||||
self.curve.write().path =
|
self.curve.write().path =
|
||||||
|
@ -1,36 +1,21 @@
|
|||||||
use crate::{
|
use crate::geometry::path::SurfacePath;
|
||||||
geometry::path::SurfacePath,
|
|
||||||
storage::{Handle, HandleWrapper},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A curve, defined in local surface coordinates
|
/// A curve, defined in local surface coordinates
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||||
pub struct Curve {
|
pub struct Curve {
|
||||||
path: SurfacePath,
|
path: SurfacePath,
|
||||||
global_form: HandleWrapper<GlobalCurve>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Curve {
|
impl Curve {
|
||||||
/// Construct a new instance of `Curve`
|
/// Construct a new instance of `Curve`
|
||||||
pub fn new(
|
pub fn new(path: SurfacePath) -> Self {
|
||||||
path: SurfacePath,
|
Self { path }
|
||||||
global_form: impl Into<HandleWrapper<GlobalCurve>>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
path,
|
|
||||||
global_form: global_form.into(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the path that defines the curve
|
/// Access the path that defines the curve
|
||||||
pub fn path(&self) -> SurfacePath {
|
pub fn path(&self) -> SurfacePath {
|
||||||
self.path
|
self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the global form of the curve
|
|
||||||
pub fn global_form(&self) -> &Handle<GlobalCurve> {
|
|
||||||
&self.global_form
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A curve, defined in global (3D) coordinates
|
/// A curve, defined in global (3D) coordinates
|
||||||
|
@ -64,7 +64,7 @@ impl fmt::Display for HalfEdge {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let [a, b] = self.boundary();
|
let [a, b] = self.boundary();
|
||||||
write!(f, "edge from {a:?} to {b:?}")?;
|
write!(f, "edge from {a:?} to {b:?}")?;
|
||||||
write!(f, " on {:?}", self.curve().global_form())?;
|
write!(f, " on {:?}", self.global_form().curve())?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,6 @@ use super::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// The available object stores
|
/// The available object stores
|
||||||
///
|
|
||||||
/// # Implementation Note
|
|
||||||
///
|
|
||||||
/// The intention is to eventually manage all objects in here. Making this
|
|
||||||
/// happen is simply a case of putting in the required work. See [#1021].
|
|
||||||
///
|
|
||||||
/// [#1021]: https://github.com/hannobraun/Fornjot/issues/1021
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Objects {
|
pub struct Objects {
|
||||||
/// Store for [`Curve`]s
|
/// Store for [`Curve`]s
|
||||||
@ -80,7 +73,7 @@ impl Surfaces {
|
|||||||
self.store.reserve()
|
self.store.reserve()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a [`Surface`] into the store
|
/// Insert an object into the store
|
||||||
pub fn insert(&mut self, handle: Handle<Surface>, surface: Surface) {
|
pub fn insert(&mut self, handle: Handle<Surface>, surface: Surface) {
|
||||||
self.store.insert(handle, surface);
|
self.store.insert(handle, surface);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use fj_math::Scalar;
|
|||||||
use crate::{
|
use crate::{
|
||||||
geometry::path::SurfacePath,
|
geometry::path::SurfacePath,
|
||||||
objects::{Curve, GlobalCurve, Objects},
|
objects::{Curve, GlobalCurve, Objects},
|
||||||
partial::{FullToPartialCache, Partial, PartialObject},
|
partial::{FullToPartialCache, PartialObject},
|
||||||
services::Service,
|
services::Service,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -12,22 +12,18 @@ use crate::{
|
|||||||
pub struct PartialCurve {
|
pub struct PartialCurve {
|
||||||
/// The path that defines the curve
|
/// The path that defines the curve
|
||||||
pub path: Option<MaybeSurfacePath>,
|
pub path: Option<MaybeSurfacePath>,
|
||||||
|
|
||||||
/// The global form of the curve
|
|
||||||
pub global_form: Partial<GlobalCurve>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialObject for PartialCurve {
|
impl PartialObject for PartialCurve {
|
||||||
type Full = Curve;
|
type Full = Curve;
|
||||||
|
|
||||||
fn from_full(curve: &Self::Full, cache: &mut FullToPartialCache) -> Self {
|
fn from_full(curve: &Self::Full, _: &mut FullToPartialCache) -> Self {
|
||||||
Self {
|
Self {
|
||||||
path: Some(curve.path().into()),
|
path: Some(curve.path().into()),
|
||||||
global_form: Partial::from_full(curve.global_form().clone(), cache),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(self, objects: &mut Service<Objects>) -> Self::Full {
|
fn build(self, _: &mut Service<Objects>) -> Self::Full {
|
||||||
let path = match self.path.expect("Need path to build curve") {
|
let path = match self.path.expect("Need path to build curve") {
|
||||||
MaybeSurfacePath::Defined(path) => path,
|
MaybeSurfacePath::Defined(path) => path,
|
||||||
undefined => {
|
undefined => {
|
||||||
@ -36,9 +32,8 @@ impl PartialObject for PartialCurve {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let global_form = self.global_form.build(objects);
|
|
||||||
|
|
||||||
Curve::new(path, global_form)
|
Curve::new(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,6 @@ impl Default for PartialHalfEdge {
|
|||||||
(None, surface_form)
|
(None, surface_form)
|
||||||
});
|
});
|
||||||
|
|
||||||
let global_curve = curve.read().global_form.clone();
|
|
||||||
let global_vertices = vertices.each_ref_ext().map(
|
let global_vertices = vertices.each_ref_ext().map(
|
||||||
|vertex: &(Option<Point<1>>, Partial<SurfaceVertex>)| {
|
|vertex: &(Option<Point<1>>, Partial<SurfaceVertex>)| {
|
||||||
let surface_vertex = vertex.1.clone();
|
let surface_vertex = vertex.1.clone();
|
||||||
@ -84,8 +83,8 @@ impl Default for PartialHalfEdge {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let global_form = Partial::from_partial(PartialGlobalEdge {
|
let global_form = Partial::from_partial(PartialGlobalEdge {
|
||||||
curve: global_curve,
|
|
||||||
vertices: global_vertices,
|
vertices: global_vertices,
|
||||||
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
@ -13,7 +13,6 @@ impl Validate for HalfEdge {
|
|||||||
config: &ValidationConfig,
|
config: &ValidationConfig,
|
||||||
errors: &mut Vec<ValidationError>,
|
errors: &mut Vec<ValidationError>,
|
||||||
) {
|
) {
|
||||||
HalfEdgeValidationError::check_global_curve_identity(self, errors);
|
|
||||||
HalfEdgeValidationError::check_global_vertex_identity(self, errors);
|
HalfEdgeValidationError::check_global_vertex_identity(self, errors);
|
||||||
HalfEdgeValidationError::check_vertex_coincidence(self, config, errors);
|
HalfEdgeValidationError::check_vertex_coincidence(self, config, errors);
|
||||||
}
|
}
|
||||||
@ -107,26 +106,6 @@ pub enum HalfEdgeValidationError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl HalfEdgeValidationError {
|
impl HalfEdgeValidationError {
|
||||||
fn check_global_curve_identity(
|
|
||||||
half_edge: &HalfEdge,
|
|
||||||
errors: &mut Vec<ValidationError>,
|
|
||||||
) {
|
|
||||||
let global_curve_from_curve = half_edge.curve().global_form();
|
|
||||||
let global_curve_from_global_form = half_edge.global_form().curve();
|
|
||||||
|
|
||||||
if global_curve_from_curve.id() != global_curve_from_global_form.id() {
|
|
||||||
errors.push(
|
|
||||||
Box::new(Self::GlobalCurveMismatch {
|
|
||||||
global_curve_from_curve: global_curve_from_curve.clone(),
|
|
||||||
global_curve_from_global_form:
|
|
||||||
global_curve_from_global_form.clone(),
|
|
||||||
half_edge: half_edge.clone(),
|
|
||||||
})
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_global_vertex_identity(
|
fn check_global_vertex_identity(
|
||||||
half_edge: &HalfEdge,
|
half_edge: &HalfEdge,
|
||||||
errors: &mut Vec<ValidationError>,
|
errors: &mut Vec<ValidationError>,
|
||||||
@ -185,47 +164,12 @@ mod tests {
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
builder::HalfEdgeBuilder,
|
builder::HalfEdgeBuilder,
|
||||||
insert::Insert,
|
objects::HalfEdge,
|
||||||
objects::{GlobalCurve, HalfEdge},
|
|
||||||
partial::{Partial, PartialHalfEdge, PartialObject},
|
partial::{Partial, PartialHalfEdge, PartialObject},
|
||||||
services::Services,
|
services::Services,
|
||||||
validate::Validate,
|
validate::Validate,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn half_edge_global_curve_mismatch() -> anyhow::Result<()> {
|
|
||||||
let mut services = Services::new();
|
|
||||||
|
|
||||||
let valid = {
|
|
||||||
let surface = services.objects.surfaces.xy_plane();
|
|
||||||
|
|
||||||
let mut half_edge = PartialHalfEdge::default();
|
|
||||||
half_edge.update_as_line_segment_from_points([[0., 0.], [1., 0.]]);
|
|
||||||
half_edge.infer_vertex_positions_if_necessary(&surface.geometry());
|
|
||||||
|
|
||||||
half_edge.build(&mut services.objects)
|
|
||||||
};
|
|
||||||
let invalid = {
|
|
||||||
let global_form = {
|
|
||||||
let mut global_edge =
|
|
||||||
Partial::from(valid.global_form().clone());
|
|
||||||
global_edge.write().curve =
|
|
||||||
Partial::from(GlobalCurve.insert(&mut services.objects));
|
|
||||||
global_edge.build(&mut services.objects)
|
|
||||||
};
|
|
||||||
let vertices = valid
|
|
||||||
.boundary()
|
|
||||||
.zip_ext(valid.surface_vertices().map(Clone::clone));
|
|
||||||
|
|
||||||
HalfEdge::new(valid.curve().clone(), vertices, global_form)
|
|
||||||
};
|
|
||||||
|
|
||||||
valid.validate_and_return_first_error()?;
|
|
||||||
assert!(invalid.validate_and_return_first_error().is_err());
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn half_edge_global_vertex_mismatch() -> anyhow::Result<()> {
|
fn half_edge_global_vertex_mismatch() -> anyhow::Result<()> {
|
||||||
let mut services = Services::new();
|
let mut services = Services::new();
|
||||||
|
Loading…
Reference in New Issue
Block a user