forked from 1b-agent/opencadstudio-upstream
Point clouds: PCEXTRACTEDGE, PCEXTRACTCORNER, PCEXTRACTCENTERLINE, PCEXTRACTSECTION
Planes are found from the cloud points under the pick and grown over the connected points on them: two planes give a line along their intersection over the points' extent, three a point at their corner. A cylindrical segment gives a line along its axis. A live section object traces the points on its kept side as polylines or lines in the section plane, with a preview and Accept/Settings/Undo; -PCEXTRACTSECTION creates them directly. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
2e23a903a4
commit
7761652a9f
4 files changed
+1083
No files matched your search
@@ -15,6 +15,7 @@ mod layerprops;
|
||||
mod layers;
|
||||
pub(crate) mod pdf_import;
|
||||
mod point_cloud;
|
||||
mod pc_extract;
|
||||
mod pdf_underlay;
|
||||
mod pdf_dialogs;
|
||||
mod xclip;
|
||||
@@ -270,6 +271,9 @@ impl OpenCADStudio {
|
||||
if let Some(t) = self.dispatch_pdf_underlay(cmd, i) {
|
||||
return Some(t);
|
||||
}
|
||||
if let Some(t) = self.dispatch_pc_extract(cmd, i) {
|
||||
return Some(t);
|
||||
}
|
||||
if let Some(t) = self.dispatch_draw(cmd, i) {
|
||||
return Some(t);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
//! 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) {
|
||||
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))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user