fix: dimension line geometry and DXF rotation unit mismatch

append_linear_dimension() applied the same perp offset to both d1 and d2,
but only d2 is guaranteed to be at the definition_point level; d1 must be
projected independently onto the dimension line, otherwise non-collinear
first/second points produce a parallelogram instead of a rectangle.

Fix: compute dim_line_pos = def.dot(perp) and project each endpoint
separately so the dimension line is always parallel to axis.

Additionally, the acadrust DXF reader stores LinearDimension.rotation from
group code 50 (degrees) without converting to radians, while DWG and our
own annotation commands store it in radians.  Add a post-load fixup in
load_file() that converts the rotation to radians for DXF files so
tessellation can call cos/sin uniformly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Sonnet 4.6 committed 2026-04-26 16:57:23 +03:00
1 parent 2255dc5176
commit 19bb846c50
2 files changed
+25 -7

No files matched your search

+22 -4
View File
@@ -11,6 +11,7 @@ pub mod step;
pub mod stl;
pub mod xref;
use acadrust::entities::{Dimension, EntityType};
use acadrust::io::dwg::DwgReader;
use acadrust::{CadDocument, DwgWriter, DxfReader, DxfWriter};
use std::path::{Path, PathBuf};
@@ -60,10 +61,14 @@ pub fn load_file(path: &Path) -> Result<CadDocument, String> {
let mut reader = DwgReader::from_file(path).map_err(|e| e.to_string())?;
reader.read().map_err(|e| e.to_string())
}
"dxf" => DxfReader::from_file(path)
.map_err(|e| e.to_string())?
.read()
.map_err(|e| e.to_string()),
"dxf" => {
let mut doc = DxfReader::from_file(path)
.map_err(|e| e.to_string())?
.read()
.map_err(|e| e.to_string())?;
fix_dxf_dimension_rotations(&mut doc);
Ok(doc)
}
_ => Err(format!("Unsupported file format: .{ext}")),
}
}
@@ -162,3 +167,16 @@ pub fn save_dxf(doc: &CadDocument, path: &Path) -> Result<(), String> {
.write_to_file(path)
.map_err(|e| e.to_string())
}
// ── DXF post-load fixups ──────────────────────────────────────────────────
/// The acadrust DXF reader stores LinearDimension.rotation directly from DXF
/// group code 50, which is in degrees. DWG and our own dimension-creation code
/// store it in radians. Convert so tessellation can call cos/sin uniformly.
fn fix_dxf_dimension_rotations(doc: &mut CadDocument) {
for entity in doc.entities_mut() {
if let EntityType::Dimension(Dimension::Linear(d)) = entity {
d.rotation = d.rotation.to_radians();
}
}
}
+3 -3
View File
@@ -707,9 +707,9 @@ fn append_linear_dimension(
axis: Vec3,
) {
let perp = Vec3::new(-axis.y, axis.x, 0.0);
let offset = (def - first).dot(perp);
let d1 = first + perp * offset;
let d2 = second + perp * offset;
let dim_line_pos = def.dot(perp);
let d1 = first + perp * (dim_line_pos - first.dot(perp));
let d2 = second + perp * (dim_line_pos - second.dot(perp));
add_segment(points, first, d1);
add_segment(points, second, d2);
add_segment(points, d1, d2);