forked from 1b-agent/fieldcraft-upstream
Open .solidcraft designs: rebuild, persistent face names, geometry commands (#4)
* geometry: open .solidcraft designs, rebuild them and keep persistent face names open_design(bytes) reads a design (container or JSON) with solidcraft-io, rebuilds its timeline with solidcraft-doc and returns its bodies; each Shape carries SolidCraft's persistent face names by B-rep face index, so a face keeps its name through a parameter edit. sample::plate_design builds a parametric test plate in code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * engine: geometry.open, geometry.bodies and geometry.tessellate The session holds the open design (shared, restored on a failed command, journalled when it changes). Hostile-params coverage includes non-files, missing files, oversized paths and extreme tolerances against an open design. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * docs: opening SolidCraft designs in the architecture and roadmap Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm * geometry: open_design_file reads through SolidCraft's bounded file access; simplify The engine's hand-rolled capped read is replaced by open_design_file, which uses solidcraft_io::vfs::read (refuses non-regular files before opening, works on the browser's in-memory files). Drops the duplicate size check, simplifies the sample sketch and the design-change test in Session::execute. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm --------- Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
13 files changed
+6290
-19
No files matched your search
@@ -8,10 +8,19 @@
|
||||
//! be replaced without touching the rest of the workspace. Only this crate may depend on
|
||||
//! `solidcraft-*` (`cargo xtask layers` enforces it).
|
||||
//!
|
||||
//! Geometry enters two ways: shapes built in code (such as [`block`]) and SolidCraft designs
|
||||
//! opened with [`open_design`], which rebuilds the design's parametric timeline and gives its
|
||||
//! bodies with persistent face names (a boundary condition on a named face follows that face
|
||||
//! through an edit of the design).
|
||||
//!
|
||||
//! Lengths are millimetres.
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
mod design;
|
||||
pub mod sample;
|
||||
|
||||
pub use design::{Design, FeatureError, MAX_DESIGN_BYTES, open_design, open_design_file};
|
||||
use solidcraft_kernel::{Body, KernelError, guard};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, thiserror::Error)]
|
||||
@@ -38,6 +47,19 @@ impl From<KernelError> for Error {
|
||||
pub struct Shape {
|
||||
pub name: String,
|
||||
body: Body,
|
||||
/// By B-rep face index (the [`SurfaceMesh::tri_face`] tags); empty for shapes built in code.
|
||||
faces: Vec<Face>,
|
||||
}
|
||||
|
||||
/// A B-rep face's persistent identity.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Face {
|
||||
/// Stable across rebuilds of the design: named after the feature and sketch curve that made
|
||||
/// the face (`F2:side:l4`, `F2:top`, …), not after its position in the body.
|
||||
pub name: String,
|
||||
/// The name follows the history SolidCraft recorded; `false` when it was worked out from the
|
||||
/// geometry, which an upstream edit can fool.
|
||||
pub exact: bool,
|
||||
}
|
||||
|
||||
/// Mass properties and extent of a [`Shape`].
|
||||
@@ -69,10 +91,21 @@ fn xyz(v: solidcraft_geom::Vec3) -> [f64; 3] {
|
||||
pub fn block(a: [f64; 3], b: [f64; 3]) -> Result<Shape> {
|
||||
let v = |p: [f64; 3]| solidcraft_geom::Vec3 { x: p[0], y: p[1], z: p[2] };
|
||||
let body = guard("block", || solidcraft_kernel::box_solid(v(a), v(b)))?;
|
||||
Ok(Shape { name: "Block".into(), body })
|
||||
Ok(Shape { name: "Block".into(), body, faces: Vec::new() })
|
||||
}
|
||||
|
||||
impl Shape {
|
||||
/// The persistent identities of the faces, by B-rep face index (empty for shapes built in code).
|
||||
pub fn faces(&self) -> &[Face] {
|
||||
&self.faces
|
||||
}
|
||||
|
||||
/// The index of the face with this persistent name: the [`SurfaceMesh::tri_face`] tag its
|
||||
/// triangles carry.
|
||||
pub fn face_index(&self, name: &str) -> Option<u32> {
|
||||
self.faces.iter().position(|f| f.name == name).and_then(|i| u32::try_from(i).ok())
|
||||
}
|
||||
|
||||
pub fn measure(&self) -> Result<Measure> {
|
||||
let m = guard("measure", || solidcraft_kernel::measure(&self.body))?;
|
||||
Ok(Measure {
|
||||
|
||||
Reference in new issue
Block a user