src.utils.curve.simple_global_curve_optimizer
Classes
|
- class src.utils.curve.simple_global_curve_optimizer.SimpleGlobalCurveOptimizer(merge_radius=None, min_segment_length=None, z_tolerance=2.0, min_voxel_size=0.1)
- Author:
Alberto M. Esmoris Pena
Energy-minimising global optimiser for the polylines produced by
SimpleCurveExtractor. Runs a per-vertex energy descent over candidate polylines and bridges coverage-refine sub-features into their main siblings inside each mixed CURVE_ID.Three objectives drive the energy formulation:
Maximise the count of covered curve points.
Minimise non-curve traversal.
Maximise smoothness (minimise local curvature).
Instances are constructed once per pipeline run from the private SCE pipeline phase
_step_global_optimization; they take a snapshot of the relevant SCE configuration (merge_radius,min_segment_length,z_tolerance,min_voxel_size) and run the three-pass per-vertex descent plus the mixed-CID bridging pass without further coupling to the orchestrator. SeeSimpleCurveExtractorfor the upstream pipeline that producessmooth_curvesandmetadata.- Variables:
merge_radius (float or None) – Spatial radius governing the coverage / max-\(\Delta z\) derivation in
oce_setup().Nonefalls back to a skeleton-voxel-scaled default at use time.min_segment_length (float or None) – Bridge-distance limit used in
oce_run_bridging().Nonefalls back to a skeleton-voxel-scaled default at use time.z_tolerance (float) – Z-tolerance (3-sigma bound) used by
max_dz()to derive the coverage Z-window.min_voxel_size (float) – Floor scale used by
max_dz()to keep the coverage Z-window portable across coordinate systems.
- __init__(merge_radius=None, min_segment_length=None, z_tolerance=2.0, min_voxel_size=0.1)
Snapshot the SCE configuration relevant to the energy descent and the mixed-CID bridging pass.
- optimize_curves_energy(smooth_curves, metadata, X_orig, skel_vs, spacing)
Energy-minimizing global optimization.
Processes ALL features with per-vertex energy descent. For mixed CIDs (main + coverage_refine), additionally bridges coverage-refine features to main features using the lowest-energy path.
Three objectives: 1. Maximize covered curve points 2. Minimize non-curve traversal 3. Maximize smoothness (min curvature)
Implemented as a thin driver that orchestrates four private phase helpers (Phase 6 CL-6c decomposition; behaviour is byte-output preserved relative to the pre-decomposition monolith):
oce_setup()— Phase 1 setup, builds the KD-tree on the downsampled curve-class points and resolves the energy weights.oce_run_descent()— Phase 2 per-vertex descent (mutatessmooth_curvesin place).oce_run_bridging()— Phase 3 bridging for mixed CIDs (mutatessmooth_curvesandmetadatain place; returns the set of absorbed indices).oce_cleanup()— Phase 4 list filter by absorbed indices.
- Parameters:
smooth_curves (list of dict) – Output curves.
metadata (list of dict) – Per-curve metadata.
X_orig (
np.ndarray) – Centered curve points (Nx3).skel_vs (float) – Skeleton voxel size.
spacing (float) – Output point spacing.
- Returns:
Optimized (curves, metadata).
- Return type:
tuple
- oce_setup(X_orig, skel_vs)
Phase 1 of
optimize_curves_energy().Build the KD-tree on the downsampled curve-class points and resolve the per-iteration energy weights (coverage radius, max dZ, alpha, gamma, curvature threshold).
Byte-output-preserving: every numerical expression is reproduced verbatim from the pre-decomposition monolith; the only change is the packaging of the resolved scalars and arrays into a context dictionary.
- Parameters:
X_orig (
np.ndarray) – Centered curve points (Nx3).skel_vs (float) – Skeleton voxel size.
- Returns:
Context dict with keys
ds_pts,ds_tree,ds_z,max_dz,snap_r,alpha,gamma,pi_12,mr; orNonewhen downsampling produced an empty point set (caller short-circuits).- Return type:
dict or None
- oce_run_descent(smooth_curves, ctx, spacing)
Phase 2 of
optimize_curves_energy().Per-vertex energy descent over all features and all step sizes. Each accepted descent at
smooth_curves[fi]is committed in place viarebuild_feature(); rejected steps are reverted to the pre-step vertex.Byte-output-preserving: the outer step-size list, the per-curve loop ordering, the per-vertex
range(1, n - 1)loop, the inline coverage / curvature / centroid / displacement formulas, and the per-curve coverage-comparison fallback are all reproduced verbatim. The mutablesmooth_curveslist is the SAME instance the driver passed in, so vertex acceptance is observed by the caller.- Parameters:
smooth_curves (list of dict) – Output curves (mutated).
ctx (dict) – Context dict from
oce_setup().spacing (float) – Output point spacing.
- Returns:
None— mutation is in place.
- oce_run_bridging(smooth_curves, metadata, ctx, skel_vs, spacing)
Phase 3 of
optimize_curves_energy().Bridge coverage-refine features to their main siblings inside each mixed CID, scoring candidate bridges with the energy helper. The
smooth_curves[best_mi]slot is replaced by the merged feature, and the absorbed coverage feature index is recorded so Phase 4 can prune it.Byte-output-preserving: the iteration order of
mixed_cidsis governed bycid_has_main & cid_has_covover the same metadata mutation (set ordering matches the pre-decomposition monolith because we receive the SAME metadata list). The KDTree.query nearest-neighbour tie-break is preserved by reusing_collect_endpointsexactly as the monolith did. The inlinenp.sum(np.sqrt(np.sum(...)))length writes are retained verbatim (NOT replaced with_polyline_lengths) to avoid the float-reduction-order divergence flagged in the Phase-1 SC-09 review.- Parameters:
smooth_curves (list of dict) – Output curves (mutated).
metadata (list of dict) – Per-curve metadata (mutated).
ctx (dict) – Context dict from
oce_setup().skel_vs (float) – Skeleton voxel size (used only for the bridge_limit fallback).
spacing (float) – Output point spacing.
- Returns:
Tuple
(absorbed, n_bridged)whereabsorbedis the set of indices into the CALLER’ssmooth_curves/metadatalists that should be filtered in Phase 4.- Return type:
tuple
- static oce_cleanup(smooth_curves, metadata, absorbed, n_bridged)
Phase 4 of
optimize_curves_energy().Filter
smooth_curvesandmetadataby theabsorbedindex set produced in Phase 3 and log the bridge count.Byte-output-preserving: the index-keyed comprehensions reproduce the pre-decomposition loop exactly; the resulting NEW lists replace the caller’s bindings via the return tuple.
- Parameters:
smooth_curves (list of dict) – Output curves.
metadata (list of dict) – Per-curve metadata.
absorbed (set) – Indices to drop.
n_bridged (int) – Bridge count, for logging.
- Returns:
Tuple
(smooth_curves, metadata).- Return type:
tuple
- static grid_subsample(pts, cell_size)
Spatial grid subsampling: retain one point per axis-aligned cell. Fully vectorized with numpy for performance on large point clouds.
- Parameters:
pts (
np.ndarray) – Input points (N x 3).cell_size (float) – Cell edge length.
- Returns:
Subsampled points (M x 3).
- Return type:
np.ndarray
- static z_monotone_ok(pts, i, new_z)
Check that new_z preserves local Z monotonicity at vertex i.
- Parameters:
pts (
np.ndarray) – Polyline points (N x 3).i (int) – Vertex index.
new_z (float) – Candidate Z value.
- Returns:
True if Z-trend is preserved.
- Return type:
bool
- static vertex_energy(pts, i, ds_tree, ds_z, snap_r, max_dz, alpha, gamma)
Energy at vertex i of polyline pts.
- Parameters:
pts (
np.ndarray) – Polyline points (N x 3).i (int) – Vertex index.
ds_tree – KDTree on downsampled curve-class points (XY).
ds_z (
np.ndarray) – Z values of downsampled pts.snap_r (float) – Search radius.
max_dz (float) – Max Z-difference.
alpha (float) – Coverage weight.
gamma (float) – Curvature weight.
- Returns:
Scalar energy.
- Return type:
float
- static rebuild_feature(pts, spacing)
Rebuild arc-lengths and slopes for a polyline after modification.
- static make_bridge(p1, p2, spacing)
Create a smooth bridge between two 3D points.
Instead of a 2-point bridge (which creates an abrupt Z-jump), linearly interpolates N points so that each step has a small dZ. The number of points is determined by the 3D distance and the given spacing.
- Parameters:
p1 (
np.ndarray) – Start point (3D).p2 (
np.ndarray) – End point (3D).spacing (float) – Target point spacing.
- Returns:
(bridge_pts, bridge_slopes) where bridge_pts is (N x 3) and bridge_slopes is (N,).
- Return type:
tuple
- static endpoint_tangent(pts, is_end, n=5)
Estimate the tangent direction at one end of a polyline using the last
npoints.- Parameters:
pts (
np.ndarray) – Polyline points (N x 3).is_end (bool) – True for the tail, False for the head.
n (int) – Number of trailing points.
- Returns:
Unit direction vector (3D), or zero vector if degenerate.
- Return type:
np.ndarray
- max_dz(radius)
Compute the maximum Z-difference threshold for merging/chaining operations. Uses the smaller of \(3 \sigma_z\) and the given radius, with a floor of \(10 \times\)
min_voxel_sizeto prevent degenerate behaviour when``z_tolerance``is zero.- Parameters:
radius (float) – The spatial radius context.
- Returns:
Maximum Z-difference.
- Return type:
float