Rebase fixes: one helix re-export, a closing brace lost in tests.rs

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-09 12:47:56 +00:00
1 parent 141a5fea8a
commit 9219eb5dc1
10 files changed
+37 -35

No files matched your search

+1 -2
View File
@@ -74,8 +74,7 @@ fn contact_sets_stop_a_driven_joint_at_touching() {
#[test]
fn motion_study_plays_and_exports() {
let mut s = rail();
let r =
run(&mut s, "motion.study", json!({"name": "Push", "steps": 100, "keys": [{"joint": "Rail", "points": [[0, 10], [100, -5]]}]}));
let r = run(&mut s, "motion.study", json!({"name": "Push", "steps": 100, "keys": [{"joint": "Rail", "points": [[0, 10], [100, -5]]}]}));
assert_eq!(r["keys"], 1);
run(&mut s, "motion.play", json!({"study": "Push", "step": 50}));
assert!((b_x(&s) - 12.5).abs() < 1e-6, "{}", b_x(&s));
+4 -2
View File
@@ -136,7 +136,9 @@ fn patterns_of_a_blind_hole_drill_every_copy() {
};
let r = patterned(("solid.pattern.rectangular", json!({"features": ["Hole1"], "dir1": [1, 0, 0], "count1": 3, "spacing1": "15 mm"})));
assert!((r - 3.0 * one).abs() < 1e-3 * one, "{r} vs 3 × {one}");
let c =
patterned(("solid.pattern.circular", json!({"features": ["Hole1"], "axis": {"origin": [25, 12, 0], "dir": [0, 0, 1]}, "count": 2, "angle": 360})));
let c = patterned((
"solid.pattern.circular",
json!({"features": ["Hole1"], "axis": {"origin": [25, 12, 0], "dir": [0, 0, 1]}, "count": 2, "angle": 360}),
));
assert!((c - 2.0 * one).abs() < 1e-3 * one, "{c} vs 2 × {one}");
}
+12 -4
View File
@@ -1076,16 +1076,24 @@ fn c_equal(s: &mut Session, p: &Value) -> Result<Value> {
constrain(s, p, "sketch.constraint.equal", |sk| two_curves(sk, p, "sketch.constraint.equal").map(|(a, b)| ConstraintKind::Equal { a, b }))
}
fn c_parallel(s: &mut Session, p: &Value) -> Result<Value> {
constrain(s, p, "sketch.constraint.parallel", |sk| two_curves(sk, p, "sketch.constraint.parallel").map(|(a, b)| ConstraintKind::Parallel { a, b }))
constrain(s, p, "sketch.constraint.parallel", |sk| {
two_curves(sk, p, "sketch.constraint.parallel").map(|(a, b)| ConstraintKind::Parallel { a, b })
})
}
fn c_perpendicular(s: &mut Session, p: &Value) -> Result<Value> {
constrain(s, p, "sketch.constraint.perpendicular", |sk| two_curves(sk, p, "sketch.constraint.perpendicular").map(|(a, b)| ConstraintKind::Perpendicular { a, b }))
constrain(s, p, "sketch.constraint.perpendicular", |sk| {
two_curves(sk, p, "sketch.constraint.perpendicular").map(|(a, b)| ConstraintKind::Perpendicular { a, b })
})
}
fn c_concentric(s: &mut Session, p: &Value) -> Result<Value> {
constrain(s, p, "sketch.constraint.concentric", |sk| two_curves(sk, p, "sketch.constraint.concentric").map(|(a, b)| ConstraintKind::Concentric { a, b }))
constrain(s, p, "sketch.constraint.concentric", |sk| {
two_curves(sk, p, "sketch.constraint.concentric").map(|(a, b)| ConstraintKind::Concentric { a, b })
})
}
fn c_collinear(s: &mut Session, p: &Value) -> Result<Value> {
constrain(s, p, "sketch.constraint.collinear", |sk| two_curves(sk, p, "sketch.constraint.collinear").map(|(a, b)| ConstraintKind::Collinear { a, b }))
constrain(s, p, "sketch.constraint.collinear", |sk| {
two_curves(sk, p, "sketch.constraint.collinear").map(|(a, b)| ConstraintKind::Collinear { a, b })
})
}
fn c_midpoint(s: &mut Session, p: &Value) -> Result<Value> {
let cmd = "sketch.constraint.midpoint";
@@ -54,7 +54,8 @@ fn curvature_polygon_arc_length_linear_diameter() {
// A horizontal line ending where a control-point spline starts: G2 keeps the spline's
// start straight (zero curvature) and tangent.
let l = ids(&run(&mut s, "sketch.line", json!({"points": [[-10, 0], [0, 0]], "infer": true}))["curves"])[0].clone();
let sp = ids(&run(&mut s, "sketch.spline.control_point", json!({"points": [format!("{l}.end"), [5, 2], [10, 6], [15, 15]]}))["curves"])[0].clone();
let sp =
ids(&run(&mut s, "sketch.spline.control_point", json!({"points": [format!("{l}.end"), [5, 2], [10, 6], [15, 15]]}))["curves"])[0].clone();
run(&mut s, "sketch.constraint.curvature", json!({"a": l, "b": sp}));
let sk = sketch(&s);
let pts: Vec<Vec2> = sk.curves[sk.curve_index(&sp).unwrap()].kind.point_ids().iter().map(|i| sk.point(*i).unwrap()).collect();
+5 -2
View File
@@ -348,7 +348,9 @@ fn degree_five_and_cut_free_form_profiles_extrude_exactly() {
let vol = |s: &mut Session| run(s, "inspect.measure", json!({}))["total"]["volume_mm3"].as_f64().unwrap();
// A degree-5 control spline closed by a line: one B-spline side face.
let mut s = new_sketch();
let sp = ids(&run(&mut s, "sketch.spline.control_point_5", json!({"points": [[0, 0], [4, 10], [10, 12], [16, 12], [22, 10], [26, 0]]}))["curves"])[0].clone();
let sp =
ids(&run(&mut s, "sketch.spline.control_point_5", json!({"points": [[0, 0], [4, 10], [10, 12], [16, 12], [22, 10], [26, 0]]}))["curves"])[0]
.clone();
run(&mut s, "sketch.line", json!({"points": [format!("{sp}.end"), format!("{sp}.start")]}));
let a = profiles(&s)[0];
run(&mut s, "sketch.finish", json!({}));
@@ -427,7 +429,8 @@ fn fillet_a_line_and_an_arc() {
let mut s = new_sketch();
// A line into a quarter arc meeting at a sharp corner.
let l = ids(&run(&mut s, "sketch.line", json!({"points": [[0, 0], [20, 0]]}))["curves"])[0].clone();
let a = ids(&run(&mut s, "sketch.arc.center_point", json!({"center": [30, 0], "start": format!("{l}.end"), "end": [30, -10]}))["curves"])[0].clone();
let a =
ids(&run(&mut s, "sketch.arc.center_point", json!({"center": [30, 0], "start": format!("{l}.end"), "end": [30, -10]}))["curves"])[0].clone();
let _ = a;
let f = run(&mut s, "sketch.fillet", json!({"point": format!("{l}.end"), "radius": 2}));
let arc = ids(&f["curves"])[0].clone();
+1 -5
View File
@@ -146,11 +146,7 @@ mod tests {
assert!((v - 240.0).abs() < 1e-9, "{v}");
// Stitch the patch of a box's open top back on.
run(&mut s, "solid.box", json!({"length": 10, "width": 10, "height": 10, "corner": [20, 0, 0], "body_name": "Cup"}));
run(
&mut s,
"surface.patch",
json!({"edges": [[25, 0, 10], [30, 5, 10], [25, 10, 10], [20, 5, 10]], "body": "Cup", "body_name": "Lid"}),
);
run(&mut s, "surface.patch", json!({"edges": [[25, 0, 10], [30, 5, 10], [25, 10, 10], [20, 5, 10]], "body": "Cup", "body_name": "Lid"}));
assert!(s.world_state().body("Lid").unwrap().body.is_surface());
assert!(s.execute("surface.thicken", &json!({"bodies": ["Nope"], "thickness": 1})).is_err());
assert!(s.execute("surface.trim", &json!({"body": "Sheet"})).is_err());
+1 -3
View File
@@ -69,9 +69,7 @@ fn draft(s: &mut Session, p: &Value) -> Result<Value> {
fn accessibility(s: &mut Session, p: &Value) -> Result<Value> {
let dir = match p.get("direction") {
Some(v) => {
vec3(v).and_then(Vec3::normalized).ok_or_else(|| bad("inspect.accessibility", "`direction` must be a non-zero [x,y,z]"))?
}
Some(v) => vec3(v).and_then(Vec3::normalized).ok_or_else(|| bad("inspect.accessibility", "`direction` must be a non-zero [x,y,z]"))?,
None => Vec3::Z,
};
set(s, p, SurfaceAnalysis::Access { dir })
+1 -3
View File
@@ -61,9 +61,7 @@ fn table(id: &str) -> &'static [(&'static str, K)] {
"sketch.intersect" => &[("refs", Picks)],
"sketch.project_to_surface" | "sketch.isoparametric_curve" => &[("face", Pick), ("body", Body)],
"sketch.intersection_curve" => &[("a", Picks), ("b", Picks)],
"inspect.curvature_comb" | "inspect.minimum_radius" | "inspect.isocurve" => {
&[("edges", Picks), ("faces", Picks)]
}
"inspect.curvature_comb" | "inspect.minimum_radius" | "inspect.isocurve" => &[("edges", Picks), ("faces", Picks)],
"parts.insert" | "parts.fastener" => &[("at", Pick), ("point", Make), ("direction", Dir)],
"appearance.assign" => &[("faces", Picks), ("bodies", Body), ("body", Body)],
"solid.move" => &[("bodies", Body), ("translate", Dir), ("axis", Dir), ("origin", Make)],
+10 -12
View File
@@ -299,10 +299,7 @@ fn hostile_params_never_panic() {
];
let mut internal = Vec::new();
for spec in command_specs() {
if matches!(
spec.id,
"doc.open" | "file.save" | "file.save_as" | "file.export" | "file.save_mesh" | "sketch.export_dxf"
) {
if matches!(spec.id, "doc.open" | "file.save" | "file.save_as" | "file.export" | "file.save_mesh" | "sketch.export_dxf") {
continue; // file system side effects are covered by their own tests
}
for v in hostile_values() {
@@ -405,11 +402,7 @@ fn timeline_edits_reresolve_references() {
assert_eq!(names, ["Base", "Bore", "Round"]);
assert!(rel(volume(&mut s), expect(60.0, 25.0)) < 1e-3);
// Redefine the fillet in place with a new radius; it keeps its name and position.
run(
&mut s,
"timeline.redefine",
json!({"feature": "Round", "command": "solid.fillet", "params": {"edges": [[30, 0, 25]], "radius": 4}}),
);
run(&mut s, "timeline.redefine", json!({"feature": "Round", "command": "solid.fillet", "params": {"edges": [[30, 0, 25]], "radius": 4}}));
let f4 = (16.0 - 16.0 * PI / 4.0) * 60.0;
assert!(rel(volume(&mut s), 60.0 * 30.0 * 25.0 - f4 - PI * 9.0 * 25.0) < 1e-3);
assert_eq!(s.doc.features.iter().map(|f| f.name.as_str()).collect::<Vec<_>>(), ["Base", "Bore", "Round"]);
@@ -1117,7 +1110,11 @@ fn face_extrude_follows_edits() {
let mut s = Session::default();
run(&mut s, "solid.box", json!({"length": 40, "width": 30, "height": 20}));
let before = volume(&mut s);
run(&mut s, "solid.revolve", json!({"face": [40, 15, 10], "axis": {"origin": [40, 0, 30], "dir": [0, 1, 0]}, "angle": "90 deg", "operation": "new"}));
run(
&mut s,
"solid.revolve",
json!({"face": [40, 15, 10], "axis": {"origin": [40, 0, 30], "dir": [0, 1, 0]}, "angle": "90 deg", "operation": "new"}),
);
let added = volume(&mut s) - before;
let want = 30.0 * 20.0 * 20.0 * PI / 2.0;
assert!(rel(added, want) < 1e-4, "{added} vs {want}");
@@ -1622,6 +1619,8 @@ fn hole_as_deep_as_the_plate() {
assert!(r.is_ok(), "{i} {p}: {r:?}");
assert!(volume(&mut s) < before - 1.0, "{i} {p}");
}
}
/// Appearances outlive later features: a coloured face keeps its colour after a fillet on a
/// neighbouring edge; an imported STEP's body and face colours survive a hole.
#[test]
@@ -1779,8 +1778,7 @@ fn combine_keep_tools_and_new_component() {
let mut s = Session::default();
run(&mut s, "solid.box", json!({"length": 20, "width": 20, "height": 20, "body_name": "A"}));
run(&mut s, "solid.box", json!({"corner": [10, 0, 0], "length": 20, "width": 20, "height": 20, "body_name": "B"}));
let r =
run(&mut s, "solid.combine", json!({"target": "A", "tools": ["B"], "operation": "cut", "keep_tools": true, "new_component": true}));
let r = run(&mut s, "solid.combine", json!({"target": "A", "tools": ["B"], "operation": "cut", "keep_tools": true, "new_component": true}));
let comp = r["component"].as_u64().unwrap_or(0);
assert!(comp > 0, "{r}");
let st = s.model.state();
-1
View File
@@ -51,7 +51,6 @@ pub use blend_variable::{fillet_chord, fillet_variable};
pub use body::{Body, EdgeInfo, FaceInfo, FacePaint, Paint};
pub use build::{PathSeg, box_solid, cylinder, extrude, extrude_tapered, loft, revolve, sphere, sweep, torus};
pub use delete_face::delete_faces;
pub use helix::{loft_to_point, sweep_helix};
pub use helix::{loft_to_point, sweep_helix, sweep_helix_mesh};
pub use iges_in::{MAX_IGES_BYTES, iges_import, iges_to_step};
pub use iges_out::iges_export_bodies;