fix(sketch): constraint glyphs move off dimension values
A horizontal or vertical glyph sat beside its line on a fixed side, so a dimension placed on that side drew its value box on top of the glyph. A glyph that would overlap a dimension's value now goes to the other side of its line, or steps along it when both sides are taken. The scenario `glyphs` check also fails when a glyph overlaps a dimension value; constraint_glyphs_clear_of_dimensions covers it. Fixes #175 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
1aedbf6631
commit
cb5144b6e2
3 files changed
+36
-8
No files matched your search
@@ -535,7 +535,7 @@ fn approx(got: f64, want: &Value, what: &str) -> Result<(), String> {
|
||||
/// Checks: `bodies` (count), `volume` / `area` (total, number or [value, rel tol]), `faces`,
|
||||
/// `features` (count), `errors` (timeline features in error, default 0), `dialog` (null: none
|
||||
/// open, or a word its kind must contain), `tool` (null or command id), `sketching` (bool),
|
||||
/// `selection` (count), `glyphs` ({constraint id: count}, none overlapping), `param` ({name: value}), `sketch_status` (solved|…), `dof`, `query`
|
||||
/// `selection` (count), `glyphs` ({constraint id: count}, none overlapping one another or a dimension value), `param` ({name: value}), `sketch_status` (solved|…), `dof`, `query`
|
||||
/// ({command, params?, path, value}: a command's result).
|
||||
pub fn check(h: &mut Harness, e: &Value) -> Result<(), String> {
|
||||
let doc = h.call("document.inspect", json!({"measure": true}))["result"].clone();
|
||||
@@ -695,6 +695,10 @@ pub fn check(h: &mut Harness, e: &Value) -> Result<(), String> {
|
||||
if let Some((b, _)) = g.iter().skip(i + 1).find(|(_, q)| q.distance(*p) < 14.0) {
|
||||
return Err(format!("glyphs of {a} and {b} overlap at {p:?}"));
|
||||
}
|
||||
let r = egui::Rect::from_center_size(*p, egui::vec2(14.0, 14.0));
|
||||
if let Some((d, _)) = crate::dim_view::text_rects().into_iter().find(|(_, t)| t.intersects(r)) {
|
||||
return Err(format!("glyph of {a} at {p:?} overlaps the value of dimension {d}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
"sketching" => {
|
||||
|
||||
@@ -1000,7 +1000,13 @@ fn glyphs(app: &SolveApp, painter: &egui::Painter, proj: &Proj, hover: Option<Po
|
||||
let tk = crate::theme::Tokens::get();
|
||||
let picked = PICKED.with(|p| p.borrow().clone());
|
||||
// Where each glyph goes: beside its entity (to its left, away from the line), every entity
|
||||
// of a two-entity constraint getting one; glyphs that would overlap step along.
|
||||
// of a two-entity constraint getting one; glyphs that would overlap step along. A glyph
|
||||
// that would sit on a dimension's value goes to the other side of its line.
|
||||
let dim_texts: Vec<egui::Rect> = crate::dim_view::text_rects().into_iter().map(|(_, r)| r.expand(2.0)).collect();
|
||||
let on_dim = |p: Pos2| {
|
||||
let r = egui::Rect::from_center_size(p, egui::vec2(GLYPH, GLYPH));
|
||||
dim_texts.iter().any(|d| d.intersects(r))
|
||||
};
|
||||
let mut placed: Vec<(String, Pos2, Pos2)> = Vec::new();
|
||||
for c in &ss.sketch.constraints {
|
||||
if c.kind.is_dimension() {
|
||||
@@ -1017,13 +1023,22 @@ fn glyphs(app: &SolveApp, painter: &egui::Painter, proj: &Proj, hover: Option<Po
|
||||
None => egui::vec2(0.7, -0.7),
|
||||
};
|
||||
let step = if dir.is_some() { egui::vec2(side.y, -side.x) } else { egui::vec2(1.0, 0.0) };
|
||||
let mut sp = base + side * (GLYPH * 0.9);
|
||||
for _ in 0..12 {
|
||||
if !placed.iter().any(|(_, q, _)| q.distance(sp) < GLYPH + 1.0) {
|
||||
break;
|
||||
let free = |sp: Pos2| !placed.iter().any(|(_, q, _)| q.distance(sp) < GLYPH + 1.0);
|
||||
let start = |s: egui::Vec2| base + s * (GLYPH * 0.9);
|
||||
let side = if on_dim(start(side)) && !on_dim(start(-side)) { -side } else { side };
|
||||
// Step along until clear of other glyphs, preferring a spot clear of dimension
|
||||
// values too.
|
||||
let settle = |avoid_dims: bool| {
|
||||
let mut sp = start(side);
|
||||
for _ in 0..12 {
|
||||
if free(sp) && !(avoid_dims && on_dim(sp)) {
|
||||
return Some(sp);
|
||||
}
|
||||
sp += step * (GLYPH + 2.0);
|
||||
}
|
||||
sp += step * (GLYPH + 2.0);
|
||||
}
|
||||
None
|
||||
};
|
||||
let sp = settle(true).or_else(|| settle(false)).unwrap_or_else(|| start(side) + step * (12.0 * (GLYPH + 2.0)));
|
||||
placed.push((c.id.clone(), sp, base));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
[
|
||||
{"call": "engine.execute", "params": {"command": "sketch.create", "params": {"plane": "XY"}}},
|
||||
{"call": "engine.execute", "params": {"command": "sketch.rectangle.two_point", "params": {"p0": [0, 0], "p1": [10, 10]}}},
|
||||
{"call": "engine.execute", "params": {"command": "sketch.dimension", "params": {"entities": ["l1"], "value": 10, "text_at": [5, -0.3]}}},
|
||||
{"call": "engine.execute", "params": {"command": "sketch.dimension", "params": {"entities": ["l2"], "value": 10, "text_at": [10.3, 5]}}},
|
||||
{"call": "ui.view", "params": {"view": "top"}},
|
||||
{"call": "ui.view", "params": {"view": "fit"}},
|
||||
{"expect": {"glyphs": {"k1": 1, "k2": 1, "k3": 1, "k4": 1}}}
|
||||
]
|
||||
Reference in new issue
Block a user