use brepkit_topology::Topology;
use brepkit_topology::edge::{EdgeCurve, EdgeId};
use brepkit_topology::face::{FaceId, FaceSurface};
use brepkit_topology::vertex::VertexId;
use super::checks::{CheckId, EntityRef, Severity, ValidationIssue};
use crate::CheckError;
pub fn check_vertex_on_curve(
topo: &Topology,
vertex_id: VertexId,
edge_id: EdgeId,
tolerance: f64,
) -> Result<Vec<ValidationIssue>, CheckError> {
let vertex = topo.vertex(vertex_id)?;
let edge = topo.edge(edge_id)?;
let pos = vertex.point();
let deviation = match edge.curve() {
EdgeCurve::Line => return Ok(vec![]),
EdgeCurve::Circle(c) => {
let t_closest = c.project(pos);
(pos - c.evaluate(t_closest)).length()
}
EdgeCurve::Ellipse(e) => {
let t_closest = e.project(pos);
(pos - e.evaluate(t_closest)).length()
}
EdgeCurve::NurbsCurve(nc) => {
let (t0, t1) = nc.domain();
let d_start = (pos - nc.evaluate(t0)).length();
let d_end = (pos - nc.evaluate(t1)).length();
d_start.min(d_end)
}
};
if deviation > tolerance {
return Ok(vec![ValidationIssue {
check: CheckId::VertexOnCurve,
severity: Severity::Warning,
entity: EntityRef::Vertex(vertex_id),
description: format!(
"vertex deviates {deviation:.2e} from edge curve (tolerance {tolerance:.2e})"
),
deviation: Some(deviation),
}]);
}
Ok(vec![])
}
pub fn check_vertex_on_surface(
topo: &Topology,
vertex_id: VertexId,
face_id: FaceId,
tolerance: f64,
) -> Result<Vec<ValidationIssue>, CheckError> {
let vertex = topo.vertex(vertex_id)?;
let pos = vertex.point();
let face = topo.face(face_id)?;
let deviation = match face.surface() {
FaceSurface::Plane { normal, d } => {
let pv = brepkit_math::vec::Vec3::new(pos.x(), pos.y(), pos.z());
(normal.dot(pv) - d).abs()
}
FaceSurface::Cylinder(s) => {
let (u, v) = s.project_point(pos);
(pos - s.evaluate(u, v)).length()
}
FaceSurface::Cone(s) => {
let (u, v) = s.project_point(pos);
(pos - s.evaluate(u, v)).length()
}
FaceSurface::Sphere(s) => {
let (u, v) = s.project_point(pos);
(pos - s.evaluate(u, v)).length()
}
FaceSurface::Torus(s) => {
let (u, v) = s.project_point(pos);
(pos - s.evaluate(u, v)).length()
}
FaceSurface::Nurbs(s) => {
match brepkit_math::nurbs::projection::project_point_to_surface(s, pos, tolerance) {
Ok(proj) => proj.distance,
Err(_) => return Ok(vec![]),
}
}
};
if deviation > tolerance {
return Ok(vec![ValidationIssue {
check: CheckId::VertexOnSurface,
severity: Severity::Warning,
entity: EntityRef::Vertex(vertex_id),
description: format!(
"vertex deviates {deviation:.2e} from face surface (tolerance {tolerance:.2e})"
),
deviation: Some(deviation),
}]);
}
Ok(vec![])
}