mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-05 11:35:55 +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>
83 lines
3.9 KiB
Rust
83 lines
3.9 KiB
Rust
//! A board-like assembly for issue #883, the worst case for a large STEP import: every
|
|
//! component is its own product with a package body and its own pins (nothing shared).
|
|
//!
|
|
//! ```sh
|
|
//! SOLIDCRAFT_STEP_PCB_COMPONENTS=600 SOLIDCRAFT_STEP_PCB_PINS=15 \
|
|
//! cargo run --release -p solidcraft-kernel --example step_board_fixture -- board.step
|
|
//! ```
|
|
//!
|
|
//! 600 components of 15 pins give 52 MB. The defaults are 500 and 16; the path defaults to
|
|
//! `board.step`.
|
|
|
|
fn main() {
|
|
if let Err(e) = run::main() {
|
|
eprintln!("step_board_fixture: {e}");
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
|
|
mod run {
|
|
use solidcore_record::Vec3;
|
|
use solidcraft_kernel::{Body, ExportBody, ExportProduct, StepHeader, box_solid, cylinder, fillet, step_export_products};
|
|
|
|
/// A count from `SOLIDCRAFT_<name>`, or `default` when it is unset.
|
|
fn count(name: &str, default: usize) -> Result<usize, String> {
|
|
solidcraft_geom::env::var(name).map_or(Ok(default), |s| s.parse().map_err(|e| format!("SOLIDCRAFT_{name}: {e}")))
|
|
}
|
|
|
|
/// A package: a box with its vertical edges and then its top edges rounded (left sharp where
|
|
/// a round does not build).
|
|
fn package(w: f64, d: f64, h: f64) -> Result<Body, String> {
|
|
let b = box_solid(Vec3::ZERO, Vec3::new(w, d, h)).map_err(|e| e.to_string())?;
|
|
let vertical = [Vec3::new(0.0, 0.0, h / 2.0), Vec3::new(w, 0.0, h / 2.0), Vec3::new(w, d, h / 2.0), Vec3::new(0.0, d, h / 2.0)];
|
|
let top = [Vec3::new(w / 2.0, 0.0, h), Vec3::new(w, d / 2.0, h), Vec3::new(w / 2.0, d, h), Vec3::new(0.0, d / 2.0, h)];
|
|
let b = fillet(&b, &vertical, 0.3).unwrap_or(b);
|
|
Ok(fillet(&b, &top, 0.1).unwrap_or(b))
|
|
}
|
|
|
|
pub fn main() -> Result<(), String> {
|
|
let components = count("STEP_PCB_COMPONENTS", 500)?;
|
|
let pins = count("STEP_PCB_PINS", 16)?;
|
|
let path = std::env::args().nth(1).unwrap_or_else(|| "board.step".into());
|
|
let mut owned: Vec<Vec<Body>> = Vec::new();
|
|
for c in 0..components {
|
|
let w = 4.0 + (c % 7) as f64 * 0.37;
|
|
let d = 3.0 + (c % 5) as f64 * 0.29;
|
|
let mut bodies = vec![package(w, d, 1.2 + (c % 3) as f64 * 0.1)?];
|
|
for p in 0..pins {
|
|
let side = if p % 2 == 0 { -0.6 } else { d + 0.6 };
|
|
let x = 0.3 + (p / 2) as f64 * (w - 0.6) / (pins / 2).max(1) as f64 + c as f64 * 1e-4;
|
|
bodies.push(cylinder(Vec3::new(x, side, -1.5), Vec3::Z, 0.25, 2.0 + (p % 3) as f64 * 0.01).map_err(|e| e.to_string())?);
|
|
}
|
|
owned.push(bodies);
|
|
}
|
|
let mut products: Vec<ExportProduct> = owned
|
|
.iter()
|
|
.enumerate()
|
|
.map(|(c, bodies)| ExportProduct {
|
|
name: format!("U{c}"),
|
|
bodies: bodies
|
|
.iter()
|
|
.enumerate()
|
|
.map(|(k, b)| ExportBody { name: format!("U{c}_{k}"), body: b, color: Some([0.2, 0.2, 0.2]) })
|
|
.collect(),
|
|
children: Vec::new(),
|
|
})
|
|
.collect();
|
|
let side = (components as f64).sqrt().ceil() as usize;
|
|
let children = (0..components)
|
|
.map(|c| {
|
|
let (x, y) = ((c % side) as f64 * 12.0, (c / side) as f64 * 10.0);
|
|
(c, [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [x, y, 1.6, 1.0]], format!("U{c}"))
|
|
})
|
|
.collect();
|
|
products.push(ExportProduct { name: "Board".into(), bodies: Vec::new(), children });
|
|
let root = products.len() - 1;
|
|
let header = StepHeader { file_name: "board.step".into(), ..Default::default() };
|
|
let text = step_export_products(&products, root, &header).map_err(|e| e.to_string())?;
|
|
std::fs::write(&path, &text).map_err(|e| format!("{path}: {e}"))?;
|
|
println!("wrote {path}: {} bytes, {components} components", text.len());
|
|
Ok(())
|
|
}
|
|
}
|