feat(properties): fill placeholder rows from acadrust fields + doc lookups

Bump acadrust to a46cb8b (spline knot parameterization + mtext line-space
style now stored) and populate rows the builders left blank:

Entity-local: spline Knot Parameterization + closed-spline Area (shoelace),
mtext Line space style, hatch Spacing (pattern-line offset), leader Text
offset (annotation offset), region Area + Perimeter (wire-loop approx).

Doc-dependent (resolved in app/properties.rs where the document is
reachable): insert Block Unit + Unit factor (block record units vs
INSUNITS), underlay Name + Path (definition object), leader Text style /
vertical placement / overall scale and tolerance Text style (dimension
style), multileader Max points + segment angles (mleader style).

Rows needing an annotation-scale / sheet-set subsystem or an internal
PDF/DWF layer parser are intentionally left blank.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-07-03 00:05:58 +03:00
commit f50ad0dde4
7 changed files with 258 additions and 8 deletions

View file

@ -52,6 +52,39 @@ fn translate_wires(wires: &mut Vec<acadrust::entities::Wire>, d: Vec3) {
}
}
/// Approximate a region's enclosed area and boundary perimeter from its
/// wireframe loops. Perimeter is the total edge length across every wire.
/// Area accumulates the Newell area vector of each loop (opposite-wound
/// holes subtract) and halves its magnitude — exact for a single planar
/// loop, approximate for multi-loop or curved regions. Returns zeros when
/// there is nothing to measure.
fn region_area_perimeter(wires: &[acadrust::entities::Wire]) -> (f64, f64) {
let mut perimeter = 0.0;
let (mut nx, mut ny, mut nz) = (0.0, 0.0, 0.0);
for wire in wires {
let pts = &wire.points;
if pts.len() < 2 {
continue;
}
for seg in pts.windows(2) {
let dx = seg[1].x - seg[0].x;
let dy = seg[1].y - seg[0].y;
let dz = seg[1].z - seg[0].z;
perimeter += (dx * dx + dy * dy + dz * dz).sqrt();
}
let n = pts.len();
for i in 0..n {
let a = &pts[i];
let b = &pts[(i + 1) % n];
nx += (a.y - b.y) * (a.z + b.z);
ny += (a.z - b.z) * (a.x + b.x);
nz += (a.x - b.x) * (a.y + b.y);
}
}
let area = 0.5 * (nx * nx + ny * ny + nz * nz).sqrt();
(area, perimeter)
}
// ── Solid3D ───────────────────────────────────────────────────────────────────
impl Grippable for Solid3D {
@ -132,11 +165,12 @@ impl Grippable for Region {
impl PropertyEditable for Region {
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
let (area, perimeter) = region_area_perimeter(&self.wires);
vec![PropSection {
title: "Geometry".into(),
props: vec![
ro("Area", "rgn_area", String::new()),
ro("Perimeter", "rgn_perimeter", String::new()),
ro("Area", "rgn_area", format!("{area:.4}")),
ro("Perimeter", "rgn_perimeter", format!("{perimeter:.4}")),
],
}]
}