mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-07 20:41:50 +00:00
dc38349cbf
* Kernel: the B-rep record and the native body file come from solidcore-record SolidCraft's portable B-rep record (`solidcraft_geom::brep`: brep.rs, topology, history, envelope, part, curve2) and the native body file (`solidcraft_kernel::native`: the tagged binary codec and the container) move to solidcore's `solidcore-record` crate: geometry as data, with structural validation and no maths (solidcore's docs/layers.md, stage 1). Every caller uses `solidcore_record::brep` and `solidcore_record::native`; the old copies are deleted. What computes from coordinates stays with the kernel, in geom's `brep`: - `brep::check`: the record's geometric checks (orthonormal frames, non-degenerate planes, unit revolution axes, non-singular placements). `check::validate` and `check::validate_built` are the record's validation and these together, and every caller of `Brep::validate` uses them, so what is accepted is unchanged; - `brep::label`: a surface's natural ranges (a cone's apex), `curve_interval`, `edge_curve_interval` and `form_turns`; - `brep::pcurve::eval`: a pcurve's point; - `geometry::check`, `placement::moved` and `split_edges` become functions on the record. The kernel's native module keeps the conversion between a body and its saved record (metadata.rs) and checks the decoded record's geometry. `native/analytic.rs`, which no module declared, is deleted. solidcore-record is pinned to its rev on solidcore's `layer-record` branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NvoxKMbMFSQU8tzRtoJhtT * Geometry: Vec2, Vec3, Plane and the profile types come from solidcore-record The plain data of vectors and points, sketch planes and planar profiles (`Seg2`, `Loop2`, `Region2`) moves to `solidcore-record`, with its constants and component-wise operators only (owner decision, solidcore layer split). Their geometry stays in geom as traits: `Vec2Geom`, `Vec3Geom`, `PlaneGeom`, `Seg2Geom`, `Loop2Geom`, `Region2Geom`, `Seg2ArcFit`, `Loop2ArcFit` and `Region2ArcFit`, in scope with `use solidcraft_geom::prelude::*`. Every caller names the types from `solidcore_record`; geom no longer defines or re-exports them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NvoxKMbMFSQU8tzRtoJhtT * Kernel: pin solidcore-record to solidcore main f5e8e9a29 solidcore-record is merged on solidcore main (tangency-labs/solidcore#2519); its crate there is identical to the rev pinned before but for its clippy configuration. The lock is regenerated against the merged rev. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NvoxKMbMFSQU8tzRtoJhtT --------- Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
69 lines
3.6 KiB
Rust
69 lines
3.6 KiB
Rust
//! Reduced diagnostics must preserve placement, rollback, feasibility and exact freedom results.
|
|
|
|
use solidcore_record::Vec2;
|
|
use solidcraft_sketch::{Analysis, ConstraintKind, Hold, Sketch, solve_with};
|
|
|
|
fn compare(sketch: &Sketch, hold: &Hold) {
|
|
let mut full_geometry = sketch.clone();
|
|
let mut freedom_geometry = sketch.clone();
|
|
let mut status_geometry = sketch.clone();
|
|
let mut full = solve_with(&mut full_geometry, hold, None, Analysis::Full, None);
|
|
let freedom = solve_with(&mut freedom_geometry, hold, None, Analysis::Freedom, None);
|
|
let status = solve_with(&mut status_geometry, hold, None, Analysis::StatusOnly, None);
|
|
assert_eq!(freedom_geometry, full_geometry);
|
|
assert_eq!(status_geometry, full_geometry);
|
|
assert!(freedom.redundant.is_empty(), "freedom queries must not compute redundant IDs");
|
|
full.redundant.clear();
|
|
assert_eq!(serde_json::to_value(&freedom).unwrap(), serde_json::to_value(&full).unwrap());
|
|
full.dof = 0;
|
|
full.point_determined.clear();
|
|
full.curve_determined.clear();
|
|
assert_eq!(serde_json::to_value(&status).unwrap(), serde_json::to_value(&full).unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn analysis_levels_preserve_results_on_anchored_floating_failed_and_held_geometry() {
|
|
let mut anchored = Sketch::new();
|
|
let q = anchored.add_point(Vec2::new(12.0, 3.0), None).unwrap();
|
|
let k = ConstraintKind::Distance { p: 0, q, value: 10.0 };
|
|
anchored.add_constraint(k.clone(), None).unwrap();
|
|
let redundant = anchored.add_constraint(k, None).unwrap();
|
|
let full = solve_with(&mut anchored.clone(), &Hold::default(), None, Analysis::Full, None);
|
|
assert!(full.ok());
|
|
assert_eq!(full.dof, 1);
|
|
assert!(full.redundant.contains(&redundant));
|
|
compare(&anchored, &Hold::default());
|
|
compare(&anchored, &Hold { points: vec![q], radii: vec![] });
|
|
|
|
let mut conflict = anchored.clone();
|
|
conflict.add_constraint(ConstraintKind::Distance { p: 0, q, value: 11.0 }, None).unwrap();
|
|
assert!(!solve_with(&mut conflict.clone(), &Hold::default(), None, Analysis::Full, None).ok());
|
|
compare(&conflict, &Hold::default());
|
|
|
|
let mut floating = Sketch::new();
|
|
let l = floating.add_line(Vec2::new(5.0, 5.0), Vec2::new(14.0, 6.0), None, None, None).unwrap();
|
|
floating.add_constraint(ConstraintKind::Horizontal { l }, None).unwrap();
|
|
floating.add_constraint(ConstraintKind::Horizontal { l }, None).unwrap();
|
|
floating.add_constraint(ConstraintKind::Length { l, value: 10.0 }, None).unwrap();
|
|
compare(&floating, &Hold::default());
|
|
|
|
let mut blocks = Sketch::new();
|
|
let p = blocks.add_point(Vec2::new(4.0, 1.0), None).unwrap();
|
|
let q = blocks.add_point(Vec2::new(5.0, 2.0), None).unwrap();
|
|
blocks.add_constraint(ConstraintKind::Coincident { p, q }, None).unwrap();
|
|
blocks.add_constraint(ConstraintKind::Coincident { p, q }, None).unwrap();
|
|
let c = blocks.add_circle(Vec2::new(20.0, 30.0), 5.0, None, None).unwrap();
|
|
blocks.add_constraint(ConstraintKind::Radius { c, value: 5.0 }, None).unwrap();
|
|
blocks.add_constraint(ConstraintKind::Radius { c, value: 5.0 }, None).unwrap();
|
|
blocks.add_constraint(ConstraintKind::Distance { p: 0, q: p, value: 999.0 }, None).unwrap();
|
|
blocks.constraints.last_mut().unwrap().driven = true;
|
|
compare(&blocks, &Hold::default());
|
|
compare(&blocks, &Hold { points: vec![p], radii: vec![c] });
|
|
|
|
let mut constants = Sketch::new();
|
|
let q = constants.add_point(Vec2::new(5.0, 0.0), None).unwrap();
|
|
constants.points[q].fixed = true;
|
|
constants.add_constraint(ConstraintKind::Distance { p: 0, q, value: 10.0 }, None).unwrap();
|
|
compare(&constants, &Hold::default());
|
|
}
|