feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
// Underlay entity — PDF/DWF/DGN reference.
|
|
|
|
|
//
|
|
|
|
|
// Render: clip boundary polygon (or cross at insertion if no boundary).
|
|
|
|
|
// Grips: insertion point + clip boundary vertices.
|
|
|
|
|
// Props: position, scales, rotation, contrast, fade, flags.
|
|
|
|
|
|
|
|
|
|
use acadrust::entities::{Underlay, UnderlayDisplayFlags};
|
|
|
|
|
|
|
|
|
|
use crate::command::EntityTransform;
|
refactor(grip): square-only marker set + oriented stretch handles
Phase 1 of bringing the grip vocabulary in line with the standard
CAD convention: drop the per-position-type shape encoding (Diamond
for translate, Circle for parameter) and use a plain square for
every endpoint / vertex / centre grip. The behavioural midpoint vs
vertex distinction stays — it lives on `GripDef::is_midpoint` and
drives `Translate` vs `Absolute` in the grip-edit dispatcher — only
the marker shape collapses.
- `GripShape` keeps `Square`, `Rectangle`, `Triangle`. Diamond /
Circle are gone.
- `GripDef` gains `dir: Option<[f32; 2]>` — a world-XY direction
vector consumed by `Rectangle` to orient the box along its
segment.
- `entities::common` exposes `square_grip`, `center_grip` (same
square marker, flagged as translate), `rectangle_grip(id, world,
dir)` for oriented mid-segment handles, and a kept-for-Phase-2
`triangle_grip`.
- `overlay::GripMarker` / `grips_to_screen[_paper]` thread `dir`
through to the canvas painter; the Rectangle path rotates the
box around the grip centre using the world-XY direction (flipping
the sin for screen-Y).
Every existing `diamond_grip(id, w)` call becomes `center_grip(id,
w)` — the visual change is square-replacing-diamond at line
midpoints / arc midpoints / circle centres / ellipse centres /
viewport / hatch loop centroids / dimension grips / image corners /
multileader / ray / underlay / ole2frame / solid3d.
`LwPolyline` grows a stretch handle on every segment (straight or
arc), drawn as the new oriented rectangle. The grip-edit path
translates both segment endpoints for straight segments and
adjusts the arc bulge from the new midpoint for arc segments.
2026-05-29 02:07:34 +03:00
|
|
|
use crate::entities::common::{center_grip, edit_prop as edit, ro_prop as ro, square_grip};
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
use crate::entities::traits::{Grippable, PropertyEditable, Transformable, TruckConvertible};
|
2026-06-16 11:33:46 +03:00
|
|
|
use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
|
|
|
|
|
use crate::scene::model::object::{GripApply, GripDef, PropSection};
|
|
|
|
|
use crate::scene::model::wire_model::SnapHint;
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
|
|
|
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
|
|
|
|
2026-05-12 23:47:40 +03:00
|
|
|
fn v3(v: &acadrust::types::Vector3) -> [f64; 3] {
|
|
|
|
|
[v.x, v.y, v.z]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn v3f32(v: &acadrust::types::Vector3) -> [f32; 3] {
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
[v.x as f32, v.y as f32, v.z as f32]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Small cross marker at the insertion point (used when no clip boundary).
|
2026-05-12 23:47:40 +03:00
|
|
|
fn cross_wire(origin: [f64; 3], size: f64) -> Vec<[f64; 3]> {
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
let [ox, oy, oz] = origin;
|
|
|
|
|
vec![
|
|
|
|
|
[ox - size, oy, oz],
|
|
|
|
|
[ox + size, oy, oz],
|
2026-05-12 23:47:40 +03:00
|
|
|
[f64::NAN; 3],
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
[ox, oy - size, oz],
|
|
|
|
|
[ox, oy + size, oz],
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── TruckConvertible ──────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
impl TruckConvertible for Underlay {
|
|
|
|
|
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
|
|
|
|
|
let origin = v3(&self.insertion_point);
|
refactor(snap): producers emit f64 snap points (world_offset removal P3)
TruckEntity.snap_pts is now DVec3 and every entity producer builds snap
candidates straight from the acadrust f64 coordinates instead of casting
to f32 first (text, mtext, arc, circle, ellipse, point, shape, solid,
mline, mtext, attribute, tolerance, table, underlay, ole2frame, mesh,
multileader, dimension, block-cache). offset_snap_pts stays f64
throughout. Still offset-relative (inert) — but snap precision is no
longer capped at ~0.5 m by an early f32 cast, which fixes a latent
UTM-scale snap error and sets up the absolute-coordinate switch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 22:10:29 +03:00
|
|
|
let _origin_f32 = v3f32(&self.insertion_point);
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
|
|
|
|
|
if !self.clip_boundary_vertices.is_empty() {
|
|
|
|
|
// Draw clip boundary polygon + close it.
|
|
|
|
|
let world_verts = self.world_clip_boundary();
|
2026-06-11 00:04:37 +03:00
|
|
|
let mut pts: Vec<[f64; 3]> = world_verts.iter().map(|v| [v.x, v.y, v.z]).collect();
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
// Close polygon.
|
|
|
|
|
if let Some(&first) = pts.first() {
|
|
|
|
|
pts.push(first);
|
|
|
|
|
}
|
|
|
|
|
// Insertion grip.
|
2026-05-12 23:47:40 +03:00
|
|
|
let key: Vec<[f64; 3]> = pts.clone();
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
Some(TruckEntity {
|
|
|
|
|
object: TruckObject::Lines(pts),
|
refactor(snap): producers emit f64 snap points (world_offset removal P3)
TruckEntity.snap_pts is now DVec3 and every entity producer builds snap
candidates straight from the acadrust f64 coordinates instead of casting
to f32 first (text, mtext, arc, circle, ellipse, point, shape, solid,
mline, mtext, attribute, tolerance, table, underlay, ole2frame, mesh,
multileader, dimension, block-cache). offset_snap_pts stays f64
throughout. Still offset-relative (inert) — but snap precision is no
longer capped at ~0.5 m by an early f32 cast, which fixes a latent
UTM-scale snap error and sets up the absolute-coordinate switch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 22:10:29 +03:00
|
|
|
snap_pts: vec![(glam::DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z), SnapHint::Node)],
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
tangent_geoms: vec![],
|
|
|
|
|
key_vertices: key,
|
2026-05-06 23:24:26 +03:00
|
|
|
fill_tris: vec![],
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
// No clip boundary: draw a cross at insertion point.
|
|
|
|
|
let pts = cross_wire(origin, 1.0);
|
|
|
|
|
Some(TruckEntity {
|
|
|
|
|
object: TruckObject::Lines(pts),
|
refactor(snap): producers emit f64 snap points (world_offset removal P3)
TruckEntity.snap_pts is now DVec3 and every entity producer builds snap
candidates straight from the acadrust f64 coordinates instead of casting
to f32 first (text, mtext, arc, circle, ellipse, point, shape, solid,
mline, mtext, attribute, tolerance, table, underlay, ole2frame, mesh,
multileader, dimension, block-cache). offset_snap_pts stays f64
throughout. Still offset-relative (inert) — but snap precision is no
longer capped at ~0.5 m by an early f32 cast, which fixes a latent
UTM-scale snap error and sets up the absolute-coordinate switch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 22:10:29 +03:00
|
|
|
snap_pts: vec![(glam::DVec3::new(self.insertion_point.x, self.insertion_point.y, self.insertion_point.z), SnapHint::Node)],
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
tangent_geoms: vec![],
|
|
|
|
|
key_vertices: vec![origin],
|
2026-05-06 23:24:26 +03:00
|
|
|
fill_tris: vec![],
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Grippable ─────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
impl Grippable for Underlay {
|
|
|
|
|
fn grips(&self) -> Vec<GripDef> {
|
2026-06-11 00:04:37 +03:00
|
|
|
let origin = glam::DVec3::new(
|
|
|
|
|
self.insertion_point.x,
|
|
|
|
|
self.insertion_point.y,
|
|
|
|
|
self.insertion_point.z,
|
|
|
|
|
);
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
let mut grips = vec![square_grip(0, origin)];
|
|
|
|
|
|
|
|
|
|
if !self.clip_boundary_vertices.is_empty() {
|
|
|
|
|
let world_verts = self.world_clip_boundary();
|
|
|
|
|
for (i, v) in world_verts.iter().enumerate() {
|
2026-06-11 00:04:37 +03:00
|
|
|
grips.push(center_grip(i + 1, glam::DVec3::new(v.x, v.y, v.z)));
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
grips
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn apply_grip(&mut self, grip_id: usize, apply: GripApply) {
|
|
|
|
|
if grip_id == 0 {
|
|
|
|
|
// Insertion point grip.
|
|
|
|
|
match apply {
|
|
|
|
|
GripApply::Translate(d) => {
|
|
|
|
|
self.insertion_point.x += d.x as f64;
|
|
|
|
|
self.insertion_point.y += d.y as f64;
|
|
|
|
|
self.insertion_point.z += d.z as f64;
|
|
|
|
|
}
|
|
|
|
|
GripApply::Absolute(p) => {
|
|
|
|
|
self.insertion_point.x = p.x as f64;
|
|
|
|
|
self.insertion_point.y = p.y as f64;
|
|
|
|
|
self.insertion_point.z = p.z as f64;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Clip boundary vertex grip (grip_id = vertex_index + 1).
|
|
|
|
|
let idx = grip_id - 1;
|
|
|
|
|
if idx >= self.clip_boundary_vertices.len() {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// Clip boundary vertices are in local (underlay) space.
|
|
|
|
|
// We need to invert the world transform to apply the grip.
|
|
|
|
|
let cos_r = self.rotation.cos();
|
|
|
|
|
let sin_r = self.rotation.sin();
|
|
|
|
|
let new_world = match apply {
|
|
|
|
|
GripApply::Absolute(p) => {
|
|
|
|
|
// world → local: translate, un-rotate, un-scale
|
|
|
|
|
let wx = p.x as f64 - self.insertion_point.x;
|
|
|
|
|
let wy = p.y as f64 - self.insertion_point.y;
|
|
|
|
|
let lx = (wx * cos_r + wy * sin_r) / self.x_scale.max(1e-10);
|
|
|
|
|
let ly = (-wx * sin_r + wy * cos_r) / self.y_scale.max(1e-10);
|
|
|
|
|
(lx, ly)
|
|
|
|
|
}
|
|
|
|
|
GripApply::Translate(d) => {
|
|
|
|
|
let v = &self.clip_boundary_vertices[idx];
|
|
|
|
|
let wx = d.x as f64 / self.x_scale.max(1e-10);
|
|
|
|
|
let wy = d.y as f64 / self.y_scale.max(1e-10);
|
|
|
|
|
let lx = wx * cos_r + wy * sin_r;
|
|
|
|
|
let ly = -wx * sin_r + wy * cos_r;
|
|
|
|
|
(v.x + lx, v.y + ly)
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
self.clip_boundary_vertices[idx].x = new_world.0;
|
|
|
|
|
self.clip_boundary_vertices[idx].y = new_world.1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── PropertyEditable ──────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
impl PropertyEditable for Underlay {
|
2026-07-02 22:46:19 +03:00
|
|
|
fn geometry_properties(&self, _text_style_names: &[String]) -> Vec<PropSection> {
|
feat(properties): conform entity property groups to PROPERTIES.md
Rewrite each entity's property builder to the per-entity group/row spec:
the correct sections (Geometry, Misc, Text, Pattern, Lines & Arrows, Leaders,
Block, …) with the spec's rows and real computed values — Diameter,
Circumference, Area, Delta X/Y/Z, Angle, Total angle, Arc length, Radius ratio,
etc. — plus apply routing for the editable rows.
Covers ~26 entities (Line, Circle, Arc, Point, Ellipse, Spline, polylines,
Ray/XLine, Insert, Text, MText, Hatch, Leader, MultiLeader, Tolerance, Solid,
Solid3D/Region/Body, meshes, MLine, Raster/Wipeout, Underlay, Table, Viewport,
Attribute, OLE). The 3D Visualization/Material group and the full Dimension
spec are deferred (they need document access for material/dimstyle name
resolution). Rows whose data is not in the pinned acadrust revision are shown
as empty placeholders, to be filled when the dependency is bumped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 23:03:18 +03:00
|
|
|
let yes_no = |b: bool| if b { "Yes" } else { "No" };
|
|
|
|
|
|
|
|
|
|
// Width / Height derived from the world-space clip boundary bounds
|
|
|
|
|
// (the only in-entity source of the placed footprint size).
|
|
|
|
|
let (width, height) = if self.clip_boundary_vertices.is_empty() {
|
|
|
|
|
(0.0_f64, 0.0_f64)
|
|
|
|
|
} else {
|
|
|
|
|
let verts = self.world_clip_boundary();
|
|
|
|
|
let mut min_x = f64::INFINITY;
|
|
|
|
|
let mut min_y = f64::INFINITY;
|
|
|
|
|
let mut max_x = f64::NEG_INFINITY;
|
|
|
|
|
let mut max_y = f64::NEG_INFINITY;
|
|
|
|
|
for v in &verts {
|
|
|
|
|
min_x = min_x.min(v.x);
|
|
|
|
|
min_y = min_y.min(v.y);
|
|
|
|
|
max_x = max_x.max(v.x);
|
|
|
|
|
max_y = max_y.max(v.y);
|
|
|
|
|
}
|
|
|
|
|
(max_x - min_x, max_y - min_y)
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
};
|
feat(properties): conform entity property groups to PROPERTIES.md
Rewrite each entity's property builder to the per-entity group/row spec:
the correct sections (Geometry, Misc, Text, Pattern, Lines & Arrows, Leaders,
Block, …) with the spec's rows and real computed values — Diameter,
Circumference, Area, Delta X/Y/Z, Angle, Total angle, Arc length, Radius ratio,
etc. — plus apply routing for the editable rows.
Covers ~26 entities (Line, Circle, Arc, Point, Ellipse, Spline, polylines,
Ray/XLine, Insert, Text, MText, Hatch, Leader, MultiLeader, Tolerance, Solid,
Solid3D/Region/Body, meshes, MLine, Raster/Wipeout, Underlay, Table, Viewport,
Attribute, OLE). The 3D Visualization/Material group and the full Dimension
spec are deferred (they need document access for material/dimstyle name
resolution). Rows whose data is not in the pinned acadrust revision are shown
as empty placeholders, to be filled when the dependency is bumped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 23:03:18 +03:00
|
|
|
|
|
|
|
|
let show = self.flags.contains(UnderlayDisplayFlags::ON);
|
|
|
|
|
let clipping = self.flags.contains(UnderlayDisplayFlags::CLIPPING);
|
|
|
|
|
let monochrome = self.flags.contains(UnderlayDisplayFlags::MONOCHROME);
|
|
|
|
|
let adjust_bg = self.flags.contains(UnderlayDisplayFlags::ADJUST_FOR_BACKGROUND);
|
|
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
PropSection {
|
|
|
|
|
title: "Geometry".into(),
|
|
|
|
|
props: vec![
|
|
|
|
|
edit("Position X", "ul_ix", self.insertion_point.x),
|
|
|
|
|
edit("Position Y", "ul_iy", self.insertion_point.y),
|
|
|
|
|
edit("Position Z", "ul_iz", self.insertion_point.z),
|
|
|
|
|
edit("Scale X", "ul_sx", self.x_scale),
|
|
|
|
|
edit("Scale Y", "ul_sy", self.y_scale),
|
|
|
|
|
edit("Scale Z", "ul_sz", self.z_scale),
|
|
|
|
|
ro("Width", "ul_width", format!("{:.4}", width)),
|
|
|
|
|
ro("Height", "ul_height", format!("{:.4}", height)),
|
|
|
|
|
edit("Rotation", "ul_rot", self.rotation.to_degrees()),
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
PropSection {
|
|
|
|
|
title: "Underlay Adjust".into(),
|
|
|
|
|
props: vec![
|
|
|
|
|
edit("Contrast", "ul_contrast", self.contrast as f64),
|
|
|
|
|
edit("Fade", "ul_fade", self.fade as f64),
|
|
|
|
|
ro("Monochrome", "ul_mono", yes_no(monochrome)),
|
|
|
|
|
ro(
|
|
|
|
|
"Adjust Colors for Background",
|
|
|
|
|
"ul_adjust_bg",
|
|
|
|
|
yes_no(adjust_bg),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
PropSection {
|
|
|
|
|
title: "Misc".into(),
|
|
|
|
|
props: vec![
|
|
|
|
|
// Underlay name/path/layers live on the separate
|
|
|
|
|
// UnderlayDefinition object, not reachable from the entity.
|
|
|
|
|
ro("Underlay name", "ul_name", String::new()),
|
|
|
|
|
ro("Underlay path", "ul_path", String::new()),
|
|
|
|
|
ro("Show underlay", "ul_on", yes_no(show)),
|
|
|
|
|
ro("Clipping", "ul_clip", yes_no(clipping)),
|
|
|
|
|
ro("Show clipped", "ul_clip_inverted", yes_no(self.clip_inverted)),
|
|
|
|
|
ro("Underlay layers", "ul_layers", String::new()),
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
]
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn apply_geom_prop(&mut self, field: &str, value: &str) {
|
|
|
|
|
if let Ok(v) = value.trim().parse::<f64>() {
|
|
|
|
|
match field {
|
|
|
|
|
"ul_ix" => self.insertion_point.x = v,
|
|
|
|
|
"ul_iy" => self.insertion_point.y = v,
|
|
|
|
|
"ul_iz" => self.insertion_point.z = v,
|
|
|
|
|
"ul_sx" => self.x_scale = v,
|
|
|
|
|
"ul_sy" => self.y_scale = v,
|
|
|
|
|
"ul_sz" => self.z_scale = v,
|
|
|
|
|
"ul_rot" => self.rotation = v.to_radians(),
|
|
|
|
|
"ul_contrast" => self.set_contrast(v.clamp(0.0, 100.0) as u8),
|
|
|
|
|
"ul_fade" => self.set_fade(v.clamp(0.0, 80.0) as u8),
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Transformable ─────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
impl Transformable for Underlay {
|
|
|
|
|
fn apply_transform(&mut self, t: &EntityTransform) {
|
2026-06-16 11:33:46 +03:00
|
|
|
use crate::scene::view::transform::reflect_xy_point;
|
feat: add Underlay entity support (PDF/DWF/DGN)
- New src/entities/underlay.rs: TruckConvertible (clip boundary polygon
or cross marker), Grippable (insertion + boundary vertex grips),
PropertyEditable (position, scale, rotation, contrast, fade, flags),
Transformable (translate, mirror, scale, rotate)
- Wire EntityType::Underlay into all four match arms in traits.rs
- UNDERLAY command: FADE/CONTRAST/ON/OFF/CLIP ON|OFF/MONO ON|OFF
subcommands to edit selected underlay entities
- Entity type name map entry for UNDERLAY
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:43:44 +03:00
|
|
|
match t {
|
|
|
|
|
EntityTransform::Translate(d) => {
|
|
|
|
|
self.insertion_point.x += d.x as f64;
|
|
|
|
|
self.insertion_point.y += d.y as f64;
|
|
|
|
|
self.insertion_point.z += d.z as f64;
|
|
|
|
|
}
|
|
|
|
|
EntityTransform::Mirror { p1, p2 } => {
|
|
|
|
|
reflect_xy_point(
|
|
|
|
|
&mut self.insertion_point.x,
|
|
|
|
|
&mut self.insertion_point.y,
|
|
|
|
|
*p1,
|
|
|
|
|
*p2,
|
|
|
|
|
);
|
|
|
|
|
// Reflect rotation angle.
|
|
|
|
|
let dx = (p2.x - p1.x) as f64;
|
|
|
|
|
let dy = (p2.y - p1.y) as f64;
|
|
|
|
|
let axis_angle = dy.atan2(dx);
|
|
|
|
|
self.rotation = 2.0 * axis_angle - self.rotation;
|
|
|
|
|
}
|
|
|
|
|
EntityTransform::Scale { center, factor } => {
|
|
|
|
|
let bx = center.x as f64;
|
|
|
|
|
let by = center.y as f64;
|
|
|
|
|
let bz = center.z as f64;
|
|
|
|
|
let f = *factor as f64;
|
|
|
|
|
self.insertion_point.x = bx + (self.insertion_point.x - bx) * f;
|
|
|
|
|
self.insertion_point.y = by + (self.insertion_point.y - by) * f;
|
|
|
|
|
self.insertion_point.z = bz + (self.insertion_point.z - bz) * f;
|
|
|
|
|
self.x_scale *= f;
|
|
|
|
|
self.y_scale *= f;
|
|
|
|
|
self.z_scale *= f;
|
|
|
|
|
}
|
|
|
|
|
EntityTransform::Rotate { center, angle_rad } => {
|
|
|
|
|
let bx = center.x as f64;
|
|
|
|
|
let by = center.y as f64;
|
|
|
|
|
let a = *angle_rad as f64;
|
|
|
|
|
let cos_a = a.cos();
|
|
|
|
|
let sin_a = a.sin();
|
|
|
|
|
let dx = self.insertion_point.x - bx;
|
|
|
|
|
let dy = self.insertion_point.y - by;
|
|
|
|
|
self.insertion_point.x = bx + dx * cos_a - dy * sin_a;
|
|
|
|
|
self.insertion_point.y = by + dx * sin_a + dy * cos_a;
|
|
|
|
|
self.rotation += a;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|