Merge pull request #738 from hannobraun/validation

Remove structural validation
This commit is contained in:
Hanno Braun 2022-06-28 19:07:38 +02:00 committed by GitHub
commit 318dc7b9f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 2 additions and 314 deletions

View File

@ -26,12 +26,10 @@
//! [`Shape`]: crate::shape::Shape //! [`Shape`]: crate::shape::Shape
mod coherence; mod coherence;
mod structural;
mod uniqueness; mod uniqueness;
pub use self::{ pub use self::{
coherence::{CoherenceIssues, CoherenceMismatch}, coherence::{CoherenceIssues, CoherenceMismatch},
structural::StructuralIssues,
uniqueness::UniquenessIssues, uniqueness::UniquenessIssues,
}; };
@ -39,10 +37,7 @@ use std::{collections::HashSet, ops::Deref};
use fj_math::Scalar; use fj_math::Scalar;
use crate::{ use crate::iter::ObjectIters;
iter::ObjectIters,
objects::{Curve, Cycle, Edge, Surface, Vertex},
};
/// Validate the given [`Shape`] /// Validate the given [`Shape`]
pub fn validate<T>( pub fn validate<T>(
@ -52,16 +47,8 @@ pub fn validate<T>(
where where
T: ObjectIters, T: ObjectIters,
{ {
let mut curves = HashSet::new();
let mut cycles = HashSet::new();
let mut edges = HashSet::new();
let mut surfaces = HashSet::new();
let mut vertices = HashSet::new(); let mut vertices = HashSet::new();
for curve in object.curve_iter() {
curves.insert(curve);
}
for vertex in object.vertex_iter() { for vertex in object.vertex_iter() {
uniqueness::validate_vertex(&vertex, &vertices)?; uniqueness::validate_vertex(&vertex, &vertices)?;
@ -70,23 +57,6 @@ where
for edge in object.edge_iter() { for edge in object.edge_iter() {
coherence::validate_edge(&edge, config.identical_max_distance)?; coherence::validate_edge(&edge, config.identical_max_distance)?;
structural::validate_edge(&edge, &curves, &vertices)?;
edges.insert(edge);
}
for cycle in object.cycle_iter() {
structural::validate_cycle(&cycle, &edges)?;
cycles.insert(cycle);
}
for surface in object.surface_iter() {
surfaces.insert(surface);
}
for face in object.face_iter() {
structural::validate_face(&face, &cycles, &surfaces)?;
} }
Ok(Validated(object)) Ok(Validated(object))
@ -157,75 +127,17 @@ pub enum ValidationError {
#[error("Geometric validation failed")] #[error("Geometric validation failed")]
Geometric, Geometric,
/// Structural validation failed
#[error("Structural validation failed")]
Structural(#[from] StructuralIssues),
/// Uniqueness validation failed /// Uniqueness validation failed
#[error("Uniqueness validation failed")] #[error("Uniqueness validation failed")]
Uniqueness(#[from] UniquenessIssues), Uniqueness(#[from] UniquenessIssues),
} }
impl ValidationError {
/// Indicate whether validation found a missing curve
pub fn missing_curve(&self, curve: &Curve<3>) -> bool {
if let Self::Structural(StructuralIssues { missing_curve, .. }) = self {
return missing_curve.as_ref() == Some(curve);
}
false
}
/// Indicate whether validation found a missing vertex
pub fn missing_vertex(&self, vertex: &Vertex) -> bool {
if let Self::Structural(StructuralIssues {
missing_vertices, ..
}) = self
{
return missing_vertices.contains(vertex);
}
false
}
/// Indicate whether validation found a missing edge
pub fn missing_edge(&self, edge: &Edge<3>) -> bool {
if let Self::Structural(StructuralIssues { missing_edges, .. }) = self {
return missing_edges.contains(edge);
}
false
}
/// Indicate whether validation found a missing surface
pub fn missing_surface(&self, surface: &Surface) -> bool {
if let Self::Structural(StructuralIssues {
missing_surface, ..
}) = self
{
return missing_surface.as_ref() == Some(surface);
}
false
}
/// Indicate whether validation found a missing cycle
pub fn missing_cycle(&self, cycle: &Cycle<3>) -> bool {
if let Self::Structural(StructuralIssues { missing_cycles, .. }) = self
{
return missing_cycles.contains(cycle);
}
false
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use fj_math::{Point, Scalar}; use fj_math::{Point, Scalar};
use crate::{ use crate::{
objects::{Curve, Cycle, Edge, Face, Surface, Vertex, VerticesOfEdge}, objects::{Curve, Edge, Vertex, VerticesOfEdge},
shape::{LocalForm, Shape}, shape::{LocalForm, Shape},
validation::{validate, ValidationConfig, ValidationError}, validation::{validate, ValidationConfig, ValidationError},
}; };
@ -270,91 +182,6 @@ mod tests {
assert!(result.is_err()); assert!(result.is_err());
} }
#[test]
fn structural_cycle() {
let mut shape = Shape::new();
// Trying to refer to edge that is not from the same shape. Should fail.
let edge = Edge::line_segment_from_points([[0., 0., 0.], [1., 0., 0.]]);
shape.insert(Cycle::new(vec![edge.clone()]));
let err =
validate(shape.clone(), &ValidationConfig::default()).unwrap_err();
assert!(err.missing_edge(&edge));
// Referring to edge that *is* from the same shape. Should work.
let edge = Edge::line_segment_from_points([[0., 0., 0.], [1., 0., 0.]]);
shape.insert(Cycle::new(vec![edge]));
}
#[test]
fn structural_edge() {
let mut shape = Shape::new();
let curve = Curve::x_axis();
let a = Vertex::from_point([1., 0., 0.]);
let b = Vertex::from_point([2., 0., 0.]);
let a = LocalForm::new(Point::from([1.]), a);
let b = LocalForm::new(Point::from([2.]), b);
// Shouldn't work. Nothing has been added to `shape`.
shape.insert(Edge {
curve: LocalForm::canonical_only(curve),
vertices: VerticesOfEdge::from_vertices([a.clone(), b.clone()]),
});
let err =
validate(shape.clone(), &ValidationConfig::default()).unwrap_err();
assert!(err.missing_curve(&curve));
assert!(err.missing_vertex(&a.canonical()));
assert!(err.missing_vertex(&b.canonical()));
let curve = Curve::x_axis();
let a = Vertex::from_point([1., 0., 0.]);
let b = Vertex::from_point([2., 0., 0.]);
let a = LocalForm::new(Point::from([1.]), a);
let b = LocalForm::new(Point::from([2.]), b);
// Everything has been added to `shape` now. Should work!
shape.insert(Edge {
curve: LocalForm::canonical_only(curve),
vertices: VerticesOfEdge::from_vertices([a, b]),
});
}
#[test]
fn structural_face() {
let mut shape = Shape::new();
let triangle = [[0., 0.], [1., 0.], [0., 1.]];
let surface = Surface::xy_plane();
let cycle = Cycle::polygon_from_points(&surface, triangle);
// Nothing has been added to `shape`. Should fail.
shape.insert(Face::new(
surface,
vec![cycle.clone()],
Vec::new(),
[255, 0, 0, 255],
));
let err =
validate(shape.clone(), &ValidationConfig::default()).unwrap_err();
assert!(err.missing_surface(&surface));
assert!(err.missing_cycle(&cycle.canonical()));
let surface = Surface::xy_plane();
let cycle = Cycle::polygon_from_points(&surface, triangle);
// Everything has been added to `shape` now. Should work!
shape.insert(Face::new(
surface,
vec![cycle],
Vec::new(),
[255, 0, 0, 255],
));
}
#[test] #[test]
fn uniqueness_vertex() -> anyhow::Result<()> { fn uniqueness_vertex() -> anyhow::Result<()> {
let mut shape = Shape::new(); let mut shape = Shape::new();

View File

@ -1,139 +0,0 @@
use std::{collections::HashSet, fmt};
use crate::objects::{Curve, Cycle, Edge, Face, Surface, Vertex};
pub fn validate_edge(
edge: &Edge<3>,
curves: &HashSet<Curve<3>>,
vertices: &HashSet<Vertex>,
) -> Result<(), StructuralIssues> {
let mut missing_curve = None;
let mut missing_vertices = HashSet::new();
if !curves.contains(&edge.curve()) {
missing_curve = Some(edge.curve.canonical());
}
for vertex in edge.vertices().into_iter().flatten() {
if !vertices.contains(&vertex) {
missing_vertices.insert(vertex);
}
}
if missing_curve.is_some() || !missing_vertices.is_empty() {
return Err(StructuralIssues {
missing_curve,
missing_vertices,
..StructuralIssues::default()
});
}
Ok(())
}
pub fn validate_cycle(
cycle: &Cycle<3>,
edges: &HashSet<Edge<3>>,
) -> Result<(), StructuralIssues> {
let mut missing_edges = HashSet::new();
for edge in cycle.edges() {
if !edges.contains(&edge) {
missing_edges.insert(edge);
}
}
if !missing_edges.is_empty() {
return Err(StructuralIssues {
missing_edges,
..StructuralIssues::default()
});
}
Ok(())
}
pub fn validate_face(
face: &Face,
cycles: &HashSet<Cycle<3>>,
surfaces: &HashSet<Surface>,
) -> Result<(), StructuralIssues> {
if let Face::Face(face) = face {
let mut missing_surface = None;
let mut missing_cycles = HashSet::new();
if !surfaces.contains(&face.surface()) {
missing_surface = Some(face.surface);
}
for cycle in face.all_cycles() {
if !cycles.contains(&cycle) {
missing_cycles.insert(cycle);
}
}
if missing_surface.is_some() || !missing_cycles.is_empty() {
return Err(StructuralIssues {
missing_surface,
missing_cycles,
..StructuralIssues::default()
});
}
}
Ok(())
}
/// Structural issues found during validation
///
/// Used by [`ValidationError`].
#[derive(Debug, Default, thiserror::Error)]
pub struct StructuralIssues {
/// Missing curve found in edge validation
pub missing_curve: Option<Curve<3>>,
/// Missing vertices found in edge validation
pub missing_vertices: HashSet<Vertex>,
/// Missing edges found in cycle validation
pub missing_edges: HashSet<Edge<3>>,
/// Missing surface found in face validation
pub missing_surface: Option<Surface>,
/// Missing cycles found in face validation
pub missing_cycles: HashSet<Cycle<3>>,
}
impl fmt::Display for StructuralIssues {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "Structural issues found:")?;
if let Some(curve) = &self.missing_curve {
writeln!(f, "- Missing curve: {:?}", curve)?;
}
if !self.missing_vertices.is_empty() {
writeln!(f, "- Missing vertices:")?;
for vertex in &self.missing_vertices {
writeln!(f, " - {:?}", vertex)?;
}
}
if !self.missing_edges.is_empty() {
writeln!(f, "- Missing edges:")?;
for edge in &self.missing_edges {
writeln!(f, " - {}", edge)?;
}
}
if let Some(surface) = &self.missing_surface {
writeln!(f, "- Missing surface: {:?}", surface)?;
}
if !self.missing_cycles.is_empty() {
writeln!(f, "- Missing cycles:")?;
for cycle in &self.missing_cycles {
writeln!(f, " - {:?}", cycle)?;
}
}
Ok(())
}
}