mirror of
https://github.com/hannobraun/Fornjot
synced 2025-01-11 10:47:09 +00:00
Merge pull request #2275 from hannobraun/geometry
Read half-edge geometry from geometry layer in most places
This commit is contained in:
commit
ee15b609a5
@ -2,8 +2,6 @@
|
|||||||
//!
|
//!
|
||||||
//! See [`CycleApprox`].
|
//! See [`CycleApprox`].
|
||||||
|
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
use fj_math::Segment;
|
use fj_math::Segment;
|
||||||
|
|
||||||
use crate::{geometry::SurfaceGeometry, objects::Cycle, Core};
|
use crate::{geometry::SurfaceGeometry, objects::Cycle, Core};
|
||||||
@ -30,8 +28,7 @@ impl Approx for (&Cycle, &SurfaceGeometry) {
|
|||||||
.half_edges()
|
.half_edges()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|half_edge| {
|
.map(|half_edge| {
|
||||||
(half_edge.deref(), surface)
|
(half_edge, surface).approx_with_cache(tolerance, cache, core)
|
||||||
.approx_with_cache(tolerance, cache, core)
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -5,14 +5,16 @@
|
|||||||
//! approximations are usually used to build cycle approximations, and this way,
|
//! approximations are usually used to build cycle approximations, and this way,
|
||||||
//! the caller doesn't have to deal with duplicate vertices.
|
//! the caller doesn't have to deal with duplicate vertices.
|
||||||
|
|
||||||
use crate::{geometry::SurfaceGeometry, objects::HalfEdge, Core};
|
use crate::{
|
||||||
|
geometry::SurfaceGeometry, objects::HalfEdge, storage::Handle, Core,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
curve::CurveApproxCache, vertex::VertexApproxCache, Approx, ApproxPoint,
|
curve::CurveApproxCache, vertex::VertexApproxCache, Approx, ApproxPoint,
|
||||||
Tolerance,
|
Tolerance,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Approx for (&HalfEdge, &SurfaceGeometry) {
|
impl Approx for (&Handle<HalfEdge>, &SurfaceGeometry) {
|
||||||
type Approximation = HalfEdgeApprox;
|
type Approximation = HalfEdgeApprox;
|
||||||
type Cache = HalfEdgeApproxCache;
|
type Cache = HalfEdgeApproxCache;
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ impl Approx for (&HalfEdge, &SurfaceGeometry) {
|
|||||||
let rest = {
|
let rest = {
|
||||||
let approx = (
|
let approx = (
|
||||||
half_edge.curve(),
|
half_edge.curve(),
|
||||||
half_edge.path(),
|
core.layers.geometry.of_half_edge(half_edge).path,
|
||||||
surface,
|
surface,
|
||||||
half_edge.boundary(),
|
half_edge.boundary(),
|
||||||
)
|
)
|
||||||
@ -55,8 +57,12 @@ impl Approx for (&HalfEdge, &SurfaceGeometry) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
approx.points.into_iter().map(|point| {
|
approx.points.into_iter().map(|point| {
|
||||||
let point_surface =
|
let point_surface = core
|
||||||
half_edge.path().point_from_path_coords(point.local_form);
|
.layers
|
||||||
|
.geometry
|
||||||
|
.of_half_edge(half_edge)
|
||||||
|
.path
|
||||||
|
.point_from_path_coords(point.local_form);
|
||||||
|
|
||||||
ApproxPoint::new(point_surface, point.global_form)
|
ApproxPoint::new(point_surface, point.global_form)
|
||||||
})
|
})
|
||||||
|
@ -110,7 +110,7 @@ impl Approx for &Face {
|
|||||||
exterior,
|
exterior,
|
||||||
interiors,
|
interiors,
|
||||||
color: self.region().get_color(core),
|
color: self.region().get_color(core),
|
||||||
coord_handedness: self.coord_handedness(),
|
coord_handedness: self.coord_handedness(&core.layers.geometry),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,12 @@ use fj_math::{Aabb, Vector};
|
|||||||
use crate::{
|
use crate::{
|
||||||
geometry::{Geometry, SurfacePath},
|
geometry::{Geometry, SurfacePath},
|
||||||
objects::HalfEdge,
|
objects::HalfEdge,
|
||||||
|
storage::Handle,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl super::BoundingVolume<2> for HalfEdge {
|
impl super::BoundingVolume<2> for Handle<HalfEdge> {
|
||||||
fn aabb(&self, _: &Geometry) -> Option<Aabb<2>> {
|
fn aabb(&self, geometry: &Geometry) -> Option<Aabb<2>> {
|
||||||
match self.path() {
|
match geometry.of_half_edge(self).path {
|
||||||
SurfacePath::Circle(circle) => {
|
SurfacePath::Circle(circle) => {
|
||||||
// Just calculate the AABB of the whole circle. This is not the
|
// Just calculate the AABB of the whole circle. This is not the
|
||||||
// most precise, but it should do for now.
|
// most precise, but it should do for now.
|
||||||
@ -22,7 +23,10 @@ impl super::BoundingVolume<2> for HalfEdge {
|
|||||||
}
|
}
|
||||||
SurfacePath::Line(_) => {
|
SurfacePath::Line(_) => {
|
||||||
let points = self.boundary().inner.map(|point_curve| {
|
let points = self.boundary().inner.map(|point_curve| {
|
||||||
self.path().point_from_path_coords(point_curve)
|
geometry
|
||||||
|
.of_half_edge(self)
|
||||||
|
.path
|
||||||
|
.point_from_path_coords(point_curve)
|
||||||
});
|
});
|
||||||
|
|
||||||
Some(Aabb::<2>::from_points(points))
|
Some(Aabb::<2>::from_points(points))
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use fj_math::{Scalar, Winding};
|
use fj_math::{Scalar, Winding};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
geometry::SurfacePath,
|
geometry::{Geometry, SurfacePath},
|
||||||
objects::{HalfEdge, ObjectSet},
|
objects::{HalfEdge, ObjectSet},
|
||||||
storage::Handle,
|
storage::Handle,
|
||||||
};
|
};
|
||||||
@ -29,7 +29,7 @@ impl Cycle {
|
|||||||
/// Please note that this is not *the* winding of the cycle, only one of the
|
/// Please note that this is not *the* winding of the cycle, only one of the
|
||||||
/// two possible windings, depending on the direction you look at the
|
/// two possible windings, depending on the direction you look at the
|
||||||
/// surface that the cycle is defined on from.
|
/// surface that the cycle is defined on from.
|
||||||
pub fn winding(&self) -> Winding {
|
pub fn winding(&self, geometry: &Geometry) -> Winding {
|
||||||
// The cycle could be made up of one or two circles. If that is the
|
// The cycle could be made up of one or two circles. If that is the
|
||||||
// case, the winding of the cycle is determined by the winding of the
|
// case, the winding of the cycle is determined by the winding of the
|
||||||
// first circle.
|
// first circle.
|
||||||
@ -43,7 +43,7 @@ impl Cycle {
|
|||||||
let [a, b] = first.boundary().inner;
|
let [a, b] = first.boundary().inner;
|
||||||
let edge_direction_positive = a < b;
|
let edge_direction_positive = a < b;
|
||||||
|
|
||||||
let circle = match first.path() {
|
let circle = match geometry.of_half_edge(first).path {
|
||||||
SurfacePath::Circle(circle) => circle,
|
SurfacePath::Circle(circle) => circle,
|
||||||
SurfacePath::Line(_) => unreachable!(
|
SurfacePath::Line(_) => unreachable!(
|
||||||
"Invalid cycle: less than 3 edges, but not all are circles"
|
"Invalid cycle: less than 3 edges, but not all are circles"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use fj_math::Winding;
|
use fj_math::Winding;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
geometry::Geometry,
|
||||||
objects::{Region, Surface},
|
objects::{Region, Surface},
|
||||||
storage::{Handle, HandleWrapper},
|
storage::{Handle, HandleWrapper},
|
||||||
};
|
};
|
||||||
@ -64,8 +65,8 @@ impl Face {
|
|||||||
/// Faces *do* have an orientation, meaning they have definite front and
|
/// Faces *do* have an orientation, meaning they have definite front and
|
||||||
/// back sides. The front side is the side, where the face's exterior cycle
|
/// back sides. The front side is the side, where the face's exterior cycle
|
||||||
/// is wound counter-clockwise.
|
/// is wound counter-clockwise.
|
||||||
pub fn coord_handedness(&self) -> Handedness {
|
pub fn coord_handedness(&self, geometry: &Geometry) -> Handedness {
|
||||||
match self.region.exterior().winding() {
|
match self.region.exterior().winding(geometry) {
|
||||||
Winding::Ccw => Handedness::RightHanded,
|
Winding::Ccw => Handedness::RightHanded,
|
||||||
Winding::Cw => Handedness::LeftHanded,
|
Winding::Cw => Handedness::LeftHanded,
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ pub trait BuildHalfEdge {
|
|||||||
core: &mut Core,
|
core: &mut Core,
|
||||||
) -> Handle<HalfEdge> {
|
) -> Handle<HalfEdge> {
|
||||||
let half_edge = HalfEdge::new(
|
let half_edge = HalfEdge::new(
|
||||||
sibling.path(),
|
core.layers.geometry.of_half_edge(sibling).path,
|
||||||
sibling.boundary().reverse(),
|
sibling.boundary().reverse(),
|
||||||
sibling.curve().clone(),
|
sibling.curve().clone(),
|
||||||
start_vertex,
|
start_vertex,
|
||||||
@ -44,7 +44,7 @@ pub trait BuildHalfEdge {
|
|||||||
core.layers.geometry.define_half_edge(
|
core.layers.geometry.define_half_edge(
|
||||||
half_edge.clone(),
|
half_edge.clone(),
|
||||||
HalfEdgeGeometry {
|
HalfEdgeGeometry {
|
||||||
path: sibling.path(),
|
path: core.layers.geometry.of_half_edge(sibling).path,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ impl UpdateHalfEdgeGeometry for Handle<HalfEdge> {
|
|||||||
update: impl FnOnce(SurfacePath) -> SurfacePath,
|
update: impl FnOnce(SurfacePath) -> SurfacePath,
|
||||||
core: &mut Core,
|
core: &mut Core,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let path = update(self.path());
|
let path = update(core.layers.geometry.of_half_edge(self).path);
|
||||||
|
|
||||||
let half_edge = HalfEdge::new(
|
let half_edge = HalfEdge::new(
|
||||||
path,
|
path,
|
||||||
@ -73,7 +73,7 @@ impl UpdateHalfEdgeGeometry for Handle<HalfEdge> {
|
|||||||
core: &mut Core,
|
core: &mut Core,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
HalfEdge::new(
|
HalfEdge::new(
|
||||||
self.path(),
|
core.layers.geometry.of_half_edge(self).path,
|
||||||
update(self.boundary()),
|
update(self.boundary()),
|
||||||
self.curve().clone(),
|
self.curve().clone(),
|
||||||
self.start_vertex().clone(),
|
self.start_vertex().clone(),
|
||||||
|
@ -68,7 +68,10 @@ impl AddHole for Shell {
|
|||||||
[Cycle::empty().add_joined_edges(
|
[Cycle::empty().add_joined_edges(
|
||||||
[(
|
[(
|
||||||
entry.clone(),
|
entry.clone(),
|
||||||
entry.path(),
|
core.layers
|
||||||
|
.geometry
|
||||||
|
.of_half_edge(&entry)
|
||||||
|
.path,
|
||||||
entry.boundary(),
|
entry.boundary(),
|
||||||
)],
|
)],
|
||||||
core,
|
core,
|
||||||
@ -139,7 +142,10 @@ impl AddHole for Shell {
|
|||||||
[Cycle::empty().add_joined_edges(
|
[Cycle::empty().add_joined_edges(
|
||||||
[(
|
[(
|
||||||
entry.clone(),
|
entry.clone(),
|
||||||
entry.path(),
|
core.layers
|
||||||
|
.geometry
|
||||||
|
.of_half_edge(&entry)
|
||||||
|
.path,
|
||||||
entry.boundary(),
|
entry.boundary(),
|
||||||
)],
|
)],
|
||||||
core,
|
core,
|
||||||
@ -159,7 +165,14 @@ impl AddHole for Shell {
|
|||||||
|region, core| {
|
|region, core| {
|
||||||
region.add_interiors(
|
region.add_interiors(
|
||||||
[Cycle::empty().add_joined_edges(
|
[Cycle::empty().add_joined_edges(
|
||||||
[(exit.clone(), exit.path(), exit.boundary())],
|
[(
|
||||||
|
exit.clone(),
|
||||||
|
core.layers
|
||||||
|
.geometry
|
||||||
|
.of_half_edge(exit)
|
||||||
|
.path,
|
||||||
|
exit.boundary(),
|
||||||
|
)],
|
||||||
core,
|
core,
|
||||||
)],
|
)],
|
||||||
core,
|
core,
|
||||||
|
@ -14,7 +14,7 @@ impl Reverse for Cycle {
|
|||||||
.pairs()
|
.pairs()
|
||||||
.map(|(current, next)| {
|
.map(|(current, next)| {
|
||||||
let half_edge = HalfEdge::new(
|
let half_edge = HalfEdge::new(
|
||||||
current.path(),
|
core.layers.geometry.of_half_edge(current).path,
|
||||||
current.boundary().reverse(),
|
current.boundary().reverse(),
|
||||||
current.curve().clone(),
|
current.curve().clone(),
|
||||||
next.start_vertex().clone(),
|
next.start_vertex().clone(),
|
||||||
@ -25,7 +25,7 @@ impl Reverse for Cycle {
|
|||||||
core.layers.geometry.define_half_edge(
|
core.layers.geometry.define_half_edge(
|
||||||
half_edge.clone(),
|
half_edge.clone(),
|
||||||
HalfEdgeGeometry {
|
HalfEdgeGeometry {
|
||||||
path: current.path(),
|
path: core.layers.geometry.of_half_edge(current).path,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ use super::ReverseCurveCoordinateSystems;
|
|||||||
|
|
||||||
impl ReverseCurveCoordinateSystems for Handle<HalfEdge> {
|
impl ReverseCurveCoordinateSystems for Handle<HalfEdge> {
|
||||||
fn reverse_curve_coordinate_systems(&self, core: &mut Core) -> Self {
|
fn reverse_curve_coordinate_systems(&self, core: &mut Core) -> Self {
|
||||||
let path = self.path().reverse();
|
let path = core.layers.geometry.of_half_edge(self).path.reverse();
|
||||||
let boundary = self.boundary().reverse();
|
let boundary = self.boundary().reverse();
|
||||||
|
|
||||||
let half_edge = HalfEdge::new(
|
let half_edge = HalfEdge::new(
|
||||||
|
@ -33,7 +33,7 @@ pub trait SplitHalfEdge {
|
|||||||
) -> [Handle<HalfEdge>; 2];
|
) -> [Handle<HalfEdge>; 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SplitHalfEdge for HalfEdge {
|
impl SplitHalfEdge for Handle<HalfEdge> {
|
||||||
fn split_half_edge(
|
fn split_half_edge(
|
||||||
&self,
|
&self,
|
||||||
point: impl Into<Point<1>>,
|
point: impl Into<Point<1>>,
|
||||||
@ -44,14 +44,14 @@ impl SplitHalfEdge for HalfEdge {
|
|||||||
let [start, end] = self.boundary().inner;
|
let [start, end] = self.boundary().inner;
|
||||||
|
|
||||||
let a = HalfEdge::new(
|
let a = HalfEdge::new(
|
||||||
self.path(),
|
core.layers.geometry.of_half_edge(self).path,
|
||||||
[start, point],
|
[start, point],
|
||||||
self.curve().clone(),
|
self.curve().clone(),
|
||||||
self.start_vertex().clone(),
|
self.start_vertex().clone(),
|
||||||
)
|
)
|
||||||
.insert(core);
|
.insert(core);
|
||||||
let b = HalfEdge::new(
|
let b = HalfEdge::new(
|
||||||
self.path(),
|
core.layers.geometry.of_half_edge(self).path,
|
||||||
[point, end],
|
[point, end],
|
||||||
self.curve().clone(),
|
self.curve().clone(),
|
||||||
Vertex::new().insert(core),
|
Vertex::new().insert(core),
|
||||||
@ -60,11 +60,15 @@ impl SplitHalfEdge for HalfEdge {
|
|||||||
|
|
||||||
core.layers.geometry.define_half_edge(
|
core.layers.geometry.define_half_edge(
|
||||||
a.clone(),
|
a.clone(),
|
||||||
HalfEdgeGeometry { path: self.path() },
|
HalfEdgeGeometry {
|
||||||
|
path: core.layers.geometry.of_half_edge(self).path,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
core.layers.geometry.define_half_edge(
|
core.layers.geometry.define_half_edge(
|
||||||
b.clone(),
|
b.clone(),
|
||||||
HalfEdgeGeometry { path: self.path() },
|
HalfEdgeGeometry {
|
||||||
|
path: core.layers.geometry.of_half_edge(self).path,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
[a, b]
|
[a, b]
|
||||||
|
@ -77,7 +77,7 @@ impl SweepCycle for Cycle {
|
|||||||
|
|
||||||
top_edges.push((
|
top_edges.push((
|
||||||
top_edge,
|
top_edge,
|
||||||
bottom_half_edge.path(),
|
core.layers.geometry.of_half_edge(bottom_half_edge).path,
|
||||||
bottom_half_edge.boundary(),
|
bottom_half_edge.boundary(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ pub trait SweepHalfEdge {
|
|||||||
) -> (Face, Handle<HalfEdge>);
|
) -> (Face, Handle<HalfEdge>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SweepHalfEdge for HalfEdge {
|
impl SweepHalfEdge for Handle<HalfEdge> {
|
||||||
fn sweep_half_edge(
|
fn sweep_half_edge(
|
||||||
&self,
|
&self,
|
||||||
end_vertex: Handle<Vertex>,
|
end_vertex: Handle<Vertex>,
|
||||||
@ -59,7 +59,12 @@ impl SweepHalfEdge for HalfEdge {
|
|||||||
) -> (Face, Handle<HalfEdge>) {
|
) -> (Face, Handle<HalfEdge>) {
|
||||||
let path = path.into();
|
let path = path.into();
|
||||||
|
|
||||||
let surface = self.path().sweep_surface_path(surface, path, core);
|
let surface = core
|
||||||
|
.layers
|
||||||
|
.geometry
|
||||||
|
.of_half_edge(self)
|
||||||
|
.path
|
||||||
|
.sweep_surface_path(surface, path, core);
|
||||||
|
|
||||||
// Next, we need to define the boundaries of the face. Let's start with
|
// Next, we need to define the boundaries of the face. Let's start with
|
||||||
// the global vertices and edges.
|
// the global vertices and edges.
|
||||||
|
@ -40,7 +40,10 @@ impl SweepSketch for Sketch {
|
|||||||
let region = {
|
let region = {
|
||||||
// The following code assumes that the sketch is winded counter-
|
// The following code assumes that the sketch is winded counter-
|
||||||
// clockwise. Let's check that real quick.
|
// clockwise. Let's check that real quick.
|
||||||
assert!(region.exterior().winding().is_ccw());
|
assert!(region
|
||||||
|
.exterior()
|
||||||
|
.winding(&core.layers.geometry)
|
||||||
|
.is_ccw());
|
||||||
|
|
||||||
let is_negative_sweep = {
|
let is_negative_sweep = {
|
||||||
let u = match core.layers.geometry.of_surface(&surface).u {
|
let u = match core.layers.geometry.of_surface(&surface).u {
|
||||||
|
@ -16,7 +16,7 @@ impl TransformObject for Handle<HalfEdge> {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
// Don't need to transform the path, as that's defined in surface
|
// Don't need to transform the path, as that's defined in surface
|
||||||
// coordinates.
|
// coordinates.
|
||||||
let path = self.path();
|
let path = core.layers.geometry.of_half_edge(self).path;
|
||||||
let boundary = self.boundary();
|
let boundary = self.boundary();
|
||||||
let curve = self
|
let curve = self
|
||||||
.curve()
|
.curve()
|
||||||
|
@ -13,10 +13,10 @@ impl Validate for Face {
|
|||||||
&self,
|
&self,
|
||||||
_: &ValidationConfig,
|
_: &ValidationConfig,
|
||||||
errors: &mut Vec<ValidationError>,
|
errors: &mut Vec<ValidationError>,
|
||||||
_: &Geometry,
|
geometry: &Geometry,
|
||||||
) {
|
) {
|
||||||
FaceValidationError::check_boundary(self, errors);
|
FaceValidationError::check_boundary(self, errors);
|
||||||
FaceValidationError::check_interior_winding(self, errors);
|
FaceValidationError::check_interior_winding(self, geometry, errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,14 +56,18 @@ impl FaceValidationError {
|
|||||||
// checks for `Cycle` to make sure that the cycle is closed properly.
|
// checks for `Cycle` to make sure that the cycle is closed properly.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_interior_winding(face: &Face, errors: &mut Vec<ValidationError>) {
|
fn check_interior_winding(
|
||||||
|
face: &Face,
|
||||||
|
geometry: &Geometry,
|
||||||
|
errors: &mut Vec<ValidationError>,
|
||||||
|
) {
|
||||||
if face.region().exterior().half_edges().is_empty() {
|
if face.region().exterior().half_edges().is_empty() {
|
||||||
// Can't determine winding, if the cycle has no edges. Sounds like a
|
// Can't determine winding, if the cycle has no edges. Sounds like a
|
||||||
// job for a different validation check.
|
// job for a different validation check.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let exterior_winding = face.region().exterior().winding();
|
let exterior_winding = face.region().exterior().winding(geometry);
|
||||||
|
|
||||||
for interior in face.region().interiors() {
|
for interior in face.region().interiors() {
|
||||||
if interior.half_edges().is_empty() {
|
if interior.half_edges().is_empty() {
|
||||||
@ -71,7 +75,7 @@ impl FaceValidationError {
|
|||||||
// like a job for a different validation check.
|
// like a job for a different validation check.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let interior_winding = interior.winding();
|
let interior_winding = interior.winding(geometry);
|
||||||
|
|
||||||
if exterior_winding == interior_winding {
|
if exterior_winding == interior_winding {
|
||||||
errors.push(
|
errors.push(
|
||||||
|
@ -104,6 +104,7 @@ impl ShellValidationError {
|
|||||||
surface_a: &SurfaceGeometry,
|
surface_a: &SurfaceGeometry,
|
||||||
edge_b: &Handle<HalfEdge>,
|
edge_b: &Handle<HalfEdge>,
|
||||||
surface_b: &SurfaceGeometry,
|
surface_b: &SurfaceGeometry,
|
||||||
|
geometry: &Geometry,
|
||||||
config: &ValidationConfig,
|
config: &ValidationConfig,
|
||||||
mismatches: &mut Vec<CurveCoordinateSystemMismatch>,
|
mismatches: &mut Vec<CurveCoordinateSystemMismatch>,
|
||||||
) {
|
) {
|
||||||
@ -116,10 +117,14 @@ impl ShellValidationError {
|
|||||||
let c = a + (d - a) * 2. / 3.;
|
let c = a + (d - a) * 2. / 3.;
|
||||||
|
|
||||||
for point_curve in [a, b, c, d] {
|
for point_curve in [a, b, c, d] {
|
||||||
let a_surface =
|
let a_surface = geometry
|
||||||
edge_a.path().point_from_path_coords(point_curve);
|
.of_half_edge(edge_a)
|
||||||
let b_surface =
|
.path
|
||||||
edge_b.path().point_from_path_coords(point_curve);
|
.point_from_path_coords(point_curve);
|
||||||
|
let b_surface = geometry
|
||||||
|
.of_half_edge(edge_b)
|
||||||
|
.path
|
||||||
|
.point_from_path_coords(point_curve);
|
||||||
|
|
||||||
let a_global =
|
let a_global =
|
||||||
surface_a.point_from_surface_coords(a_surface);
|
surface_a.point_from_surface_coords(a_surface);
|
||||||
@ -148,6 +153,7 @@ impl ShellValidationError {
|
|||||||
&geometry.of_surface(surface_a),
|
&geometry.of_surface(surface_a),
|
||||||
edge_b,
|
edge_b,
|
||||||
&geometry.of_surface(surface_b),
|
&geometry.of_surface(surface_b),
|
||||||
|
geometry,
|
||||||
config,
|
config,
|
||||||
&mut mismatches,
|
&mut mismatches,
|
||||||
);
|
);
|
||||||
@ -156,6 +162,7 @@ impl ShellValidationError {
|
|||||||
&geometry.of_surface(surface_b),
|
&geometry.of_surface(surface_b),
|
||||||
edge_a,
|
edge_a,
|
||||||
&geometry.of_surface(surface_a),
|
&geometry.of_surface(surface_a),
|
||||||
|
geometry,
|
||||||
config,
|
config,
|
||||||
&mut mismatches,
|
&mut mismatches,
|
||||||
);
|
);
|
||||||
@ -245,6 +252,7 @@ impl ShellValidationError {
|
|||||||
&geometry.of_surface(surface_a),
|
&geometry.of_surface(surface_a),
|
||||||
half_edge_b.clone(),
|
half_edge_b.clone(),
|
||||||
&geometry.of_surface(surface_b),
|
&geometry.of_surface(surface_b),
|
||||||
|
geometry,
|
||||||
)
|
)
|
||||||
.all(|d| d < config.distinct_min_distance)
|
.all(|d| d < config.distinct_min_distance)
|
||||||
{
|
{
|
||||||
@ -369,14 +377,19 @@ fn distances(
|
|||||||
surface_a: &SurfaceGeometry,
|
surface_a: &SurfaceGeometry,
|
||||||
edge_b: Handle<HalfEdge>,
|
edge_b: Handle<HalfEdge>,
|
||||||
surface_b: &SurfaceGeometry,
|
surface_b: &SurfaceGeometry,
|
||||||
|
geometry: &Geometry,
|
||||||
) -> impl Iterator<Item = Scalar> {
|
) -> impl Iterator<Item = Scalar> {
|
||||||
fn sample(
|
fn sample(
|
||||||
percent: f64,
|
percent: f64,
|
||||||
(edge, surface): (&Handle<HalfEdge>, &SurfaceGeometry),
|
(edge, surface): (&Handle<HalfEdge>, &SurfaceGeometry),
|
||||||
|
geometry: &Geometry,
|
||||||
) -> Point<3> {
|
) -> Point<3> {
|
||||||
let [start, end] = edge.boundary().inner;
|
let [start, end] = edge.boundary().inner;
|
||||||
let path_coords = start + (end - start) * percent;
|
let path_coords = start + (end - start) * percent;
|
||||||
let surface_coords = edge.path().point_from_path_coords(path_coords);
|
let surface_coords = geometry
|
||||||
|
.of_half_edge(edge)
|
||||||
|
.path
|
||||||
|
.point_from_path_coords(path_coords);
|
||||||
surface.point_from_surface_coords(surface_coords)
|
surface.point_from_surface_coords(surface_coords)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,8 +402,8 @@ fn distances(
|
|||||||
let mut distances = Vec::new();
|
let mut distances = Vec::new();
|
||||||
for i in 0..sample_count {
|
for i in 0..sample_count {
|
||||||
let percent = i as f64 * step;
|
let percent = i as f64 * step;
|
||||||
let sample1 = sample(percent, (&edge_a, surface_a));
|
let sample1 = sample(percent, (&edge_a, surface_a), geometry);
|
||||||
let sample2 = sample(1.0 - percent, (&edge_b, surface_b));
|
let sample2 = sample(1.0 - percent, (&edge_b, surface_b), geometry);
|
||||||
distances.push(sample1.distance_to(&sample2))
|
distances.push(sample1.distance_to(&sample2))
|
||||||
}
|
}
|
||||||
distances.into_iter()
|
distances.into_iter()
|
||||||
|
@ -13,11 +13,15 @@ impl Validate for Sketch {
|
|||||||
&self,
|
&self,
|
||||||
config: &ValidationConfig,
|
config: &ValidationConfig,
|
||||||
errors: &mut Vec<ValidationError>,
|
errors: &mut Vec<ValidationError>,
|
||||||
_: &Geometry,
|
geometry: &Geometry,
|
||||||
) {
|
) {
|
||||||
SketchValidationError::check_object_references(self, config, errors);
|
SketchValidationError::check_object_references(self, config, errors);
|
||||||
SketchValidationError::check_exterior_cycles(self, config, errors);
|
SketchValidationError::check_exterior_cycles(
|
||||||
SketchValidationError::check_interior_cycles(self, config, errors);
|
self, geometry, config, errors,
|
||||||
|
);
|
||||||
|
SketchValidationError::check_interior_cycles(
|
||||||
|
self, geometry, config, errors,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,12 +78,13 @@ impl SketchValidationError {
|
|||||||
|
|
||||||
fn check_exterior_cycles(
|
fn check_exterior_cycles(
|
||||||
sketch: &Sketch,
|
sketch: &Sketch,
|
||||||
|
geometry: &Geometry,
|
||||||
_config: &ValidationConfig,
|
_config: &ValidationConfig,
|
||||||
errors: &mut Vec<ValidationError>,
|
errors: &mut Vec<ValidationError>,
|
||||||
) {
|
) {
|
||||||
sketch.regions().iter().for_each(|region| {
|
sketch.regions().iter().for_each(|region| {
|
||||||
let cycle = region.exterior();
|
let cycle = region.exterior();
|
||||||
if cycle.winding() == Winding::Cw {
|
if cycle.winding(geometry) == Winding::Cw {
|
||||||
errors.push(ValidationError::Sketch(
|
errors.push(ValidationError::Sketch(
|
||||||
SketchValidationError::ClockwiseExteriorCycle {
|
SketchValidationError::ClockwiseExteriorCycle {
|
||||||
cycle: cycle.clone(),
|
cycle: cycle.clone(),
|
||||||
@ -91,6 +96,7 @@ impl SketchValidationError {
|
|||||||
|
|
||||||
fn check_interior_cycles(
|
fn check_interior_cycles(
|
||||||
sketch: &Sketch,
|
sketch: &Sketch,
|
||||||
|
geometry: &Geometry,
|
||||||
_config: &ValidationConfig,
|
_config: &ValidationConfig,
|
||||||
errors: &mut Vec<ValidationError>,
|
errors: &mut Vec<ValidationError>,
|
||||||
) {
|
) {
|
||||||
@ -98,7 +104,7 @@ impl SketchValidationError {
|
|||||||
region
|
region
|
||||||
.interiors()
|
.interiors()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|interior| interior.winding() == Winding::Ccw)
|
.filter(|interior| interior.winding(geometry) == Winding::Ccw)
|
||||||
.for_each(|cycle| {
|
.for_each(|cycle| {
|
||||||
errors.push(ValidationError::Sketch(
|
errors.push(ValidationError::Sketch(
|
||||||
SketchValidationError::CounterClockwiseInteriorCycle {
|
SketchValidationError::CounterClockwiseInteriorCycle {
|
||||||
|
@ -41,13 +41,16 @@ pub struct AdjacentHalfEdgesNotConnected {
|
|||||||
impl ValidationCheck<Cycle> for AdjacentHalfEdgesNotConnected {
|
impl ValidationCheck<Cycle> for AdjacentHalfEdgesNotConnected {
|
||||||
fn check(
|
fn check(
|
||||||
object: &Cycle,
|
object: &Cycle,
|
||||||
_: &Geometry,
|
geometry: &Geometry,
|
||||||
config: &ValidationConfig,
|
config: &ValidationConfig,
|
||||||
) -> impl Iterator<Item = Self> {
|
) -> impl Iterator<Item = Self> {
|
||||||
object.half_edges().pairs().filter_map(|(first, second)| {
|
object.half_edges().pairs().filter_map(|(first, second)| {
|
||||||
let end_pos_of_first_half_edge = {
|
let end_pos_of_first_half_edge = {
|
||||||
let [_, end] = first.boundary().inner;
|
let [_, end] = first.boundary().inner;
|
||||||
first.path().point_from_path_coords(end)
|
geometry
|
||||||
|
.of_half_edge(first)
|
||||||
|
.path
|
||||||
|
.point_from_path_coords(end)
|
||||||
};
|
};
|
||||||
let start_pos_of_second_half_edge = second.start_position();
|
let start_pos_of_second_half_edge = second.start_position();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user