Point cloud extraction: structured scans only

Plane and cylinder picks ask again and section extraction gives nothing
on a scan without segments, as the reference does with unstructured
scans (scan segmentation is not decoded yet). The section dialog's time
estimate reads in minutes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
ramox81andClaude Opus 5.5 committed 2026-09-30 17:50:23 +03:00
1 parent 15c0da8b79
commit d1b61c7330
23 files changed
+46 -26

No files matched your search

+1 -1
View File
@@ -4019,7 +4019,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4006,7 +4006,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4004,7 +4004,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4005,7 +4005,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4007,7 +4007,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4008,7 +4008,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4007,7 +4007,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4006,7 +4006,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4007,7 +4007,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -3995,7 +3995,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4006,7 +4006,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4006,7 +4006,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -3995,7 +3995,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4006,7 +4006,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4005,7 +4005,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4006,7 +4006,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4007,7 +4007,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4008,7 +4008,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -3990,7 +3990,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -4002,7 +4002,7 @@ insert =
.pcs-max-points = Maximum points to process
.pcs-faster = Faster
.pcs-accurate = More accurate
.pcs-time = Estimated time: __ocs_fmt_0__ min
.pcs-time = Estimated time: __ocs_fmt_0__ minutes
.pcs-output = Output geometry
.pcs-polylines = 2D Polylines
.pcs-width = Polyline width
+1 -1
View File
@@ -150,7 +150,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
"Maximum points to process" => Some(("insert", "pcs-max-points")),
"Faster" => Some(("insert", "pcs-faster")),
"More accurate" => Some(("insert", "pcs-accurate")),
"Estimated time: {count} min" => Some(("insert", "pcs-time")),
"Estimated time: {count} minutes" => Some(("insert", "pcs-time")),
"Output geometry" => Some(("insert", "pcs-output")),
"2D Polylines" => Some(("insert", "pcs-polylines")),
"Polyline width" => Some(("insert", "pcs-width")),
+24 -4
View File
@@ -15,9 +15,12 @@
// [Accept/Settings/Undo] <Settings>:
// (-PCEXTRACTSECTION creates them without asking.)
//
// A plane is found from the cloud points under the cursor: the front-most
// point in the pick aperture, a plane fitted to the points around it, then
// grown over the points on that plane connected to it.
// Planes, cylinders and section lines come from structured (segmented)
// scans only; on an unstructured scan a plane or cylinder pick asks again
// and a section extracts nothing, as the reference does. On a
// structured scan a plane is found from the cloud points under the cursor:
// the front-most point in the pick aperture, a plane fitted to the points
// around it, then grown over the points on that plane connected to it.
use std::sync::{Arc, Mutex};
@@ -53,6 +56,13 @@ impl Clouds {
})
}
/// Whether the clouds carry segments (structured scans) to extract from.
// ponytail: scan segmentation is not decoded, so every scan counts as
// unstructured; read the scan's segmentation to extract from structured ones.
fn segmented(&self) -> bool {
false
}
fn of(&self, handle: Handle) -> Option<Clouds> {
let found: Vec<_> = self.0.iter().filter(|(h, _)| *h == handle).cloned().collect();
(!found.is_empty()).then_some(Clouds(found))
@@ -406,7 +416,10 @@ impl CadCommand for PlanesCommand {
let Some(context) = self.context else {
return CmdResult::NeedPoint;
};
// Off the cloud or not on a plane: the prompt again.
// Off the cloud, not on a plane or an unstructured scan: the prompt again.
if !self.clouds.segmented() {
return CmdResult::NeedPoint;
}
let Some(plane) = surface_hit(&self.clouds, &context, pt)
.and_then(|(hit, pixel)| detect_plane(&self.clouds, hit, pixel))
else {
@@ -470,6 +483,9 @@ impl CadCommand for CenterlineCommand {
let Some(context) = self.context else {
return CmdResult::NeedPoint;
};
if !self.clouds.segmented() {
return CmdResult::NeedPoint;
}
match surface_hit(&self.clouds, &context, pt).and_then(|(hit, pixel)| detect_cylinder(&self.clouds, hit, pixel)) {
Some((start, end)) => CmdResult::CommitAndExit(EntityType::Line(Line::from_points(vector(start), vector(end)))),
None => CmdResult::NeedPoint,
@@ -746,6 +762,10 @@ impl SectionCommand {
let (Some(cloud), Some(section)) = (&self.cloud, self.section) else {
return Ok(Vec::new());
};
// An unstructured scan gives no section lines (nothing, silently).
if !cloud.segmented() {
return Ok(Vec::new());
}
let s = settings();
let n = section.viewing;
let kept: Vec<DVec3> = cloud
+1 -1
View File
@@ -1592,7 +1592,7 @@ pub fn view_pc_section<'a>(state: &'a PcSectionState, sizing: crate::ui::modal::
Space::new().width(Fill),
text(t!("More accurate")).size(10).style(muted_style),
Space::new().width(Fill),
text(crate::tf!("Estimated time: {count} min", count = minutes)).size(10).style(muted_style),
text(crate::tf!("Estimated time: {count} minutes", count = minutes)).size(10).style(muted_style),
],
]
.spacing(6),