Spaces:
Sleeping
Sleeping
File size: 2,168 Bytes
1993d5c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | """Geometry Normalizer: Normalizes coordinates, scales, frames, and removes degenerate geometries."""
from __future__ import annotations
import logging
import numpy as np
from typing import Dict, List, Tuple
logger = logging.getLogger(__name__)
class GeometryNormalizer:
"""Standardizes point naming, coordinate scaling, centering, and precision."""
def normalize_coordinates(
self,
coords: Dict[str, List[float]],
target_span: float = 8.0,
is_3d: bool = False,
) -> Dict[str, List[float]]:
if not coords:
return {}
cleaned: Dict[str, List[float]] = {}
for pid, pt in coords.items():
cleaned[pid] = [
0.0 if abs(val) < 1e-6 else float(np.round(val, 6))
for val in pt
]
# Calculate bounding box
all_pts = np.array(list(cleaned.values()))
if len(all_pts) == 0:
return cleaned
mins = np.min(all_pts, axis=0)
maxs = np.max(all_pts, axis=0)
spans = maxs - mins
max_span = float(np.max(spans))
# If geometry is valid and non-degenerate, scale into comfortable viewing range
if max_span > 1e-4:
scale = target_span / max_span
center = (mins + maxs) / 2.0
normalized: Dict[str, List[float]] = {}
for pid, pt in cleaned.items():
pt_arr = np.array(pt)
norm_pt = (pt_arr - center) * scale
if not is_3d:
# In 2D, pin z to 0 and center in 2D plane
normalized[pid] = [
float(np.round(norm_pt[0], 4)),
float(np.round(norm_pt[1], 4)),
0.0,
]
else:
# In 3D, keep z >= 0 ground orientation when appropriate
normalized[pid] = [
float(np.round(norm_pt[0], 4)),
float(np.round(norm_pt[1], 4)),
float(np.round(norm_pt[2], 4)),
]
return normalized
return cleaned
|