mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-06 20:02:16 +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>
47 lines
2.0 KiB
Rust
47 lines
2.0 KiB
Rust
//! Public-safe 10/40/20/42 mm linkage, matching the reported one-degree-of-freedom sketch.
|
|
use serde_json::json;
|
|
use solidcore_record::Vec2;
|
|
use solidcraft_engine::Session;
|
|
use solidcraft_geom::prelude::*;
|
|
|
|
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
|
|
|
pub fn session() -> Result<Session> {
|
|
let mut s = Session::default();
|
|
s.execute("sketch.create", &json!({"plane":"XZ"}))?;
|
|
let x = -10.0 + (1600.0 - 400.0 + 52.0 * 52.0) / 104.0;
|
|
let y = -(1600.0_f64 - (x + 10.0) * (x + 10.0)).sqrt();
|
|
s.execute("sketch.line", &json!({"points":[[0,0],[-10,0],[x,y],[42,0]],"ids":["crank","coupler","rocker"],"infer":false}))?;
|
|
s.execute("sketch.line", &json!({"points":["crank.start","rocker.end"],"ids":["ground"],"infer":false}))?;
|
|
for (line, length) in [("crank", 10.0), ("coupler", 40.0), ("rocker", 20.0), ("ground", 42.0)] {
|
|
s.execute("sketch.dimension", &json!({"entities":[line],"value":length}))?;
|
|
}
|
|
s.execute("sketch.constraint.horizontal_vertical", &json!({"line":"ground"}))?;
|
|
Ok(s)
|
|
}
|
|
|
|
pub fn point(s: &Session, name: &str) -> Result<Vec2> {
|
|
let sk = s.doc.sketch(s.active_sketch.ok_or("missing active sketch")?)?;
|
|
sk.resolve_point(name).and_then(|p| sk.point(p)).ok_or_else(|| format!("missing point {name}").into())
|
|
}
|
|
|
|
pub fn length_error(s: &Session) -> Result<f64> {
|
|
let mut error = 0.0_f64;
|
|
for (a, b, length) in [
|
|
("crank.start", "crank.end", 10.0),
|
|
("coupler.start", "coupler.end", 40.0),
|
|
("rocker.start", "rocker.end", 20.0),
|
|
("ground.start", "ground.end", 42.0),
|
|
] {
|
|
error = error.max((point(s, a)?.dist(point(s, b)?) - length).abs());
|
|
}
|
|
error = error.max(point(s, "crank.start")?.len());
|
|
error = error.max(point(s, "ground.end")?.dist(Vec2::new(42.0, 0.0)));
|
|
Ok(error)
|
|
}
|
|
|
|
pub fn branch(s: &Session) -> Result<f64> {
|
|
let a = point(s, "crank.end")?;
|
|
Ok((point(s, "rocker.end")? - a).cross(point(s, "coupler.end")? - a).signum())
|
|
}
|