mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 02:25:55 +00:00
The refusal of sketch.project ended in "face of " with nothing after the
"of" when the reference named no body: a picked face, edge or vertex is
found by its geometry, so the body it belongs to is not in the reference.
LinkSource::describe() now drops the "of <body>" when there is no body to
name and names the kind alone ("face", "edge", "vertex", "spun
profile", "isoparametric curve"). A source that names a body keeps its
name.
Only the text changes: the command refuses exactly what it refused before.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -932,9 +932,13 @@ fn projecting_what_the_face_sketch_already_shows_adds_no_second_copy() {
|
||||
let border = shown(&mut s);
|
||||
assert_eq!(border.0, 8, "four sides and four rounded corners");
|
||||
let corner = 5.0 - 5.0 * std::f64::consts::FRAC_1_SQRT_2;
|
||||
for refs in [json!([{"face":[20,15,10]}]), json!([{"edge":[20,0,10]}]), json!([{"edge":[corner,corner,10]}])] {
|
||||
// These references name no body, so the refusal names the kind alone: it must not end in
|
||||
// "face of " with nothing after the "of" (#4929).
|
||||
let cases = [(json!([{"face":[20,15,10]}]), "face"), (json!([{"edge":[20,0,10]}]), "edge"), (json!([{"edge":[corner,corner,10]}]), "edge")];
|
||||
for (refs, what) in cases {
|
||||
let e = s.execute("sketch.project", &json!({"refs": refs})).unwrap_err().to_string();
|
||||
assert!(e.contains("already projected"), "{refs}: {e}");
|
||||
assert!(e.ends_with(&format!("already projected into this sketch: {what}")), "{refs}: {e}");
|
||||
assert_eq!(shown(&mut s), border, "{refs}");
|
||||
}
|
||||
// Something new still projects, and alongside it a reference already shown is skipped.
|
||||
|
||||
@@ -134,10 +134,10 @@ impl LinkSource {
|
||||
/// Short description for messages and the browser.
|
||||
pub fn describe(&self) -> String {
|
||||
match self {
|
||||
LinkSource::Edge { body, .. } => format!("edge of {body}"),
|
||||
LinkSource::Face { body, .. } => format!("face of {body}"),
|
||||
LinkSource::Edge { body, .. } => of_body("edge", body),
|
||||
LinkSource::Face { body, .. } => of_body("face", body),
|
||||
LinkSource::Body { body } => body.clone(),
|
||||
LinkSource::Vertex { body, .. } => format!("vertex of {body}"),
|
||||
LinkSource::Vertex { body, .. } => of_body("vertex", body),
|
||||
LinkSource::SketchCurve { curve, .. } => format!("sketch curve {curve}"),
|
||||
LinkSource::SketchPoint { point, .. } => format!("sketch point {point}"),
|
||||
LinkSource::Origin => "origin".into(),
|
||||
@@ -146,8 +146,8 @@ impl LinkSource {
|
||||
LinkSource::Plane { name } => format!("{name} plane"),
|
||||
LinkSource::OnSurface { curve, .. } => format!("{curve} on a face"),
|
||||
LinkSource::Intersection { a, b } => format!("intersection of {} and {}", a.describe(), b.describe()),
|
||||
LinkSource::Spun { body, .. } => format!("spun profile of {body}"),
|
||||
LinkSource::Iso { body, .. } => format!("isoparametric curve of {body}"),
|
||||
LinkSource::Spun { body, .. } => of_body("spun profile", body),
|
||||
LinkSource::Iso { body, .. } => of_body("isoparametric curve", body),
|
||||
LinkSource::Text { text, .. } => format!("text \"{}\"", text.chars().take(20).collect::<String>()),
|
||||
}
|
||||
}
|
||||
@@ -178,6 +178,13 @@ impl LinkSource {
|
||||
}
|
||||
}
|
||||
|
||||
/// The description of a source that names a body: "face of Body1", or the kind alone when the
|
||||
/// reference names no body (a picked face is found by its geometry, and the body it belongs
|
||||
/// to is not named in the reference).
|
||||
fn of_body(kind: &str, body: &str) -> String {
|
||||
if body.is_empty() { kind.to_string() } else { format!("{kind} of {body}") }
|
||||
}
|
||||
|
||||
/// Half length of the line a sketch axis link produces.
|
||||
pub const SKETCH_AXIS_HALF: f64 = 100.0;
|
||||
|
||||
|
||||
@@ -949,6 +949,25 @@ fn links_update_in_place_rebuild_and_break() {
|
||||
assert_eq!(back.link(&j3).unwrap().kind, LinkKind::Intersect);
|
||||
}
|
||||
|
||||
/// A reference that names no body describes itself by its kind alone: the message must not
|
||||
/// end in "face of " with nothing after the "of" (#4929).
|
||||
#[test]
|
||||
fn a_source_without_a_body_name_names_its_kind_alone() {
|
||||
use solidcraft_geom::Vec3;
|
||||
let at = Vec3::ZERO;
|
||||
for (source, expected) in [
|
||||
(LinkSource::Edge { body: String::new(), at }, "edge"),
|
||||
(LinkSource::Face { body: String::new(), at }, "face"),
|
||||
(LinkSource::Vertex { body: String::new(), at }, "vertex"),
|
||||
(LinkSource::Iso { body: String::new(), at, dir: "u".into() }, "isoparametric curve"),
|
||||
(LinkSource::Spun { body: String::new(), origin: at, dir: Vec3::X }, "spun profile"),
|
||||
] {
|
||||
assert_eq!(source.describe(), expected, "{source:?}");
|
||||
}
|
||||
// A named body keeps its name.
|
||||
assert_eq!(LinkSource::Face { body: "Body1".into(), at }.describe(), "face of Body1");
|
||||
}
|
||||
|
||||
/// Many independent constrained rectangles solve quickly (per-component work).
|
||||
#[test]
|
||||
fn large_sketch_solves_fast() {
|
||||
|
||||
Reference in New Issue
Block a user