mirror of https://github.com/hannobraun/Fornjot
Merge pull request #1340 from hannobraun/surface
Clean up surface-related code; prepare for deeper integration into partial object API
This commit is contained in:
commit
35a02544ad
|
@ -12,8 +12,8 @@
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
geometry::path::{GlobalPath, SurfacePath},
|
||||||
objects::{Curve, GlobalCurve},
|
objects::{Curve, GlobalCurve},
|
||||||
path::{GlobalPath, SurfacePath},
|
|
||||||
storage::{Handle, ObjectId},
|
storage::{Handle, ObjectId},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ fn approx_global_curve(
|
||||||
// This will probably all be unified eventually, as `SurfacePath` and
|
// This will probably all be unified eventually, as `SurfacePath` and
|
||||||
// `GlobalPath` grow APIs that are better suited to implementing this code
|
// `GlobalPath` grow APIs that are better suited to implementing this code
|
||||||
// in a more abstract way.
|
// in a more abstract way.
|
||||||
let points = match (curve.path(), curve.surface().u()) {
|
let points = match (curve.path(), curve.surface().geometry().u) {
|
||||||
(SurfacePath::Circle(_), GlobalPath::Circle(_)) => {
|
(SurfacePath::Circle(_), GlobalPath::Circle(_)) => {
|
||||||
todo!(
|
todo!(
|
||||||
"Approximating a circle on a curved surface not supported yet."
|
"Approximating a circle on a curved surface not supported yet."
|
||||||
|
@ -90,6 +90,7 @@ fn approx_global_curve(
|
||||||
|
|
||||||
let point_global = curve
|
let point_global = curve
|
||||||
.surface()
|
.surface()
|
||||||
|
.geometry()
|
||||||
.point_from_surface_coords(point_surface);
|
.point_from_surface_coords(point_surface);
|
||||||
(point_curve, point_global)
|
(point_curve, point_global)
|
||||||
})
|
})
|
||||||
|
@ -101,15 +102,17 @@ fn approx_global_curve(
|
||||||
[curve.path().point_from_path_coords(point_curve).u]
|
[curve.path().point_from_path_coords(point_curve).u]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let approx_u = (curve.surface().u(), range_u)
|
let approx_u = (curve.surface().geometry().u, range_u)
|
||||||
.approx_with_cache(tolerance, &mut ());
|
.approx_with_cache(tolerance, &mut ());
|
||||||
|
|
||||||
let mut points = Vec::new();
|
let mut points = Vec::new();
|
||||||
for (u, _) in approx_u {
|
for (u, _) in approx_u {
|
||||||
let t = (u.t - line.origin().u) / line.direction().u;
|
let t = (u.t - line.origin().u) / line.direction().u;
|
||||||
let point_surface = curve.path().point_from_path_coords([t]);
|
let point_surface = curve.path().point_from_path_coords([t]);
|
||||||
let point_global =
|
let point_global = curve
|
||||||
curve.surface().point_from_surface_coords(point_surface);
|
.surface()
|
||||||
|
.geometry()
|
||||||
|
.point_from_surface_coords(point_surface);
|
||||||
points.push((u, point_global));
|
points.push((u, point_global));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,11 +200,11 @@ mod tests {
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
algorithms::approx::{path::RangeOnPath, Approx, ApproxPoint},
|
algorithms::approx::{path::RangeOnPath, Approx, ApproxPoint},
|
||||||
builder::CurveBuilder,
|
builder::{CurveBuilder, SurfaceBuilder},
|
||||||
|
geometry::path::GlobalPath,
|
||||||
insert::Insert,
|
insert::Insert,
|
||||||
objects::{Objects, Surface},
|
objects::Objects,
|
||||||
partial::PartialCurve,
|
partial::{PartialCurve, PartialSurface},
|
||||||
path::GlobalPath,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::CurveApprox;
|
use super::CurveApprox;
|
||||||
|
@ -210,9 +213,10 @@ mod tests {
|
||||||
fn approx_line_on_flat_surface() -> anyhow::Result<()> {
|
fn approx_line_on_flat_surface() -> anyhow::Result<()> {
|
||||||
let objects = Objects::new();
|
let objects = Objects::new();
|
||||||
|
|
||||||
let surface = objects
|
let surface =
|
||||||
.surfaces
|
PartialSurface::from_axes(GlobalPath::x_axis(), [0., 0., 1.])
|
||||||
.insert(Surface::new(GlobalPath::x_axis(), [0., 0., 1.]))?;
|
.build(&objects)?
|
||||||
|
.insert(&objects)?;
|
||||||
let mut curve = PartialCurve {
|
let mut curve = PartialCurve {
|
||||||
surface: Some(surface),
|
surface: Some(surface),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -232,10 +236,12 @@ mod tests {
|
||||||
{
|
{
|
||||||
let objects = Objects::new();
|
let objects = Objects::new();
|
||||||
|
|
||||||
let surface = objects.surfaces.insert(Surface::new(
|
let surface = PartialSurface::from_axes(
|
||||||
GlobalPath::circle_from_radius(1.),
|
GlobalPath::circle_from_radius(1.),
|
||||||
[0., 0., 1.],
|
[0., 0., 1.],
|
||||||
))?;
|
)
|
||||||
|
.build(&objects)?
|
||||||
|
.insert(&objects)?;
|
||||||
let mut curve = PartialCurve {
|
let mut curve = PartialCurve {
|
||||||
surface: Some(surface),
|
surface: Some(surface),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -255,8 +261,9 @@ mod tests {
|
||||||
let objects = Objects::new();
|
let objects = Objects::new();
|
||||||
|
|
||||||
let path = GlobalPath::circle_from_radius(1.);
|
let path = GlobalPath::circle_from_radius(1.);
|
||||||
let surface =
|
let surface = PartialSurface::from_axes(path, [0., 0., 1.])
|
||||||
objects.surfaces.insert(Surface::new(path, [0., 0., 1.]))?;
|
.build(&objects)?
|
||||||
|
.insert(&objects)?;
|
||||||
let mut curve = PartialCurve {
|
let mut curve = PartialCurve {
|
||||||
surface: Some(surface.clone()),
|
surface: Some(surface.clone()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -276,7 +283,7 @@ mod tests {
|
||||||
let point_surface =
|
let point_surface =
|
||||||
curve.path().point_from_path_coords(point_local);
|
curve.path().point_from_path_coords(point_local);
|
||||||
let point_global =
|
let point_global =
|
||||||
surface.point_from_surface_coords(point_surface);
|
surface.geometry().point_from_surface_coords(point_surface);
|
||||||
ApproxPoint::new(point_surface, point_global)
|
ApproxPoint::new(point_surface, point_global)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -288,9 +295,10 @@ mod tests {
|
||||||
fn approx_circle_on_flat_surface() -> anyhow::Result<()> {
|
fn approx_circle_on_flat_surface() -> anyhow::Result<()> {
|
||||||
let objects = Objects::new();
|
let objects = Objects::new();
|
||||||
|
|
||||||
let surface = objects
|
let surface =
|
||||||
.surfaces
|
PartialSurface::from_axes(GlobalPath::x_axis(), [0., 0., 1.])
|
||||||
.insert(Surface::new(GlobalPath::x_axis(), [0., 0., 1.]))?;
|
.build(&objects)?
|
||||||
|
.insert(&objects)?;
|
||||||
let mut curve = PartialCurve {
|
let mut curve = PartialCurve {
|
||||||
surface: Some(surface),
|
surface: Some(surface),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -306,8 +314,10 @@ mod tests {
|
||||||
.approx(tolerance)
|
.approx(tolerance)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, point_surface)| {
|
.map(|(_, point_surface)| {
|
||||||
let point_global =
|
let point_global = curve
|
||||||
curve.surface().point_from_surface_coords(point_surface);
|
.surface()
|
||||||
|
.geometry()
|
||||||
|
.point_from_surface_coords(point_surface);
|
||||||
ApproxPoint::new(point_surface, point_global)
|
ApproxPoint::new(point_surface, point_global)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
|
@ -32,7 +32,7 @@ use std::iter;
|
||||||
|
|
||||||
use fj_math::{Circle, Point, Scalar, Sign};
|
use fj_math::{Circle, Point, Scalar, Sign};
|
||||||
|
|
||||||
use crate::path::{GlobalPath, SurfacePath};
|
use crate::geometry::path::{GlobalPath, SurfacePath};
|
||||||
|
|
||||||
use super::{Approx, Tolerance};
|
use super::{Approx, Tolerance};
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use fj_math::{Point, Segment};
|
use fj_math::{Point, Segment};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
geometry::path::SurfacePath,
|
||||||
objects::{Curve, HalfEdge},
|
objects::{Curve, HalfEdge},
|
||||||
path::SurfacePath,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::LineSegmentIntersection;
|
use super::LineSegmentIntersection;
|
||||||
|
|
|
@ -4,8 +4,8 @@ use fj_math::Segment;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
algorithms::intersect::{HorizontalRayToTheRight, Intersect},
|
algorithms::intersect::{HorizontalRayToTheRight, Intersect},
|
||||||
|
geometry::path::SurfacePath,
|
||||||
objects::HalfEdge,
|
objects::HalfEdge,
|
||||||
path::SurfacePath,
|
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ use fj_math::{Plane, Point, Scalar};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
algorithms::intersect::face_point::FacePointIntersection,
|
algorithms::intersect::face_point::FacePointIntersection,
|
||||||
|
geometry::path::GlobalPath,
|
||||||
objects::{Face, HalfEdge, Vertex},
|
objects::{Face, HalfEdge, Vertex},
|
||||||
path::GlobalPath,
|
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,14 +17,14 @@ impl Intersect for (&HorizontalRayToTheRight<3>, &Handle<Face>) {
|
||||||
fn intersect(self) -> Option<Self::Intersection> {
|
fn intersect(self) -> Option<Self::Intersection> {
|
||||||
let (ray, face) = self;
|
let (ray, face) = self;
|
||||||
|
|
||||||
let plane = match face.surface().u() {
|
let plane = match face.surface().geometry().u {
|
||||||
GlobalPath::Circle(_) => todo!(
|
GlobalPath::Circle(_) => todo!(
|
||||||
"Casting a ray against a swept circle is not supported yet"
|
"Casting a ray against a swept circle is not supported yet"
|
||||||
),
|
),
|
||||||
GlobalPath::Line(line) => Plane::from_parametric(
|
GlobalPath::Line(line) => Plane::from_parametric(
|
||||||
line.origin(),
|
line.origin(),
|
||||||
line.direction(),
|
line.direction(),
|
||||||
face.surface().v(),
|
face.surface().geometry().v,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@ use fj_interop::ext::ArrayExt;
|
||||||
use fj_math::{Line, Plane, Point, Scalar};
|
use fj_math::{Line, Plane, Point, Scalar};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
geometry::path::{GlobalPath, SurfacePath},
|
||||||
objects::{Curve, GlobalCurve, Objects, Surface},
|
objects::{Curve, GlobalCurve, Objects, Surface},
|
||||||
path::{GlobalPath, SurfacePath},
|
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
@ -74,12 +74,12 @@ impl SurfaceSurfaceIntersection {
|
||||||
|
|
||||||
fn plane_from_surface(surface: &Surface) -> Plane {
|
fn plane_from_surface(surface: &Surface) -> Plane {
|
||||||
let (line, path) = {
|
let (line, path) = {
|
||||||
let line = match surface.u() {
|
let line = match surface.geometry().u {
|
||||||
GlobalPath::Line(line) => line,
|
GlobalPath::Line(line) => line,
|
||||||
_ => todo!("Only plane-plane intersection is currently supported."),
|
_ => todo!("Only plane-plane intersection is currently supported."),
|
||||||
};
|
};
|
||||||
|
|
||||||
(line, surface.v())
|
(line, surface.geometry().v)
|
||||||
};
|
};
|
||||||
|
|
||||||
Plane::from_parametric(line.origin(), line.direction(), path)
|
Plane::from_parametric(line.origin(), line.direction(), path)
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
use fj_math::{Circle, Line, Vector};
|
use fj_math::{Circle, Line, Vector};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
builder::SurfaceBuilder,
|
||||||
|
geometry::path::{GlobalPath, SurfacePath},
|
||||||
|
insert::Insert,
|
||||||
objects::{Curve, Objects, Surface},
|
objects::{Curve, Objects, Surface},
|
||||||
path::{GlobalPath, SurfacePath},
|
partial::PartialSurface,
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
@ -18,7 +21,7 @@ impl Sweep for Handle<Curve> {
|
||||||
_: &mut SweepCache,
|
_: &mut SweepCache,
|
||||||
objects: &Objects,
|
objects: &Objects,
|
||||||
) -> Result<Self::Swept, ValidationError> {
|
) -> Result<Self::Swept, ValidationError> {
|
||||||
match self.surface().u() {
|
match self.surface().geometry().u {
|
||||||
GlobalPath::Circle(_) => {
|
GlobalPath::Circle(_) => {
|
||||||
// Sweeping a `Curve` creates a `Surface`. The u-axis of that
|
// Sweeping a `Curve` creates a `Surface`. The u-axis of that
|
||||||
// `Surface` is a `GlobalPath`, which we are computing below.
|
// `Surface` is a `GlobalPath`, which we are computing below.
|
||||||
|
@ -44,20 +47,32 @@ impl Sweep for Handle<Curve> {
|
||||||
|
|
||||||
let u = match self.path() {
|
let u = match self.path() {
|
||||||
SurfacePath::Circle(circle) => {
|
SurfacePath::Circle(circle) => {
|
||||||
let center =
|
let center = self
|
||||||
self.surface().point_from_surface_coords(circle.center());
|
.surface()
|
||||||
let a = self.surface().vector_from_surface_coords(circle.a());
|
.geometry()
|
||||||
let b = self.surface().vector_from_surface_coords(circle.b());
|
.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 circle = Circle::new(center, a, b);
|
let circle = Circle::new(center, a, b);
|
||||||
|
|
||||||
GlobalPath::Circle(circle)
|
GlobalPath::Circle(circle)
|
||||||
}
|
}
|
||||||
SurfacePath::Line(line) => {
|
SurfacePath::Line(line) => {
|
||||||
let origin =
|
let origin = self
|
||||||
self.surface().point_from_surface_coords(line.origin());
|
.surface()
|
||||||
let direction =
|
.geometry()
|
||||||
self.surface().vector_from_surface_coords(line.direction());
|
.point_from_surface_coords(line.origin());
|
||||||
|
let direction = self
|
||||||
|
.surface()
|
||||||
|
.geometry()
|
||||||
|
.vector_from_surface_coords(line.direction());
|
||||||
|
|
||||||
let line = Line::from_origin_and_direction(origin, direction);
|
let line = Line::from_origin_and_direction(origin, direction);
|
||||||
|
|
||||||
|
@ -65,6 +80,9 @@ impl Sweep for Handle<Curve> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(objects.surfaces.insert(Surface::new(u, path))?)
|
let surface = PartialSurface::from_axes(u, path)
|
||||||
|
.build(objects)?
|
||||||
|
.insert(objects)?;
|
||||||
|
Ok(surface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@ use iter_fixed::IntoIteratorFixed;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
algorithms::{reverse::Reverse, transform::TransformObject},
|
algorithms::{reverse::Reverse, transform::TransformObject},
|
||||||
|
geometry::path::SurfacePath,
|
||||||
insert::Insert,
|
insert::Insert,
|
||||||
objects::{
|
objects::{
|
||||||
Curve, Cycle, Face, GlobalEdge, HalfEdge, Objects, SurfaceVertex,
|
Curve, Cycle, Face, GlobalEdge, HalfEdge, Objects, SurfaceVertex,
|
||||||
Vertex,
|
Vertex,
|
||||||
},
|
},
|
||||||
partial::HasPartial,
|
partial::HasPartial,
|
||||||
path::SurfacePath,
|
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,8 +2,8 @@ use fj_math::{Scalar, Vector};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
algorithms::{reverse::Reverse, transform::TransformObject},
|
algorithms::{reverse::Reverse, transform::TransformObject},
|
||||||
|
geometry::path::GlobalPath,
|
||||||
objects::{Face, Objects, Shell},
|
objects::{Face, Objects, Shell},
|
||||||
path::GlobalPath,
|
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
@ -24,14 +24,14 @@ impl Sweep for Handle<Face> {
|
||||||
let mut faces = Vec::new();
|
let mut faces = Vec::new();
|
||||||
|
|
||||||
let is_negative_sweep = {
|
let is_negative_sweep = {
|
||||||
let u = match self.surface().u() {
|
let u = match self.surface().geometry().u {
|
||||||
GlobalPath::Circle(_) => todo!(
|
GlobalPath::Circle(_) => todo!(
|
||||||
"Sweeping from faces defined in round surfaces is not \
|
"Sweeping from faces defined in round surfaces is not \
|
||||||
supported"
|
supported"
|
||||||
),
|
),
|
||||||
GlobalPath::Line(line) => line.direction(),
|
GlobalPath::Line(line) => line.direction(),
|
||||||
};
|
};
|
||||||
let v = self.surface().v();
|
let v = self.surface().geometry().v;
|
||||||
|
|
||||||
let normal = u.cross(&v);
|
let normal = u.cross(&v);
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ use fj_math::{Line, Point, Scalar, Vector};
|
||||||
use try_insert_ext::EntryInsertExt;
|
use try_insert_ext::EntryInsertExt;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
geometry::path::SurfacePath,
|
||||||
objects::{
|
objects::{
|
||||||
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
||||||
Surface, SurfaceVertex, Vertex,
|
Surface, SurfaceVertex, Vertex,
|
||||||
},
|
},
|
||||||
path::SurfacePath,
|
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
@ -56,7 +56,7 @@ impl Sweep for (Handle<Vertex>, Handle<Surface>) {
|
||||||
// not, we have no way of knowing the surface coordinates of the input
|
// not, we have no way of knowing the surface coordinates of the input
|
||||||
// `Vertex` on the `Surface`, and we're going to need to do that further
|
// `Vertex` on the `Surface`, and we're going to need to do that further
|
||||||
// down. There's no way to check for that, unfortunately.
|
// down. There's no way to check for that, unfortunately.
|
||||||
assert_eq!(path, surface.v());
|
assert_eq!(path, surface.geometry().v);
|
||||||
|
|
||||||
// With that out of the way, let's start by creating the `GlobalEdge`,
|
// With that out of the way, let's start by creating the `GlobalEdge`,
|
||||||
// as that is the most straight-forward part of this operations, and
|
// as that is the most straight-forward part of this operations, and
|
||||||
|
|
|
@ -1,22 +1,25 @@
|
||||||
use fj_math::Transform;
|
use fj_math::Transform;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::{Objects, Surface},
|
geometry::surface::SurfaceGeometry, objects::Objects,
|
||||||
storage::Handle,
|
partial::PartialSurface, validate::ValidationError,
|
||||||
validate::ValidationError,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::TransformObject;
|
use super::TransformObject;
|
||||||
|
|
||||||
impl TransformObject for Handle<Surface> {
|
impl TransformObject for PartialSurface {
|
||||||
fn transform(
|
fn transform(
|
||||||
self,
|
self,
|
||||||
transform: &Transform,
|
transform: &Transform,
|
||||||
objects: &Objects,
|
_: &Objects,
|
||||||
) -> Result<Self, ValidationError> {
|
) -> Result<Self, ValidationError> {
|
||||||
Ok(objects.surfaces.insert(Surface::new(
|
let geometry = self.geometry.map(|geometry| {
|
||||||
self.u().transform(transform),
|
let u = geometry.u.transform(transform);
|
||||||
transform.transform_vector(&self.v()),
|
let v = transform.transform_vector(&geometry.v);
|
||||||
))?)
|
|
||||||
|
SurfaceGeometry { u, v }
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(Self { geometry })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,12 +148,12 @@ mod tests {
|
||||||
|
|
||||||
let triangles = triangulate(face)?;
|
let triangles = triangulate(face)?;
|
||||||
|
|
||||||
let a = surface.point_from_surface_coords(a);
|
let a = surface.geometry().point_from_surface_coords(a);
|
||||||
let b = surface.point_from_surface_coords(b);
|
let b = surface.geometry().point_from_surface_coords(b);
|
||||||
let e = surface.point_from_surface_coords(e);
|
let e = surface.geometry().point_from_surface_coords(e);
|
||||||
let f = surface.point_from_surface_coords(f);
|
let f = surface.geometry().point_from_surface_coords(f);
|
||||||
let g = surface.point_from_surface_coords(g);
|
let g = surface.geometry().point_from_surface_coords(g);
|
||||||
let h = surface.point_from_surface_coords(h);
|
let h = surface.geometry().point_from_surface_coords(h);
|
||||||
|
|
||||||
// Let's test that some correct triangles are present. We don't need to
|
// Let's test that some correct triangles are present. We don't need to
|
||||||
// test them all.
|
// test them all.
|
||||||
|
@ -209,11 +209,11 @@ mod tests {
|
||||||
|
|
||||||
let triangles = triangulate(face)?;
|
let triangles = triangulate(face)?;
|
||||||
|
|
||||||
let a3 = surface.point_from_surface_coords(a);
|
let a3 = surface.geometry().point_from_surface_coords(a);
|
||||||
let b3 = surface.point_from_surface_coords(b);
|
let b3 = surface.geometry().point_from_surface_coords(b);
|
||||||
let c3 = surface.point_from_surface_coords(c);
|
let c3 = surface.geometry().point_from_surface_coords(c);
|
||||||
let d3 = surface.point_from_surface_coords(d);
|
let d3 = surface.geometry().point_from_surface_coords(d);
|
||||||
let e3 = surface.point_from_surface_coords(e);
|
let e3 = surface.geometry().point_from_surface_coords(e);
|
||||||
|
|
||||||
assert!(triangles.contains_triangle([a3, b3, d3]));
|
assert!(triangles.contains_triangle([a3, b3, d3]));
|
||||||
assert!(triangles.contains_triangle([b3, c3, d3]));
|
assert!(triangles.contains_triangle([b3, c3, d3]));
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use fj_math::{Point, Scalar, Vector};
|
use fj_math::{Point, Scalar, Vector};
|
||||||
|
|
||||||
use crate::{partial::PartialCurve, path::SurfacePath};
|
use crate::{geometry::path::SurfacePath, partial::PartialCurve};
|
||||||
|
|
||||||
/// Builder API for [`PartialCurve`]
|
/// Builder API for [`PartialCurve`]
|
||||||
pub trait CurveBuilder {
|
pub trait CurveBuilder {
|
||||||
|
|
|
@ -5,8 +5,9 @@ use crate::{
|
||||||
insert::Insert,
|
insert::Insert,
|
||||||
objects::{Curve, Objects, Surface, Vertex, VerticesInNormalizedOrder},
|
objects::{Curve, Objects, Surface, Vertex, VerticesInNormalizedOrder},
|
||||||
partial::{
|
partial::{
|
||||||
MaybePartial, PartialCurve, PartialGlobalEdge, PartialGlobalVertex,
|
MaybePartial, MergeWith, PartialCurve, PartialGlobalEdge,
|
||||||
PartialHalfEdge, PartialSurfaceVertex, PartialVertex,
|
PartialGlobalVertex, PartialHalfEdge, PartialSurfaceVertex,
|
||||||
|
PartialVertex,
|
||||||
},
|
},
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
|
@ -135,8 +136,8 @@ impl HalfEdgeBuilder for PartialHalfEdge {
|
||||||
let surface = self
|
let surface = self
|
||||||
.curve()
|
.curve()
|
||||||
.surface()
|
.surface()
|
||||||
.or_else(|| from_surface.surface())
|
.merge_with(from_surface.surface())
|
||||||
.or_else(|| to_surface.surface())
|
.merge_with(to_surface.surface())
|
||||||
.expect("Can't infer line segment without a surface");
|
.expect("Can't infer line segment without a surface");
|
||||||
let points = [&from_surface, &to_surface].map(|vertex| {
|
let points = [&from_surface, &to_surface].map(|vertex| {
|
||||||
vertex
|
vertex
|
||||||
|
|
|
@ -12,6 +12,7 @@ mod curve;
|
||||||
mod cycle;
|
mod cycle;
|
||||||
mod edge;
|
mod edge;
|
||||||
mod face;
|
mod face;
|
||||||
|
mod surface;
|
||||||
mod vertex;
|
mod vertex;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
|
@ -22,5 +23,6 @@ pub use self::{
|
||||||
shell::ShellBuilder,
|
shell::ShellBuilder,
|
||||||
sketch::SketchBuilder,
|
sketch::SketchBuilder,
|
||||||
solid::SolidBuilder,
|
solid::SolidBuilder,
|
||||||
|
surface::SurfaceBuilder,
|
||||||
vertex::{GlobalVertexBuilder, SurfaceVertexBuilder, VertexBuilder},
|
vertex::{GlobalVertexBuilder, SurfaceVertexBuilder, VertexBuilder},
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,10 +6,13 @@ use iter_fixed::IntoIteratorFixed;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
algorithms::transform::TransformObject,
|
algorithms::transform::TransformObject,
|
||||||
builder::{FaceBuilder, HalfEdgeBuilder},
|
builder::{FaceBuilder, HalfEdgeBuilder, SurfaceBuilder},
|
||||||
insert::Insert,
|
insert::Insert,
|
||||||
objects::{Cycle, Face, FaceSet, HalfEdge, Objects, Shell, Surface},
|
objects::{Cycle, Face, FaceSet, HalfEdge, Objects, Shell},
|
||||||
partial::{HasPartial, PartialCurve, PartialSurfaceVertex, PartialVertex},
|
partial::{
|
||||||
|
HasPartial, PartialCurve, PartialSurface, PartialSurfaceVertex,
|
||||||
|
PartialVertex,
|
||||||
|
},
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,9 +81,10 @@ impl<'a> ShellBuilder<'a> {
|
||||||
.map(|vertex| vertex.global_form().position());
|
.map(|vertex| vertex.global_form().position());
|
||||||
let c = a + [Z, Z, edge_length];
|
let c = a + [Z, Z, edge_length];
|
||||||
|
|
||||||
self.objects
|
PartialSurface::plane_from_points([a, b, c])
|
||||||
.surfaces
|
.build(self.objects)
|
||||||
.insert(Surface::plane_from_points([a, b, c]))
|
.unwrap()
|
||||||
|
.insert(self.objects)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
use fj_math::{Line, Point, Vector};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
geometry::{path::GlobalPath, surface::SurfaceGeometry},
|
||||||
|
partial::PartialSurface,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Builder API for [`PartialSurface`]
|
||||||
|
pub trait SurfaceBuilder {
|
||||||
|
/// Build a surface from its two axes
|
||||||
|
fn from_axes(u: GlobalPath, v: impl Into<Vector<3>>) -> Self;
|
||||||
|
|
||||||
|
/// Construct a plane from 3 points
|
||||||
|
fn plane_from_points(points: [impl Into<Point<3>>; 3]) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SurfaceBuilder for PartialSurface {
|
||||||
|
fn from_axes(u: GlobalPath, v: impl Into<Vector<3>>) -> Self {
|
||||||
|
let v = v.into();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
geometry: Some(SurfaceGeometry { u, v }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn plane_from_points(points: [impl Into<Point<3>>; 3]) -> Self {
|
||||||
|
let [a, b, c] = points.map(Into::into);
|
||||||
|
|
||||||
|
let u = GlobalPath::Line(Line::from_points([a, b]));
|
||||||
|
let v = c - a;
|
||||||
|
|
||||||
|
Self {
|
||||||
|
geometry: Some(SurfaceGeometry { u, v }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
use fj_math::Point;
|
use fj_math::Point;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
objects::{Curve, GlobalVertex, Surface},
|
geometry::surface::SurfaceGeometry,
|
||||||
|
objects::{Curve, GlobalVertex},
|
||||||
partial::{
|
partial::{
|
||||||
HasPartial, MaybePartial, PartialGlobalVertex, PartialSurfaceVertex,
|
HasPartial, MaybePartial, PartialGlobalVertex, PartialSurfaceVertex,
|
||||||
PartialVertex,
|
PartialVertex,
|
||||||
|
@ -44,7 +45,7 @@ pub trait GlobalVertexBuilder {
|
||||||
|
|
||||||
/// Update partial global vertex from the given surface and position on it
|
/// Update partial global vertex from the given surface and position on it
|
||||||
fn from_surface_and_position(
|
fn from_surface_and_position(
|
||||||
surface: &Surface,
|
surface: &SurfaceGeometry,
|
||||||
position: impl Into<Point<2>>,
|
position: impl Into<Point<2>>,
|
||||||
) -> Self;
|
) -> Self;
|
||||||
}
|
}
|
||||||
|
@ -59,9 +60,12 @@ impl GlobalVertexBuilder for PartialGlobalVertex {
|
||||||
let path = curve.path.expect(
|
let path = curve.path.expect(
|
||||||
"Need path to create `GlobalVertex` from curve and position",
|
"Need path to create `GlobalVertex` from curve and position",
|
||||||
);
|
);
|
||||||
let surface = curve.surface.expect(
|
let surface = curve
|
||||||
"Need surface to create `GlobalVertex` from curve and position",
|
.surface
|
||||||
);
|
.expect(
|
||||||
|
"Need surface to create `GlobalVertex` from curve and position",
|
||||||
|
)
|
||||||
|
.geometry();
|
||||||
|
|
||||||
let position_surface = path.point_from_path_coords(position);
|
let position_surface = path.point_from_path_coords(position);
|
||||||
|
|
||||||
|
@ -69,7 +73,7 @@ impl GlobalVertexBuilder for PartialGlobalVertex {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_surface_and_position(
|
fn from_surface_and_position(
|
||||||
surface: &Surface,
|
surface: &SurfaceGeometry,
|
||||||
position: impl Into<Point<2>>,
|
position: impl Into<Point<2>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
PartialGlobalVertex {
|
PartialGlobalVertex {
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
//! Types that are tied to objects, but aren't objects themselves
|
||||||
|
|
||||||
|
pub mod path;
|
||||||
|
pub mod surface;
|
|
@ -0,0 +1,81 @@
|
||||||
|
//! The geometry that defines a surface
|
||||||
|
|
||||||
|
use fj_math::{Line, Point, Vector};
|
||||||
|
|
||||||
|
use super::path::GlobalPath;
|
||||||
|
|
||||||
|
/// The geometry that defines a surface
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||||
|
pub struct SurfaceGeometry {
|
||||||
|
/// The u-axis of the surface
|
||||||
|
pub u: GlobalPath,
|
||||||
|
|
||||||
|
/// The v-axis of the surface
|
||||||
|
pub v: Vector<3>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SurfaceGeometry {
|
||||||
|
/// Convert a point in surface coordinates to model coordinates
|
||||||
|
pub fn point_from_surface_coords(
|
||||||
|
&self,
|
||||||
|
point: impl Into<Point<2>>,
|
||||||
|
) -> Point<3> {
|
||||||
|
let point = point.into();
|
||||||
|
self.u.point_from_path_coords([point.u])
|
||||||
|
+ self.path_to_line().vector_from_line_coords([point.v])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a vector in surface coordinates to model coordinates
|
||||||
|
pub fn vector_from_surface_coords(
|
||||||
|
&self,
|
||||||
|
vector: impl Into<Vector<2>>,
|
||||||
|
) -> Vector<3> {
|
||||||
|
let vector = vector.into();
|
||||||
|
self.u.vector_from_path_coords([vector.u])
|
||||||
|
+ self.path_to_line().vector_from_line_coords([vector.v])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn path_to_line(&self) -> Line<3> {
|
||||||
|
Line::from_origin_and_direction(self.u.origin(), self.v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use fj_math::{Line, Point, Vector};
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use crate::geometry::{path::GlobalPath, surface::SurfaceGeometry};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn point_from_surface_coords() {
|
||||||
|
let surface = SurfaceGeometry {
|
||||||
|
u: GlobalPath::Line(Line::from_origin_and_direction(
|
||||||
|
Point::from([1., 1., 1.]),
|
||||||
|
Vector::from([0., 2., 0.]),
|
||||||
|
)),
|
||||||
|
v: Vector::from([0., 0., 2.]),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
surface.point_from_surface_coords([2., 4.]),
|
||||||
|
Point::from([1., 5., 9.]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vector_from_surface_coords() {
|
||||||
|
let surface = SurfaceGeometry {
|
||||||
|
u: GlobalPath::Line(Line::from_origin_and_direction(
|
||||||
|
Point::from([1., 0., 0.]),
|
||||||
|
Vector::from([0., 2., 0.]),
|
||||||
|
)),
|
||||||
|
v: Vector::from([0., 0., 2.]),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
surface.vector_from_surface_coords([2., 4.]),
|
||||||
|
Vector::from([0., 4., 8.]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -89,10 +89,10 @@
|
||||||
|
|
||||||
pub mod algorithms;
|
pub mod algorithms;
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
|
pub mod geometry;
|
||||||
pub mod insert;
|
pub mod insert;
|
||||||
pub mod iter;
|
pub mod iter;
|
||||||
pub mod objects;
|
pub mod objects;
|
||||||
pub mod partial;
|
pub mod partial;
|
||||||
pub mod path;
|
|
||||||
pub mod storage;
|
pub mod storage;
|
||||||
pub mod validate;
|
pub mod validate;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
path::SurfacePath,
|
geometry::path::SurfacePath,
|
||||||
storage::{Handle, HandleWrapper},
|
storage::{Handle, HandleWrapper},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::slice;
|
||||||
use fj_interop::ext::SliceExt;
|
use fj_interop::ext::SliceExt;
|
||||||
use fj_math::{Scalar, Winding};
|
use fj_math::{Scalar, Winding};
|
||||||
|
|
||||||
use crate::{path::SurfacePath, storage::Handle};
|
use crate::{geometry::path::SurfacePath, storage::Handle};
|
||||||
|
|
||||||
use super::{HalfEdge, Surface};
|
use super::{HalfEdge, Surface};
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ use std::convert::Infallible;
|
||||||
use fj_math::Vector;
|
use fj_math::Vector;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
path::GlobalPath,
|
geometry::{path::GlobalPath, surface::SurfaceGeometry},
|
||||||
storage::{Handle, Store},
|
storage::{Handle, Store},
|
||||||
validate::{
|
validate::{
|
||||||
CycleValidationError, FaceValidationError, HalfEdgeValidationError,
|
CycleValidationError, FaceValidationError, HalfEdgeValidationError,
|
||||||
|
@ -380,12 +380,18 @@ impl Default for Surfaces {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let store = Store::new();
|
let store = Store::new();
|
||||||
|
|
||||||
let xy_plane =
|
let xy_plane = store.insert(Surface::new(SurfaceGeometry {
|
||||||
store.insert(Surface::new(GlobalPath::x_axis(), Vector::unit_y()));
|
u: GlobalPath::x_axis(),
|
||||||
let xz_plane =
|
v: Vector::unit_y(),
|
||||||
store.insert(Surface::new(GlobalPath::x_axis(), Vector::unit_z()));
|
}));
|
||||||
let yz_plane =
|
let xz_plane = store.insert(Surface::new(SurfaceGeometry {
|
||||||
store.insert(Surface::new(GlobalPath::y_axis(), Vector::unit_z()));
|
u: GlobalPath::x_axis(),
|
||||||
|
v: Vector::unit_z(),
|
||||||
|
}));
|
||||||
|
let yz_plane = store.insert(Surface::new(SurfaceGeometry {
|
||||||
|
u: GlobalPath::y_axis(),
|
||||||
|
v: Vector::unit_z(),
|
||||||
|
}));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
store,
|
store,
|
||||||
|
|
|
@ -1,104 +1,19 @@
|
||||||
use fj_math::{Line, Point, Vector};
|
use crate::geometry::surface::SurfaceGeometry;
|
||||||
|
|
||||||
use crate::path::GlobalPath;
|
|
||||||
|
|
||||||
/// A two-dimensional shape
|
/// A two-dimensional shape
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||||
pub struct Surface {
|
pub struct Surface {
|
||||||
u: GlobalPath,
|
geometry: SurfaceGeometry,
|
||||||
v: Vector<3>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Surface {
|
impl Surface {
|
||||||
/// Construct a `Surface` from two paths that define its coordinate system
|
/// Construct a `Surface` from two paths that define its coordinate system
|
||||||
pub fn new(u: GlobalPath, v: impl Into<Vector<3>>) -> Self {
|
pub fn new(geometry: SurfaceGeometry) -> Self {
|
||||||
let v = v.into();
|
Self { geometry }
|
||||||
Self { u, v }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a plane from 3 points
|
/// Access the surface's geometry
|
||||||
pub fn plane_from_points(points: [impl Into<Point<3>>; 3]) -> Self {
|
pub fn geometry(&self) -> SurfaceGeometry {
|
||||||
let [a, b, c] = points.map(Into::into);
|
self.geometry
|
||||||
|
|
||||||
let u = GlobalPath::Line(Line::from_points([a, b]));
|
|
||||||
let v = c - a;
|
|
||||||
|
|
||||||
Self { u, v }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Access the path that defines the u-coordinate of this surface
|
|
||||||
pub fn u(&self) -> GlobalPath {
|
|
||||||
self.u
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Access the path that defines the v-coordinate of this surface
|
|
||||||
pub fn v(&self) -> Vector<3> {
|
|
||||||
self.v
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert a point in surface coordinates to model coordinates
|
|
||||||
pub fn point_from_surface_coords(
|
|
||||||
&self,
|
|
||||||
point: impl Into<Point<2>>,
|
|
||||||
) -> Point<3> {
|
|
||||||
let point = point.into();
|
|
||||||
self.u.point_from_path_coords([point.u])
|
|
||||||
+ self.path_to_line().vector_from_line_coords([point.v])
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert a vector in surface coordinates to model coordinates
|
|
||||||
pub fn vector_from_surface_coords(
|
|
||||||
&self,
|
|
||||||
vector: impl Into<Vector<2>>,
|
|
||||||
) -> Vector<3> {
|
|
||||||
let vector = vector.into();
|
|
||||||
self.u.vector_from_path_coords([vector.u])
|
|
||||||
+ self.path_to_line().vector_from_line_coords([vector.v])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn path_to_line(&self) -> Line<3> {
|
|
||||||
Line::from_origin_and_direction(self.u.origin(), self.v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use fj_math::{Line, Point, Vector};
|
|
||||||
use pretty_assertions::assert_eq;
|
|
||||||
|
|
||||||
use crate::path::GlobalPath;
|
|
||||||
|
|
||||||
use super::Surface;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn point_from_surface_coords() {
|
|
||||||
let swept = Surface {
|
|
||||||
u: GlobalPath::Line(Line::from_origin_and_direction(
|
|
||||||
Point::from([1., 1., 1.]),
|
|
||||||
Vector::from([0., 2., 0.]),
|
|
||||||
)),
|
|
||||||
v: Vector::from([0., 0., 2.]),
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
swept.point_from_surface_coords([2., 4.]),
|
|
||||||
Point::from([1., 5., 9.]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn vector_from_surface_coords() {
|
|
||||||
let swept = Surface {
|
|
||||||
u: GlobalPath::Line(Line::from_origin_and_direction(
|
|
||||||
Point::from([1., 0., 0.]),
|
|
||||||
Vector::from([0., 2., 0.]),
|
|
||||||
)),
|
|
||||||
v: Vector::from([0., 0., 2.]),
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
swept.vector_from_surface_coords([2., 4.]),
|
|
||||||
Vector::from([0., 4., 8.]),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use fj_math::Point;
|
use fj_math::Point;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
geometry::{path::SurfacePath, surface::SurfaceGeometry},
|
||||||
insert::Insert,
|
insert::Insert,
|
||||||
objects::{
|
objects::{
|
||||||
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
Curve, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge, Objects,
|
||||||
Surface, SurfaceVertex, Vertex,
|
Surface, SurfaceVertex, Vertex,
|
||||||
},
|
},
|
||||||
path::SurfacePath,
|
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::{Validate, ValidationError},
|
validate::{Validate, ValidationError},
|
||||||
};
|
};
|
||||||
|
@ -212,6 +212,16 @@ impl MaybePartial<HalfEdge> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MaybePartial<Surface> {
|
||||||
|
/// Access the geometry
|
||||||
|
pub fn geometry(&self) -> Option<SurfaceGeometry> {
|
||||||
|
match self {
|
||||||
|
Self::Full(full) => Some(full.geometry()),
|
||||||
|
Self::Partial(partial) => partial.geometry,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MaybePartial<SurfaceVertex> {
|
impl MaybePartial<SurfaceVertex> {
|
||||||
/// Access the position
|
/// Access the position
|
||||||
pub fn position(&self) -> Option<Point<2>> {
|
pub fn position(&self) -> Option<Point<2>> {
|
||||||
|
|
|
@ -47,6 +47,7 @@ pub use self::{
|
||||||
cycle::PartialCycle,
|
cycle::PartialCycle,
|
||||||
edge::{PartialGlobalEdge, PartialHalfEdge},
|
edge::{PartialGlobalEdge, PartialHalfEdge},
|
||||||
face::PartialFace,
|
face::PartialFace,
|
||||||
|
surface::PartialSurface,
|
||||||
vertex::{PartialGlobalVertex, PartialSurfaceVertex, PartialVertex},
|
vertex::{PartialGlobalVertex, PartialSurfaceVertex, PartialVertex},
|
||||||
},
|
},
|
||||||
traits::{HasPartial, Partial},
|
traits::{HasPartial, Partial},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
|
geometry::path::SurfacePath,
|
||||||
objects::{Curve, GlobalCurve, Objects, Surface},
|
objects::{Curve, GlobalCurve, Objects, Surface},
|
||||||
partial::{MaybePartial, MergeWith, Mergeable},
|
partial::{MaybePartial, MergeWith, Mergeable},
|
||||||
path::SurfacePath,
|
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
validate::ValidationError,
|
validate::ValidationError,
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,17 +2,18 @@ pub mod curve;
|
||||||
pub mod cycle;
|
pub mod cycle;
|
||||||
pub mod edge;
|
pub mod edge;
|
||||||
pub mod face;
|
pub mod face;
|
||||||
|
pub mod surface;
|
||||||
pub mod vertex;
|
pub mod vertex;
|
||||||
|
|
||||||
use crate::objects::{
|
use crate::objects::{
|
||||||
Curve, Cycle, Face, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge,
|
Curve, Cycle, Face, GlobalCurve, GlobalEdge, GlobalVertex, HalfEdge,
|
||||||
Objects, SurfaceVertex, Vertex,
|
Objects, Surface, SurfaceVertex, Vertex,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
HasPartial, MaybePartial, Partial, PartialCurve, PartialCycle, PartialFace,
|
HasPartial, MaybePartial, Partial, PartialCurve, PartialCycle, PartialFace,
|
||||||
PartialGlobalCurve, PartialGlobalEdge, PartialGlobalVertex,
|
PartialGlobalCurve, PartialGlobalEdge, PartialGlobalVertex,
|
||||||
PartialHalfEdge, PartialSurfaceVertex, PartialVertex,
|
PartialHalfEdge, PartialSurface, PartialSurfaceVertex, PartialVertex,
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! impl_traits {
|
macro_rules! impl_traits {
|
||||||
|
@ -52,6 +53,7 @@ impl_traits!(
|
||||||
GlobalEdge, PartialGlobalEdge;
|
GlobalEdge, PartialGlobalEdge;
|
||||||
GlobalVertex, PartialGlobalVertex;
|
GlobalVertex, PartialGlobalVertex;
|
||||||
HalfEdge, PartialHalfEdge;
|
HalfEdge, PartialHalfEdge;
|
||||||
|
Surface, PartialSurface;
|
||||||
SurfaceVertex, PartialSurfaceVertex;
|
SurfaceVertex, PartialSurfaceVertex;
|
||||||
Vertex, PartialVertex;
|
Vertex, PartialVertex;
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
use crate::{
|
||||||
|
geometry::surface::SurfaceGeometry,
|
||||||
|
objects::{Objects, Surface},
|
||||||
|
partial::MergeWith,
|
||||||
|
validate::ValidationError,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A partial [`Surface`]
|
||||||
|
///
|
||||||
|
/// See [`crate::partial`] for more information
|
||||||
|
#[derive(Clone, Debug, Default)]
|
||||||
|
pub struct PartialSurface {
|
||||||
|
/// The geometry that defines the [`Surface`]
|
||||||
|
pub geometry: Option<SurfaceGeometry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialSurface {
|
||||||
|
/// Build a full [`Surface`] from the partial surface
|
||||||
|
pub fn build(self, _: &Objects) -> Result<Surface, ValidationError> {
|
||||||
|
let geometry = self
|
||||||
|
.geometry
|
||||||
|
.expect("Can't build `Surface` without geometry");
|
||||||
|
|
||||||
|
Ok(Surface::new(geometry))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MergeWith for PartialSurface {
|
||||||
|
fn merge_with(self, other: impl Into<Self>) -> Self {
|
||||||
|
let other = other.into();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
geometry: self.geometry.merge_with(other.geometry),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Surface> for PartialSurface {
|
||||||
|
fn from(surface: &Surface) -> Self {
|
||||||
|
Self {
|
||||||
|
geometry: Some(surface.geometry()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -80,7 +80,7 @@ impl From<&Vertex> for PartialVertex {
|
||||||
/// A partial [`SurfaceVertex`]
|
/// A partial [`SurfaceVertex`]
|
||||||
///
|
///
|
||||||
/// See [`crate::partial`] for more information.
|
/// See [`crate::partial`] for more information.
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct PartialSurfaceVertex {
|
pub struct PartialSurfaceVertex {
|
||||||
/// The position of the [`SurfaceVertex`]
|
/// The position of the [`SurfaceVertex`]
|
||||||
pub position: Option<Point<2>>,
|
pub position: Option<Point<2>>,
|
||||||
|
@ -108,7 +108,8 @@ impl PartialSurfaceVertex {
|
||||||
let global_form = self
|
let global_form = self
|
||||||
.global_form
|
.global_form
|
||||||
.merge_with(PartialGlobalVertex::from_surface_and_position(
|
.merge_with(PartialGlobalVertex::from_surface_and_position(
|
||||||
&surface, position,
|
&surface.geometry(),
|
||||||
|
position,
|
||||||
))
|
))
|
||||||
.into_full(objects)?;
|
.into_full(objects)?;
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,7 @@ impl SurfaceVertexValidationError {
|
||||||
) -> Result<(), Self> {
|
) -> Result<(), Self> {
|
||||||
let surface_position_as_global = surface_vertex
|
let surface_position_as_global = surface_vertex
|
||||||
.surface()
|
.surface()
|
||||||
|
.geometry()
|
||||||
.point_from_surface_coords(surface_vertex.position());
|
.point_from_surface_coords(surface_vertex.position());
|
||||||
let global_position = surface_vertex.global_form().position();
|
let global_position = surface_vertex.global_form().position();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue