mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 02:25:55 +00:00
brep: Curve2 pcurve type and the truck pcurve entry point
The shared base for the schema 4 types and the truck pcurves: 2D B-spline pcurves as SMLib keeps its UV trim curves, and the truck adapter's pcurve function, not supported yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QWhMwdqJYQKQq8RCLSL1LT
This commit is contained in:
@@ -3,7 +3,9 @@
|
||||
//! Validation checks structure and resource budgets, not geometric equivalence or trust.
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
mod curve2;
|
||||
pub mod envelope;
|
||||
pub use curve2::Curve2;
|
||||
|
||||
pub const VERSION: u32 = 3;
|
||||
pub const MAX_ITEMS: usize = 1_000_000;
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
//! Pcurves: an edge in its face's surface parameters, (u, v). 2D B-splines only, as SMLib keeps
|
||||
//! its UV trim curves (`SmBSplineCurve`); 2D lines and arcs are exact as degree-1 and rational
|
||||
//! quadratic splines.
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{Budget, Result, knots, numbers, require};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
|
||||
pub enum Curve2 {
|
||||
Spline {
|
||||
knots: Vec<f64>,
|
||||
points: Vec<[f64; 2]>,
|
||||
},
|
||||
/// Homogeneous `[u*w, v*w, w]` coefficients.
|
||||
RationalSpline {
|
||||
knots: Vec<f64>,
|
||||
homogeneous: Vec<[f64; 3]>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Curve2 {
|
||||
/// The active parameter interval `[knots[degree], knots[count]]`.
|
||||
pub fn interval(&self) -> Option<[f64; 2]> {
|
||||
let (k, count) = match self {
|
||||
Curve2::Spline { knots, points } => (knots, points.len()),
|
||||
Curve2::RationalSpline { knots, homogeneous } => (knots, homogeneous.len()),
|
||||
};
|
||||
let degree = k.len().checked_sub(count.checked_add(1)?)?;
|
||||
Some([*k.get(degree)?, *k.get(count)?])
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // called by the schema 4 validator
|
||||
pub(super) fn curve2(c: &Curve2, budget: &mut Budget) -> Result<()> {
|
||||
budget.add(1)?;
|
||||
match c {
|
||||
Curve2::Spline { knots: k, points } => {
|
||||
knots(k, points.len(), budget)?;
|
||||
budget.add(points.len())?;
|
||||
numbers(points.iter().flatten().copied())
|
||||
}
|
||||
Curve2::RationalSpline { knots: k, homogeneous } => {
|
||||
knots(k, homogeneous.len(), budget)?;
|
||||
budget.add(homogeneous.len())?;
|
||||
numbers(homogeneous.iter().flatten().copied())?;
|
||||
require(homogeneous.iter().all(|p| p[2] >= 1e-12), "non-positive rational weight")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn pcurves_validate_and_round_trip() {
|
||||
let line = Curve2::Spline { knots: vec![0., 0., 1., 1.], points: vec![[0., 0.], [1., 2.]] };
|
||||
curve2(&line, &mut Budget(0)).unwrap();
|
||||
assert_eq!(line.interval(), Some([0., 1.]));
|
||||
assert_eq!(serde_json::from_str::<Curve2>(&serde_json::to_string(&line).unwrap()).unwrap(), line);
|
||||
let bad = Curve2::RationalSpline { knots: vec![0., 0., 1., 1.], homogeneous: vec![[0., 0., 1.], [1., 2., 0.]] };
|
||||
assert!(curve2(&bad, &mut Budget(0)).is_err());
|
||||
let nan = Curve2::Spline { knots: vec![0., 0., 1., 1.], points: vec![[0., f64::NAN], [1., 2.]] };
|
||||
assert!(curve2(&nan, &mut Budget(0)).is_err());
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ use std::sync::Arc;
|
||||
mod adapter;
|
||||
mod binary;
|
||||
mod metadata;
|
||||
#[allow(dead_code)]
|
||||
mod pcurve;
|
||||
mod preview;
|
||||
pub use preview::native_preview_mesh;
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
//! Pcurves for truck faces, which keep none: each edge use's curve in its face's surface
|
||||
//! parameters, on the parameter of the edge's own curve (as the adapter writes it), running in
|
||||
//! that curve's direction. Exact where the edge lies on its surface in closed form, otherwise a
|
||||
//! 2D B-spline fitted within the tolerance.
|
||||
use super::Result;
|
||||
use solidcraft_geom::brep as b;
|
||||
use truck_modeling as mt;
|
||||
|
||||
/// For each of `face`'s boundary wires, in order, the pcurve of each of its edges, in order, in
|
||||
/// the (u, v) of the face's surface as truck evaluates it (`ParametricSurface::subs`), within
|
||||
/// `tolerance` mm when lifted onto the surface.
|
||||
pub(super) fn pcurves(face: &mt::Face, tolerance: f64) -> Result<Vec<Vec<b::Curve2>>> {
|
||||
let _ = (face, tolerance);
|
||||
Err(crate::KernelError::Failed("not supported yet: pcurves of truck faces".into()))
|
||||
}
|
||||
Reference in New Issue
Block a user