Rename SolveCraft to SolidCraft everywhere, with compatibility shims (#389)

* WIP deep rename (not for push)

* WIP2

* WIP3

* WIP4 wxs fix

* rustfmt

* Rename the remaining identifiers in merged crash-report code

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
bherbruckandClaude Opus 5.5 authored and GitHub committed 2026-10-12 17:17:01 -04:00
1 parent 27415e4dd7
commit 296683229d
464 files changed
+3408 -2956

No files matched your search

+3 -3
View File
@@ -1,8 +1,8 @@
# Vendored third-party crates
Copies of third-party crates that SolveCraft builds with local fixes, wired in with
Copies of third-party crates that SolidCraft builds with local fixes, wired in with
`[patch.crates-io]` in the workspace `Cargo.toml`. They keep their own licence; changed lines
are marked `SolveCraft:` in the source.
are marked `SolidCraft:` in the source.
## truck-shapeops 0.4.0 (Apache-2.0, © RICOS Co. Ltd., https://github.com/ricosjp/truck)
@@ -31,7 +31,7 @@ Changes:
## truck-stepio 0.3.0 (Apache-2.0, © RICOS Co. Ltd., https://github.com/ricosjp/truck)
Only the writer (`out`) is used; SolveCraft reads STEP with its own reader.
Only the writer (`out`) is used; SolidCraft reads STEP with its own reader.
Changes:
- `out/geometry.rs`: an `INTERSECTION_CURVE`'s second surface was written at the first
+1 -1
View File
@@ -1,6 +1,6 @@
//! Unofficial third-party cgmath extensions for calculate eigenvalues, operator norms and Iwasawa decomposition.
// SolveCraft: compiler warnings no longer fail the build.
// SolidCraft: compiler warnings no longer fail the build.
#![deny(clippy::all, rust_2018_idioms)]
#![warn(
missing_docs,
+2 -2
View File
@@ -92,7 +92,7 @@ pub fn pre_solve_cubic<F: BaseFloat>(p: F, q: F) -> [Complex<F>; 3] {
res.iter_mut().for_each(|x| {
let mut f = *x * *x * *x + *x * p + q;
let mut f_prime = *x * *x * three + p;
// SolveCraft: at most 100 steps. Near a double root (the eigenvalues of a
// SolidCraft: at most 100 steps. Near a double root (the eigenvalues of a
// translation matrix) the iteration can cycle forever without meeting the tolerance.
let mut steps = 0;
while f.norm() > eps_2 * f_prime.norm() && steps < 100 {
@@ -193,7 +193,7 @@ pub fn pre_solve_quartic<F: BaseFloat>(p: F, q: F, r: F) -> [Complex<F>; 4] {
res.iter_mut().for_each(|x| {
let mut f = *x * *x * *x * *x + *x * *x * p + *x * q + r;
let mut f_prime = *x * *x * *x * four + *x * p * two + q;
// SolveCraft: at most 100 steps. Near a double root (the eigenvalues of a
// SolidCraft: at most 100 steps. Near a double root (the eigenvalues of a
// translation matrix) the iteration can cycle forever without meeting the tolerance.
let mut steps = 0;
while f.norm() > eps_2 * f_prime.norm() && steps < 100 {
+1 -1
View File
@@ -1,6 +1,6 @@
//! Mesh algorigthms, include tessellations of the shape.
// SolveCraft: compiler warnings no longer fail the build.
// SolidCraft: compiler warnings no longer fail the build.
#![deny(clippy::all, rust_2018_idioms)]
#![warn(
missing_docs,
+13 -13
View File
@@ -20,7 +20,7 @@ pub(super) trait SP<S>:
}
impl<S, F> SP<S> for F where F: Fn(&S, Point3, Option<(f64, f64)>) -> Option<(f64, f64)> + Parallelizable {}
/// SolveCraft: a parameter inside the surface's bounded, non-periodic ranges.
/// SolidCraft: a parameter inside the surface's bounded, non-periodic ranges.
fn in_domain<S: ParametricSurface>(surface: &S, (u, v): (f64, f64)) -> bool {
let ok = |x: f64, range: Option<(f64, f64)>, period: Option<f64>| {
x.is_finite()
@@ -36,7 +36,7 @@ fn in_domain<S: ParametricSurface>(surface: &S, (u, v): (f64, f64)) -> bool {
ok(u, ur, surface.u_period()) && ok(v, vr, surface.v_period())
}
/// SolveCraft: the parameter clamped into the surface's bounded, non-periodic ranges.
/// SolidCraft: the parameter clamped into the surface's bounded, non-periodic ranges.
fn clamped<S: ParametricSurface>(surface: &S, (u, v): (f64, f64)) -> (f64, f64) {
let c = |x: f64, range: Option<(f64, f64)>, period: Option<f64>| match (range, period) {
(Some((a, b)), None) => x.clamp(a.min(b), a.max(b)),
@@ -46,7 +46,7 @@ fn clamped<S: ParametricSurface>(surface: &S, (u, v): (f64, f64)) -> (f64, f64)
(c(u, ur, surface.u_period()), c(v, vr, surface.v_period()))
}
/// SolveCraft: a nearest-parameter search can run off a B-spline's domain and extrapolate to
/// SolidCraft: a nearest-parameter search can run off a B-spline's domain and extrapolate to
/// thousands of parameter units (meshing that grid never finishes). Outside the nominal domain
/// keep the result only if it is really closer to the point than the clamped one (planes report
/// a nominal unit range but extend for ever).
@@ -260,7 +260,7 @@ fn shell_create_polygon<S: PreMeshableSurface>(
let boundary = PolyBoundary::new(preboundary?, &surface, tol);
Some(trimming_tessellation(surface, &boundary, tol, cap))
})();
// SolveCraft: faces with seam edges (a loop running along an edge both ways, as STEP
// SolidCraft: faces with seam edges (a loop running along an edge both ways, as STEP
// writes cylinders) are valid here; `debug_new` asserts simple loops in debug builds.
let mut new_face = Face::new_unchecked(wires, polygon);
if !orientation {
@@ -344,7 +344,7 @@ fn get_mindiff(u: f64, u0: f64, up: f64) -> f64 {
(-2..=2).map(closure).min_by(abs_diff(u0)).unwrap()
}
/// SolveCraft: the second field holds each loop's parameter box, so `include` skips loops that
/// SolidCraft: the second field holds each loop's parameter box, so `include` skips loops that
/// cannot hold the point (a face with hundreds of holes meshed in quadratic time).
#[derive(Debug, Default, Clone)]
struct PolyBoundary(Vec<Vec<Point2>>, Vec<BoundingBox<Point2>>);
@@ -495,7 +495,7 @@ impl PolyBoundary {
fn include(&self, c: Point2) -> bool {
let t = 2.0 * std::f64::consts::PI * HashGen::hash1(c);
let r = Vector2::new(f64::cos(t), f64::sin(t));
// SolveCraft: a closed loop whose box is clear of `c` winds zero times around it, and
// SolidCraft: a closed loop whose box is clear of `c` winds zero times around it, and
// no crossing with it lies within the tolerance of `c`: it changes nothing here.
let margin = 2.0 * TOLERANCE;
let near = |bdb: &BoundingBox<Point2>| {
@@ -642,19 +642,19 @@ fn insert_surface(
});
}
/// SolveCraft: most grid points a face gets (keeps hostile or huge faces bounded).
/// SolidCraft: most grid points a face gets (keeps hostile or huge faces bounded).
pub(super) const MAX_GRID: usize = 150_000;
/// SolveCraft: grid points shared by all faces of one shell; many faces get fewer each.
/// SolidCraft: grid points shared by all faces of one shell; many faces get fewer each.
pub(super) const SHELL_GRID_BUDGET: usize = 10_000_000;
/// SolveCraft: most points on one edge's polyline.
/// SolidCraft: most points on one edge's polyline.
const MAX_EDGE_POINTS: usize = 20_000;
/// SolveCraft: the grid budget of each face of a shell with `faces` faces.
/// SolidCraft: the grid budget of each face of a shell with `faces` faces.
pub(super) fn face_cap(faces: usize) -> usize {
(SHELL_GRID_BUDGET / faces.max(1)).clamp(2_000, MAX_GRID)
}
/// SolveCraft: truck's curve division, bounded: at most `MAX_EDGE_POINTS` points and a
/// SolidCraft: truck's curve division, bounded: at most `MAX_EDGE_POINTS` points and a
/// bisection depth of 24; a midpoint that does not evaluate (NaN) counts as flat (truck's
/// version recursed on it 100 levels deep, which never finishes).
fn bounded_polyline<C: PolylineableCurve>(curve: &C, range: (f64, f64), tol: f64) -> PolylineCurve {
@@ -679,7 +679,7 @@ fn bounded_polyline<C: PolylineableCurve>(curve: &C, range: (f64, f64), tol: f64
PolylineCurve(out)
}
/// SolveCraft: truck's surface division, bounded: stops refining when the grid would exceed
/// SolidCraft: truck's surface division, bounded: stops refining when the grid would exceed
/// `cap` points or after 24 rounds; cells that do not evaluate (NaN) are not refined.
fn bounded_surface_division<S: PreMeshableSurface>(surface: &S, (ur, vr): ((f64, f64), (f64, f64)), tol: f64, cap: usize) -> (Vec<f64>, Vec<f64>) {
let (mut udiv, mut vdiv) = (vec![ur.0, ur.1], vec![vr.0, vr.1]);
@@ -739,7 +739,7 @@ fn bounded_surface_division<S: PreMeshableSurface>(surface: &S, (ur, vr): ((f64,
(udiv, vdiv)
}
/// SolveCraft: refine the parameter grid so its cells are not much longer in one direction than
/// SolidCraft: refine the parameter grid so its cells are not much longer in one direction than
/// the other. A ruled surface (cylinder, cone) needs no division along its rulings, and the
/// triangles that then join a trimming loop to the far ends of the grid cut through the
/// surface (a cylinder with a hole lost volume this way).
+3 -3
View File
@@ -1,6 +1,6 @@
//! Crate for operationg shapes. Provides boolean operations to Solid, and shape healing for importing shapes from other CAD systems.
// SolveCraft: warnings are not errors in the vendored copy (newer compilers flag more).
// SolidCraft: warnings are not errors in the vendored copy (newer compilers flag more).
#![allow(dead_code)]
#![warn(clippy::all, rust_2018_idioms)]
#![warn(
@@ -14,7 +14,7 @@
unused_qualifications
)]
/// SolveCraft: report where an operation gives up (set `SHAPEOPS_TRACE`).
/// SolidCraft: report where an operation gives up (set `SHAPEOPS_TRACE`).
macro_rules! tr {
($e:expr, $tag:expr) => {
match $e {
@@ -37,7 +37,7 @@ pub use transversal::{
and, and_with_history, or, or_with_history, EdgeOrigin, FaceIndex, FaceOrigin, History, ShapeOpsCurve,
ShapeOpsSurface,
};
// SolveCraft: exercised by kernel regressions in the workspace CI.
// SolidCraft: exercised by kernel regressions in the workspace CI.
#[doc(hidden)]
pub use transversal::IntersectionCurveWithParameters;
mod alternative;
+2 -2
View File
@@ -21,7 +21,7 @@ where
{
let surface = face.surface();
let pt = wire.front_vertex().unwrap().point();
// SolveCraft: intersection-curve points lie on the surface only within the tolerance; fall
// SolidCraft: intersection-curve points lie on the surface only within the tolerance; fall
// back to the nearest parameter when the exact search fails.
let p: Point2 = surface
.search_parameter(pt, None, 100)
@@ -87,7 +87,7 @@ where
}
negative_wires.into_iter().try_for_each(|chunk| {
let pt = chunk.poly.front();
// SolveCraft: the innermost piece that holds the loop (nested intersection loops, such
// SolidCraft: the innermost piece that holds the loop (nested intersection loops, such
// as both walls of a tube crossing one face), never the loop's own twin.
let hole = -chunk.poly.area();
let op = crate::tr!(
@@ -26,7 +26,7 @@ impl<P, C, S> FacesClassification<P, C, S> {
pub fn and_or_unknown(&self) -> [Shell<P, C, S>; 3] {
let [mut and, mut or, mut unknown] = <[Shell<P, C, S>; 3]>::default();
for face in &self.shell {
// SolveCraft: no panics (wasm can't catch them).
// SolidCraft: no panics (wasm can't catch them).
match self.status.get(&face.id()) {
Some(ShapesOpStatus::And) => and.push(face.clone()),
Some(ShapesOpStatus::Or) => or.push(face.clone()),
+1 -1
View File
@@ -1,4 +1,4 @@
//! SolveCraft: where each face and edge of a boolean's result came from, recorded by the code
//! SolidCraft: where each face and edge of a boolean's result came from, recorded by the code
//! that builds them (never reconstructed from geometry).
//!
//! Topology ids are addresses of shared data, so they identify a face or an edge only while it
+6 -6
View File
@@ -55,7 +55,7 @@ fn process_one_pair_of_shells<C: ShapeOpsCurve<S>, S: ShapeOpsSurface>(
lineage: &mut Lineage<C, S>,
) -> Option<[Shell<Point3, C, S>; 2]> {
nonpositive_tolerance!(tol);
// SolveCraft: robust meshing (boundaries from earlier operations lie on surfaces only
// SolidCraft: robust meshing (boundaries from earlier operations lie on surfaces only
// within tolerance).
let poly_shell0 = shell0.robust_triangulation(tol);
let poly_shell1 = shell1.robust_triangulation(tol);
@@ -70,7 +70,7 @@ fn process_one_pair_of_shells<C: ShapeOpsCurve<S>, S: ShapeOpsSurface>(
cls1.integrate_by_component();
let [mut and0, mut or0, unknown0] = cls0.and_or_unknown();
unknown0.into_iter().try_for_each(|face| {
// SolveCraft: no panics (wasm can't catch them).
// SolidCraft: no panics (wasm can't catch them).
let pt = face.boundaries().first()?.vertex_iter().next()?.point();
let dir = hash::take_one_unit(pt);
let count = poly_shell1.iter().try_fold(0, |count, face| {
@@ -86,7 +86,7 @@ fn process_one_pair_of_shells<C: ShapeOpsCurve<S>, S: ShapeOpsSurface>(
})?;
let [mut and1, mut or1, unknown1] = cls1.and_or_unknown();
unknown1.into_iter().try_for_each(|face| {
// SolveCraft: no panics (wasm can't catch them).
// SolidCraft: no panics (wasm can't catch them).
let pt = face.boundaries().first()?.vertex_iter().next()?.point();
let dir = hash::take_one_unit(pt);
let count = poly_shell0.iter().try_fold(0, |count, face| {
@@ -123,7 +123,7 @@ pub fn or<C: ShapeOpsCurve<S>, S: ShapeOpsSurface>(
boolean(solid0, solid1, tol, |[_, or]| or).map(|(solid, _)| solid)
}
/// SolveCraft: AND operation between two solids, with where each face and edge of the result
/// SolidCraft: AND operation between two solids, with where each face and edge of the result
/// came from (operand 0 is `solid0`, operand 1 is `solid1`): the same result as [`and`], and
/// its history, `None` when a face or edge of it was not recorded. The operands must not share
/// faces or edges.
@@ -135,7 +135,7 @@ pub fn and_with_history<C: ShapeOpsCurve<S>, S: ShapeOpsSurface>(
boolean(solid0, solid1, tol, |[and, _]| and)
}
/// SolveCraft: OR operation between two solids, with where each face and edge of the result
/// SolidCraft: OR operation between two solids, with where each face and edge of the result
/// came from (operand 0 is `solid0`, operand 1 is `solid1`): the same result as [`or`], and
/// its history, `None` when a face or edge of it was not recorded. The operands must not share
/// faces or edges.
@@ -170,7 +170,7 @@ fn boolean<C: ShapeOpsCurve<S>, S: ShapeOpsSurface>(
Some((solid, history))
}
// SolveCraft: truck's connected components come out in hash order of face addresses, so the
// SolidCraft: truck's connected components come out in hash order of face addresses, so the
// result's face order changed from run to run. Keep the shell's own order instead.
fn components_in_order<C, S>(shell: &Shell<Point3, C, S>) -> Vec<Shell<Point3, C, S>> {
let pos: rustc_hash::FxHashMap<_, usize> = shell.face_iter().enumerate().map(|(i, f)| (f.id(), i)).collect();
+1 -1
View File
@@ -20,7 +20,7 @@ fn punched_cube() {
obj::write(&poly, file).unwrap();
}
// SolveCraft: boolean history.
// SolidCraft: boolean history.
use crate::{EdgeOrigin, FaceIndex, History};
@@ -19,14 +19,14 @@ impl<S> From<IntersectionCurveWithParameters<S>> for IntersectionCurve<PolylineC
impl<S> IntersectionCurveWithParameters<S>
where S: ParametricSurface3D + SearchNearestParameter<D2, Point = Point3>
{
/// SolveCraft: construct a projected curve, returning `None` for degenerate input.
/// SolidCraft: construct a projected curve, returning `None` for degenerate input.
pub fn try_new(
surface0: S,
surface1: S,
poly: PolylineCurve<Point3>,
tol: f64,
) -> Option<Self> {
// SolveCraft: a point contact is not a curve. Reject it before indexing the
// SolidCraft: a point contact is not a curve. Reject it before indexing the
// endpoints, and reject collapsed/non-finite segments before normalizing.
if poly.len() < 2 || poly.windows(2).any(|p| {
let length2 = (p[1] - p[0]).magnitude2();
+1 -1
View File
@@ -173,7 +173,7 @@ impl<P: Copy, C: Clone> Loops<P, C> {
})
}
// SolveCraft: `replaced(old, new)` is told of every edge rebuilt on the new vertex.
// SolidCraft: `replaced(old, new)` is told of every edge rebuilt on the new vertex.
fn change_vertex(
&mut self,
old_vertex: &Vertex<P>,
+1 -1
View File
@@ -3,7 +3,7 @@ mod faces_classification;
mod history;
mod integrate;
mod intersection_curve;
// SolveCraft: expose the constructor for workspace regression coverage of the vendored fix.
// SolidCraft: expose the constructor for workspace regression coverage of the vendored fix.
#[doc(hidden)]
pub use intersection_curve::IntersectionCurveWithParameters;
mod loops_store;
+1 -1
View File
@@ -6,7 +6,7 @@
//! Shapes created by set operations cannot be output yet.
//! Input will come further down the road.
// SolveCraft: compiler warnings no longer fail the build.
// SolidCraft: compiler warnings no longer fail the build.
#![deny(clippy::all, rust_2018_idioms)]
#![warn(
missing_docs,
+3 -3
View File
@@ -364,7 +364,7 @@ where
))?;
self.leader().fmt(curve_idx, f)?;
self.surface0().fmt(surface0_idx, f)?;
// SolveCraft: the second surface was written at the first one's index (duplicate ids).
// SolidCraft: the second surface was written at the first one's index (duplicate ids).
self.surface1().fmt(surface1_idx, f)
}
}
@@ -773,7 +773,7 @@ impl<C: StepLength> StepLength for Processor<RevolutedCurve<C>, Matrix4> {
fn step_length(&self) -> usize { self.entity().step_length() }
}
// SolveCraft: the written surface revolves the transformed profile about the transformed
// SolidCraft: the written surface revolves the transformed profile about the transformed
// axis; a mirroring transform reverses the turn, and with it the normal (was `!orientation`,
// right only without mirroring). The STEP normal is the opposite of truck's (see above).
impl<C> StepSurface for Processor<RevolutedCurve<C>, Matrix4> {
@@ -803,7 +803,7 @@ impl StepLength for ModelingSurface {
}
}
// SolveCraft: was the default (`true`), which dropped an inverted revolution's orientation.
// SolidCraft: was the default (`true`), which dropped an inverted revolution's orientation.
impl StepSurface for ModelingSurface {
fn same_sense(&self) -> bool {
match self {