mirror of
https://github.com/storytold/cadcraft.git
synced 2026-11-10 12:30:16 -06:00
A DIMENSION moved by an older AutoCAD keeps its *D block contents where they were and the move in DXF group 12, and is drawn translated by the insertion point. Group 12 was never read into Dimension, so the block rendered at its pre-move position and the extents reached there too. Read group 12 into a new Dimension::insertion_point, draw the block translated by it, move its bounds with it in the extents, test the block's text where it draws, and write group 12 back whenever the block written is the one read from the file. Regenerated geometry (edits drop the block link) sits at its definition points, so no offset is kept or written for it. Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com>
86 lines
3.7 KiB
Rust
86 lines
3.7 KiB
Rust
//! Angular extension lines stay with their legs when the arc is on the other side, and the
|
|
//! DIMCEN centre mark is drawn only when the dimension line is outside the circle (issue #374).
|
|
|
|
use cadcraft_doc::{DimKind, DimStyle, Dimension};
|
|
use cadcraft_geom::{Vec2, Vec3};
|
|
use cadcraft_render::{LineRole, dimension_geometry};
|
|
|
|
fn dim(kind: DimKind) -> Dimension {
|
|
Dimension {
|
|
kind,
|
|
defpt: Vec3::ZERO,
|
|
text_mid: Vec3::ZERO,
|
|
p13: Vec3::ZERO,
|
|
p14: Vec3::ZERO,
|
|
p15: Vec3::ZERO,
|
|
p16: Vec3::ZERO,
|
|
text: String::new(),
|
|
style: "Standard".into(),
|
|
measurement: 0.0,
|
|
text_rotation: 0.0,
|
|
user_text_pos: false,
|
|
block: None,
|
|
overrides: Default::default(),
|
|
assoc: Vec::new(),
|
|
marks: Default::default(),
|
|
insertion_point: Vec3::ZERO,
|
|
}
|
|
}
|
|
|
|
fn ext_lines(d: &Dimension, st: &DimStyle) -> Vec<Vec<Vec2>> {
|
|
dimension_geometry(d, st, 1.0).lines_of(LineRole::Ext).cloned().collect()
|
|
}
|
|
|
|
fn near(a: Vec2, b: Vec2) -> bool {
|
|
a.dist(b) < 1e-9
|
|
}
|
|
|
|
#[test]
|
|
fn angular_extension_lines_follow_their_legs_when_the_arc_is_swapped() {
|
|
// Vertex 0,0; leg 1 to 10,0 (reaches past the arc), leg 2 to 0,2 (short of it); the arc
|
|
// location -3,-3 is outside the 0°→90° sweep, so the 270° arc runs from leg 2 to leg 1.
|
|
let mut a = dim(DimKind::Angular3P);
|
|
a.p13 = Vec3::new(10.0, 0.0, 0.0);
|
|
a.p14 = Vec3::new(0.0, 2.0, 0.0);
|
|
a.defpt = Vec3::new(-3.0, -3.0, 0.0);
|
|
let st = DimStyle::default();
|
|
assert_eq!(dimension_geometry(&a, &st, 1.0).value, "270°");
|
|
let r = 18f64.sqrt();
|
|
// Only leg 2 needs an extension line: from DIMEXO past 0,2 to DIMEXE past the arc.
|
|
let lines = ext_lines(&a, &st);
|
|
assert_eq!(lines.len(), 1, "{lines:?}");
|
|
assert!(near(lines[0][0], Vec2::new(0.0, 2.0 + st.ext_offset)) && near(lines[0][1], Vec2::new(0.0, r + st.ext_extend)), "{lines:?}");
|
|
// DIMSE1 belongs to leg 1 (which has none), DIMSE2 to leg 2.
|
|
assert_eq!(ext_lines(&a, &DimStyle { suppress_ext1: true, ..DimStyle::default() }), lines);
|
|
assert!(ext_lines(&a, &DimStyle { suppress_ext2: true, ..DimStyle::default() }).is_empty());
|
|
// DIMBLK1 sits on leg 1's end of the arc.
|
|
let dot1 = DimStyle { arrow_block1: "_DOT".into(), arrow_block2: "_NONE".into(), ..DimStyle::default() };
|
|
let g = dimension_geometry(&a, &dot1, 1.0);
|
|
assert!(!g.fills.is_empty() && g.fills.iter().flatten().all(|p| p.dist(Vec2::new(r, 0.0)) < st.arrow_size), "{:?}", g.fills.first());
|
|
}
|
|
|
|
#[test]
|
|
fn centre_mark_only_when_the_dimension_line_is_outside_the_circle() {
|
|
let st = DimStyle::default();
|
|
// Radius led out to its text: the mark is drawn.
|
|
let mut rad = dim(DimKind::Radius);
|
|
rad.p15 = Vec3::new(5.0, 0.0, 0.0);
|
|
assert_eq!(ext_lines(&rad, &st).len(), 2, "centre mark of an outside radius dimension");
|
|
// Text moved inside the circle: the dimension line is inside, no mark.
|
|
rad.user_text_pos = true;
|
|
rad.text_mid = Vec3::new(2.0, 0.0, 0.0);
|
|
assert!(ext_lines(&rad, &st).is_empty());
|
|
// A diameter with DIMTOFL runs through the centre: no mark, nor centre lines (negative
|
|
// DIMCEN). Without DIMTOFL it is only led out to its text, like a radius, and has the mark.
|
|
let mut dia = dim(DimKind::Diameter);
|
|
dia.defpt = Vec3::new(-5.0, 0.0, 0.0);
|
|
dia.p15 = Vec3::new(5.0, 0.0, 0.0);
|
|
let tofl = DimStyle { force_line_inside: true, ..DimStyle::default() };
|
|
assert!(ext_lines(&dia, &tofl).is_empty());
|
|
assert!(ext_lines(&dia, &DimStyle { center_mark: -0.5, ..tofl.clone() }).is_empty());
|
|
assert_eq!(ext_lines(&dia, &st).len(), 2);
|
|
// A radius with DIMTOFL runs in from the centre: no mark.
|
|
rad.user_text_pos = false;
|
|
assert!(ext_lines(&rad, &tofl).is_empty());
|
|
}
|