From f513899d499a7ea30c7e6cc340d2df412f43ffd8 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Mon, 29 Jun 2026 09:07:30 +0300 Subject: [PATCH] feat(commands): add REGION (closed boundaries -> region entities) Convert selected closed polylines and circles into Region entities, one wire loop each (reuses acadrust Region/Wire). COMMANDS.md: 215/262. Co-Authored-By: Claude Opus 4.8 --- COMMANDS.md | 6 ++--- src/app/commands/draw.rs | 58 ++++++++++++++++++++++++++++++++++++++++ src/app/commands/mod.rs | 2 ++ 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/COMMANDS.md b/COMMANDS.md index c42a8cd92..1b89a1929 100644 --- a/COMMANDS.md +++ b/COMMANDS.md @@ -42,7 +42,7 @@ Status of every standard CAD command in Open CAD Studio: | `SKETCH` | — | Freehand sketch | ✅ | | `SOLID` | SO | Filled 2D shape (legacy) | ✅ | | `MINSERT` | — | Matrix block insert | ✅ | -| `REGION` | REG | 2D closed region | ❌ | +| `REGION` | REG | 2D closed region | ✅ | | `FIELD` | — | Auto-updating text field | ❌ | --- @@ -351,7 +351,7 @@ Status of every standard CAD command in Open CAD Studio: | Category | Total | ✅ Done | 🔶 Partial | ❌ Missing | |---|---|---|---|---| -| Draw | 32 | 30 | 0 | 2 | +| Draw | 32 | 31 | 0 | 1 | | Modify | 42 | 39 | 1 | 2 | | Dimension | 26 | 26 | 0 | 0 | | Text & Table | 10 | 7 | 1 | 2 | @@ -362,7 +362,7 @@ Status of every standard CAD command in Open CAD Studio: | Inquiry | 12 | 12 | 0 | 0 | | File & Plot | 17 | 14 | 0 | 3 | | Manage & Customize | 22 | 13 | 3 | 6 | -| **Total** | **262** | **214** | **15** | **33** | +| **Total** | **262** | **215** | **15** | **32** | > Counts include commands listed under more than one category (e.g. `SLICE`, `HELIX`, > `MINSERT`, `SUBTRACT`/`UNION`/`INTERSECT` appear in both their 2D and 3D groups). diff --git a/src/app/commands/draw.rs b/src/app/commands/draw.rs index 29194f77a..9e6d2d1bc 100644 --- a/src/app/commands/draw.rs +++ b/src/app/commands/draw.rs @@ -724,6 +724,64 @@ impl OpenCADStudio { return Some(self.fit_spline()); } + // REGION — convert selected closed boundaries (closed polylines / + // circles) into Region entities (one wire loop each). + "REGION" | "REG" => { + use acadrust::entities::{Region, Wire}; + use acadrust::types::Vector3; + let mut loops: Vec> = Vec::new(); + for (_, e) in self.tabs[i].scene.selected_entities().iter() { + match e { + acadrust::EntityType::LwPolyline(pl) + if pl.is_closed && pl.vertices.len() >= 3 => + { + loops.push( + pl.vertices + .iter() + .map(|v| Vector3::new(v.location.x, v.location.y, 0.0)) + .collect(), + ); + } + acadrust::EntityType::Circle(c) => { + let n = 64; + loops.push( + (0..n) + .map(|k| { + let a = std::f64::consts::TAU * k as f64 / n as f64; + Vector3::new( + c.center.x + c.radius * a.cos(), + c.center.y + c.radius * a.sin(), + c.center.z, + ) + }) + .collect(), + ); + } + _ => {} + } + } + if loops.is_empty() { + self.command_line + .push_error("REGION: select closed polylines or circles."); + } else { + self.push_undo_snapshot(i, "REGION"); + let count = loops.len(); + for pts in loops { + let mut w = Wire::new(); + let first = pts.first().copied().unwrap_or(Vector3::new(0.0, 0.0, 0.0)); + w.points = pts; + let mut r = Region::new(); + r.point_of_reference = first; + r.wires = vec![w]; + r.common.layer = self.tabs[i].active_layer.clone(); + self.tabs[i].scene.add_entity(acadrust::EntityType::Region(r)); + } + self.tabs[i].dirty = true; + self.command_line + .push_output(&format!("REGION: created {count} region(s).")); + } + } + // PYRAMID [sides] — create an n-sided pyramid mesh. cmd if cmd == "PYRAMID" || cmd.starts_with("PYRAMID ") diff --git a/src/app/commands/mod.rs b/src/app/commands/mod.rs index c6f43fa8c..0064c1e8f 100644 --- a/src/app/commands/mod.rs +++ b/src/app/commands/mod.rs @@ -342,6 +342,8 @@ inventory::submit!(crate::command::CommandRegistration { "QC", "HYPERLINK", "XOPEN", + "REGION", + "REG", // Slice/section + interference + press-pull/thicken + 3D transforms + wall/pyramid. "SLICE", "SL",