2026-04-02 23:51:17 +03:00
|
|
|
// REVCLOUD command — draw a revision cloud (arc-bumped closed polyline).
|
|
|
|
|
//
|
|
|
|
|
// Workflow: pick polygon corners (like PLINE), press Enter to close.
|
|
|
|
|
// Each segment of the polygon is subdivided into arc bumps (bulge = 0.5).
|
|
|
|
|
// Minimum arc length = `arc_length` parameter.
|
|
|
|
|
|
|
|
|
|
use acadrust::entities::LwPolyline;
|
|
|
|
|
use acadrust::types::Vector2;
|
|
|
|
|
use acadrust::{EntityType, entities::LwVertex};
|
|
|
|
|
use glam::Vec3;
|
|
|
|
|
|
|
|
|
|
use crate::command::{CadCommand, CmdResult};
|
feat: redesign Annotate ribbon tab with proper groups and SVG icons
Added 15 SVG icons for all annotation tools (dimensions, leaders,
table, wipeout, revision cloud, tolerance, ddedit).
Annotate ribbon now has 6 groups matching standard CAD layout:
- Text: MText (large dropdown) + Text + Edit Text
- Dimensions: Linear (large dropdown with 6 types) + Continue + Baseline + Tolerance
- Leaders: Multileader (large dropdown) + Leader
- Tables: Table (large)
- Markup: Wipeout + Rev Cloud
- Annotation Scaling: Scale List, Add Scale, Scale Edit, Sync Scales
Added pub tool() + ICON to all annotate tools that were missing them
(aligned_dim, diameter_dim, dim_continue, dim_baseline, table_cmd,
tolerance_cmd, ddedit), and to home/draw/wipeout and revcloud.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 03:03:08 +03:00
|
|
|
use crate::modules::{IconKind, ModuleEvent, ToolDef};
|
2026-04-02 23:51:17 +03:00
|
|
|
use crate::scene::wire_model::WireModel;
|
|
|
|
|
|
feat: redesign Annotate ribbon tab with proper groups and SVG icons
Added 15 SVG icons for all annotation tools (dimensions, leaders,
table, wipeout, revision cloud, tolerance, ddedit).
Annotate ribbon now has 6 groups matching standard CAD layout:
- Text: MText (large dropdown) + Text + Edit Text
- Dimensions: Linear (large dropdown with 6 types) + Continue + Baseline + Tolerance
- Leaders: Multileader (large dropdown) + Leader
- Tables: Table (large)
- Markup: Wipeout + Rev Cloud
- Annotation Scaling: Scale List, Add Scale, Scale Edit, Sync Scales
Added pub tool() + ICON to all annotate tools that were missing them
(aligned_dim, diameter_dim, dim_continue, dim_baseline, table_cmd,
tolerance_cmd, ddedit), and to home/draw/wipeout and revcloud.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 03:03:08 +03:00
|
|
|
pub const ICON: IconKind = IconKind::Svg(include_bytes!("../../../../assets/icons/revcloud.svg"));
|
|
|
|
|
|
|
|
|
|
pub fn tool() -> ToolDef {
|
|
|
|
|
ToolDef {
|
|
|
|
|
id: "REVCLOUD",
|
|
|
|
|
label: "Rev Cloud",
|
|
|
|
|
icon: ICON,
|
|
|
|
|
event: ModuleEvent::Command("REVCLOUD".to_string()),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-02 23:51:17 +03:00
|
|
|
const DEFAULT_ARC_LEN: f64 = 1.0; // default arc bump length
|
|
|
|
|
|
|
|
|
|
pub struct RevCloudCommand {
|
|
|
|
|
points: Vec<Vec3>,
|
|
|
|
|
arc_length: f64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl RevCloudCommand {
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
points: vec![],
|
|
|
|
|
arc_length: DEFAULT_ARC_LEN,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CadCommand for RevCloudCommand {
|
|
|
|
|
fn name(&self) -> &'static str { "REVCLOUD" }
|
|
|
|
|
|
|
|
|
|
fn prompt(&self) -> String {
|
|
|
|
|
if self.points.is_empty() {
|
|
|
|
|
format!("REVCLOUD Specify start point (arc length = {:.2}):", self.arc_length)
|
|
|
|
|
} else {
|
|
|
|
|
format!("REVCLOUD Specify next point ({} pts, Enter to close):", self.points.len())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn on_point(&mut self, pt: Vec3) -> CmdResult {
|
|
|
|
|
self.points.push(pt);
|
|
|
|
|
CmdResult::NeedPoint
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn on_enter(&mut self) -> CmdResult {
|
|
|
|
|
if self.points.len() < 3 {
|
|
|
|
|
return CmdResult::Cancel;
|
|
|
|
|
}
|
|
|
|
|
let entity = make_revcloud(&self.points, self.arc_length);
|
|
|
|
|
CmdResult::CommitAndExit(entity)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn on_mouse_move(&mut self, pt: Vec3) -> Option<WireModel> {
|
|
|
|
|
if self.points.is_empty() { return None; }
|
|
|
|
|
let mut preview_pts: Vec<[f32; 3]> =
|
|
|
|
|
self.points.iter().map(|p| [p.x, p.y, p.z]).collect();
|
|
|
|
|
preview_pts.push([pt.x, pt.y, pt.z]);
|
|
|
|
|
preview_pts.push([self.points[0].x, self.points[0].y, self.points[0].z]);
|
|
|
|
|
Some(WireModel {
|
|
|
|
|
name: "revcloud_preview".into(),
|
|
|
|
|
points: preview_pts,
|
|
|
|
|
color: WireModel::CYAN,
|
|
|
|
|
selected: false,
|
|
|
|
|
pattern_length: 0.0,
|
|
|
|
|
pattern: [0.0; 8],
|
|
|
|
|
line_weight_px: 1.0,
|
|
|
|
|
snap_pts: vec![],
|
|
|
|
|
tangent_geoms: vec![],
|
2026-04-06 23:19:08 +03:00
|
|
|
aci: 0,
|
2026-04-02 23:51:17 +03:00
|
|
|
key_vertices: vec![],
|
2026-04-26 12:21:51 +03:00
|
|
|
aabb: WireModel::UNBOUNDED_AABB,
|
2026-05-06 06:55:28 +03:00
|
|
|
plinegen: true,
|
2026-05-06 07:12:05 +03:00
|
|
|
vp_scissor: None,
|
2026-05-06 23:24:26 +03:00
|
|
|
fill_tris: vec![],
|
2026-04-02 23:51:17 +03:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn make_revcloud(pts: &[Vec3], arc_len: f64) -> EntityType {
|
|
|
|
|
let n = pts.len();
|
|
|
|
|
let mut vertices: Vec<LwVertex> = Vec::new();
|
|
|
|
|
|
|
|
|
|
// For each edge, subdivide into arc bumps (bulge ≈ 0.5)
|
|
|
|
|
let bump_bulge = 0.5f64; // tan(included_angle/4) ≈ 0.5 → ~53° arc
|
|
|
|
|
|
|
|
|
|
for i in 0..n {
|
|
|
|
|
let p0 = pts[i];
|
|
|
|
|
let p1 = pts[(i + 1) % n];
|
|
|
|
|
let seg_len = ((p1.x - p0.x).powi(2) + (p1.z - p0.z).powi(2)).sqrt() as f64;
|
|
|
|
|
if seg_len < 1e-6 { continue; }
|
|
|
|
|
|
|
|
|
|
// How many full arcs fit?
|
|
|
|
|
let num_arcs = ((seg_len / arc_len).round() as usize).max(1);
|
|
|
|
|
let step_x = (p1.x - p0.x) as f64 / num_arcs as f64;
|
|
|
|
|
let step_z = (p1.z - p0.z) as f64 / num_arcs as f64;
|
|
|
|
|
|
|
|
|
|
for j in 0..num_arcs {
|
|
|
|
|
let x = p0.x as f64 + step_x * j as f64;
|
|
|
|
|
let y = p0.z as f64 + step_z * j as f64; // DXF Y
|
|
|
|
|
let mut v = LwVertex::new(Vector2::new(x, y));
|
|
|
|
|
v.bulge = bump_bulge;
|
|
|
|
|
vertices.push(v);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut p = LwPolyline::new();
|
|
|
|
|
p.is_closed = true;
|
|
|
|
|
p.vertices = vertices;
|
|
|
|
|
EntityType::LwPolyline(p)
|
|
|
|
|
}
|