forked from 1b-agent/opencadstudio-upstream
A dockable Point Cloud Manager lists each point cloud of the drawing (only the selected ones while any is selected) with Regions (disabled, region data is not read), Unassigned Points and Scans, the scans named by their file stems. Each switch shows or hides points: the cloud, its unassigned points, all scans or one scan. The hidden set is the cloud's OCS_POINTCLOUD_VISIBILITY extended data (scan names plus *CLOUD_OFF / *UNASSIGNED_OFF markers, app id registered), written as one undo step and kept on save. The drawn points skip hidden scans by their index ranges, and the hidden set is part of the placed-cloud key. Collapse all / expand all, row highlight and a search box that filters rows (keeping parents of matches). POINTCLOUDMANAGERCLOSE closes it; the pc_manager_toggle automation action flips a switch. Co-Authored-By: Claude Opus 5.5 <[email protected]>
90 lines
3.6 KiB
Rust
90 lines
3.6 KiB
Rust
//! PCEXTRACTEDGE, PCEXTRACTCORNER, PCEXTRACTCENTERLINE and
|
|
//! (-)PCEXTRACTSECTION: the commands get the drawing's shown cloud points
|
|
//! and its section objects when they start.
|
|
|
|
use super::*;
|
|
use codec::entities::ExtendedEntityData;
|
|
use glam::DVec3;
|
|
|
|
use crate::modules::insert::pc_extract::{
|
|
CenterlineCommand, Clouds, PlanesCommand, Section, SectionCommand,
|
|
};
|
|
|
|
fn dvec(v: codec::types::Vector3) -> DVec3 {
|
|
DVec3::new(v.x, v.y, v.z)
|
|
}
|
|
|
|
impl OpenCADStudio {
|
|
/// The points each point cloud shows (the renderer's placed set).
|
|
fn extraction_clouds(&self, i: usize) -> Clouds {
|
|
let document = &self.tabs[i].scene.document;
|
|
let mut clouds = Vec::new();
|
|
for entity in document.entities() {
|
|
let codec::EntityType::Extended(extended) = entity else {
|
|
continue;
|
|
};
|
|
let ExtendedEntityData::PointCloudEx(data) = &extended.data else {
|
|
continue;
|
|
};
|
|
let common = entity.common();
|
|
// The colour the renderer places with, so its cached points are reused.
|
|
let color = if matches!(common.color, codec::types::Color::ByLayer) {
|
|
document.layers.get(&common.layer).map(|layer| layer.color.clone()).unwrap_or(common.color.clone())
|
|
} else {
|
|
common.color.clone()
|
|
};
|
|
let color = color.rgb().map_or([255; 3], |(r, g, b)| [r, g, b]);
|
|
if let Some(placed) = crate::scene::model::point_cloud::placed(
|
|
document,
|
|
data,
|
|
color,
|
|
None,
|
|
&crate::scene::model::point_cloud::hidden(common),
|
|
) {
|
|
clouds.push((common.handle, placed));
|
|
}
|
|
}
|
|
Clouds(clouds)
|
|
}
|
|
|
|
fn extraction_sections(&self, i: usize) -> Vec<Section> {
|
|
self.tabs[i]
|
|
.scene
|
|
.document
|
|
.entities()
|
|
.filter_map(|entity| {
|
|
let codec::EntityType::Extended(extended) = entity else {
|
|
return None;
|
|
};
|
|
let ExtendedEntityData::SectionObject(data) = &extended.data else {
|
|
return None;
|
|
};
|
|
let (first, last) = (dvec(*data.vertices.first()?), dvec(*data.vertices.last()?));
|
|
let tangent = (last - first).normalize_or(DVec3::X);
|
|
let vertical = dvec(data.vertical_direction).normalize_or(DVec3::Z);
|
|
let viewing = vertical.cross(tangent).normalize_or(-DVec3::Z)
|
|
* if data.flags & 4 != 0 { 1.0 } else { -1.0 };
|
|
Some(Section { origin: first, viewing, tangent, live: data.flags & 1 != 0 })
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
pub(super) fn dispatch_pc_extract(&mut self, cmd: &str, i: usize) -> Option<Task<Message>> {
|
|
use crate::command::CadCommand;
|
|
let command: Box<dyn CadCommand> = match cmd {
|
|
"PCEXTRACTEDGE" => Box::new(PlanesCommand::new(false, self.extraction_clouds(i))),
|
|
"PCEXTRACTCORNER" => Box::new(PlanesCommand::new(true, self.extraction_clouds(i))),
|
|
"PCEXTRACTCENTERLINE" => Box::new(CenterlineCommand::new(self.extraction_clouds(i))),
|
|
"PCEXTRACTSECTION" | "-PCEXTRACTSECTION" => Box::new(SectionCommand::new(
|
|
cmd == "PCEXTRACTSECTION",
|
|
self.extraction_clouds(i),
|
|
self.extraction_sections(i),
|
|
)),
|
|
_ => return None,
|
|
};
|
|
self.command_line.push_info(&command.prompt());
|
|
self.tabs[i].active_cmd = Some(command);
|
|
Some(self.finish_dispatch(cmd))
|
|
}
|
|
}
|