Baseline dimensions were spaced by the bare style's DIMDLI × DIMSCALE, so SETVAR DIMSCALE/DIMDLI (stored as overrides since #129) had no effect and a style DIMSCALE of 0 collapsed the spacing to ~0. Use the continued dimension's style with its overrides and the effective scale (the drawing's DIMSCALE when the style's is 0), as drawing does; DIMSPACE's default spacing uses the same scale. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
7f5b39fb25
commit
179ecc1f0b
|
|
@ -322,7 +322,17 @@ fn last_linear(s: &Session) -> Option<Dimension> {
|
|||
|
||||
/// Next dimension in a chain from `prev` to a new second origin.
|
||||
fn chained(s: &Session, prev: &Dimension, next: Vec2, baseline: bool) -> EntityKind {
|
||||
let spacing = s.doc().ok().and_then(|d| d.dim_style(&prev.style).map(|st| st.baseline_spacing * st.scale.max(1e-9))).unwrap_or(0.38);
|
||||
// DIMDLI × the overall scale of the dimension being continued: its overrides (SETVAR DIM*)
|
||||
// included, and DIMSCALE 0 falling back to the drawing's DIMSCALE as when it is drawn.
|
||||
let spacing = s
|
||||
.doc()
|
||||
.ok()
|
||||
.map(|d| {
|
||||
let st = d.dim_style(&prev.style).cloned().unwrap_or_default().with_overrides(&prev.overrides);
|
||||
st.baseline_spacing * st.effective_scale(d.header.f64("DIMSCALE", 1.0))
|
||||
})
|
||||
.filter(|v| v.is_finite())
|
||||
.unwrap_or(0.38);
|
||||
let dir = match prev.kind {
|
||||
DimKind::Linear { rotation } => Vec2::from_angle(rotation),
|
||||
_ => (prev.p14.xy() - prev.p13.xy()).normalized(),
|
||||
|
|
@ -671,8 +681,11 @@ fn run_dimspace(s: &mut Session, p: &Value) -> Result<Value> {
|
|||
let d = s.doc()?;
|
||||
let Some(EntityKind::Dimension(b)) = d.entity(base).map(|e| e.kind.clone()) else { return Err(bad("dimspace", "`base` is not a dimension")) };
|
||||
let st = d.dim_style(&b.style).cloned().unwrap_or_default().with_overrides(&b.overrides);
|
||||
let spacing =
|
||||
p.get("spacing").and_then(Value::as_f64).filter(|v| v.is_finite() && *v >= 0.0).unwrap_or(st.baseline_spacing * st.scale.max(1e-9) * 2.0);
|
||||
let spacing = p
|
||||
.get("spacing")
|
||||
.and_then(Value::as_f64)
|
||||
.filter(|v| v.is_finite() && *v >= 0.0)
|
||||
.unwrap_or(st.baseline_spacing * st.effective_scale(d.header.f64("DIMSCALE", 1.0)) * 2.0);
|
||||
let dir = match b.kind {
|
||||
DimKind::Linear { rotation } => Vec2::from_angle(rotation),
|
||||
DimKind::Aligned => (b.p14.xy() - b.p13.xy()).normalized(),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
//! DIMBASELINE spaces dimension lines by DIMDLI × the overall scale of the dimension it
|
||||
//! continues: SETVAR DIM* overrides count, and DIMSCALE 0 falls back to the drawing's DIMSCALE
|
||||
//! (issue #364). DIMSPACE's default spacing uses the same scale.
|
||||
|
||||
use cadcraft_engine::Session;
|
||||
use cadcraft_engine::doc::{EntityKind, Handle};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
fn dim_line_y(s: &Session, h: &Value) -> f64 {
|
||||
let h = Handle::parse_hex(h.as_str().unwrap()).unwrap();
|
||||
match &s.doc().unwrap().entity(h).unwrap().kind {
|
||||
EntityKind::Dimension(dm) => dm.defpt.y,
|
||||
k => panic!("not a dimension: {k:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Spacing between a horizontal dimension with its line at y = 5 and the baseline one after it.
|
||||
fn baseline_spacing(setup: &[(&str, Value)]) -> f64 {
|
||||
let mut s = Session::new();
|
||||
for (cmd, p) in setup {
|
||||
s.execute(cmd, p).unwrap();
|
||||
}
|
||||
let first = s.execute("dimlinear", &json!({"p1": [0, 0], "p2": [10, 0], "at": [5, 5]})).unwrap();
|
||||
let next = s.execute("dimbaseline", &json!({"points": [[20, 0]]})).unwrap();
|
||||
dim_line_y(&s, &next["handles"][0]) - dim_line_y(&s, &first["handle"])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn baseline_spacing_follows_overrides_and_dimscale() {
|
||||
let near = |a: f64, b: f64| (a - b).abs() < 1e-9;
|
||||
let plain = baseline_spacing(&[]);
|
||||
assert!(near(plain, 0.38), "{plain}");
|
||||
let scaled = baseline_spacing(&[("setvar", json!({"name": "DIMSCALE", "value": 10}))]);
|
||||
assert!(near(scaled, 3.8), "SETVAR DIMSCALE scales the spacing: {scaled}");
|
||||
let dli = baseline_spacing(&[("setvar", json!({"name": "DIMDLI", "value": 1}))]);
|
||||
assert!(near(dli, 1.0), "SETVAR DIMDLI sets the spacing: {dli}");
|
||||
let zero = baseline_spacing(&[("dimstyle", json!({"name": "Standard", "DIMSCALE": 0}))]);
|
||||
assert!(near(zero, 0.38), "DIMSCALE 0 in model space is scale 1, not a collapsed spacing: {zero}");
|
||||
|
||||
// DIMSPACE's default spacing (twice DIMDLI) uses the same scale.
|
||||
let mut s = Session::new();
|
||||
s.execute("dimstyle", &json!({"name": "Standard", "DIMSCALE": 0})).unwrap();
|
||||
let a = s.execute("dimlinear", &json!({"p1": [0, 0], "p2": [30, 0], "at": [15, 5]})).unwrap();
|
||||
let b = s.execute("dimlinear", &json!({"p1": [0, 0], "p2": [50, 0], "at": [25, 6]})).unwrap();
|
||||
s.execute("dimspace", &json!({"base": a["handle"], "handles": [b["handle"]]})).unwrap();
|
||||
let gap = dim_line_y(&s, &b["handle"]) - dim_line_y(&s, &a["handle"]);
|
||||
assert!(near(gap, 0.76), "{gap}");
|
||||
}
|
||||
Loading…
Reference in New Issue