fix: arc midpoint parsing + edge type detection for NX integer enums
- EvaluateUnitVectors returns nested lists — added recursive parser - SolidEdgeType returns int 1 (not 'Linear') — handle both formats
This commit is contained in:
@@ -116,6 +116,42 @@ class EdgeSegment:
|
|||||||
# NX edge analysis — extract type + arc parameters
|
# NX edge analysis — extract type + arc parameters
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def _parse_eval_result(result: Any) -> Point3D | None:
|
||||||
|
"""Parse NX UF EvaluateUnitVectors return into a 3D point.
|
||||||
|
|
||||||
|
Handles multiple NX Python return formats:
|
||||||
|
- NXOpen.Point3d with .X/.Y/.Z attrs
|
||||||
|
- Tuple/list of (point_obj, tangent_obj, ...)
|
||||||
|
- Nested numeric tuples ((x,y,z), (tx,ty,tz), ...)
|
||||||
|
- Flat numeric list [x,y,z,tx,ty,tz,...]
|
||||||
|
"""
|
||||||
|
# Direct Point3d-like object
|
||||||
|
if hasattr(result, 'X') and hasattr(result, 'Y') and hasattr(result, 'Z'):
|
||||||
|
return (float(result.X), float(result.Y), float(result.Z))
|
||||||
|
|
||||||
|
if isinstance(result, (list, tuple)):
|
||||||
|
# Check if first 3 elements are all numeric (flat array)
|
||||||
|
if len(result) >= 3 and all(isinstance(v, (int, float)) for v in result[:3]):
|
||||||
|
return (float(result[0]), float(result[1]), float(result[2]))
|
||||||
|
|
||||||
|
# Check first element — could be a point object or sub-list
|
||||||
|
if len(result) >= 1:
|
||||||
|
first = result[0]
|
||||||
|
# Point3d-like object
|
||||||
|
if hasattr(first, 'X') and hasattr(first, 'Y') and hasattr(first, 'Z'):
|
||||||
|
return (float(first.X), float(first.Y), float(first.Z))
|
||||||
|
# Sub-list/tuple of 3 numbers
|
||||||
|
if isinstance(first, (list, tuple)) and len(first) >= 3:
|
||||||
|
if all(isinstance(v, (int, float)) for v in first[:3]):
|
||||||
|
return (float(first[0]), float(first[1]), float(first[2]))
|
||||||
|
# Recurse into first element
|
||||||
|
parsed = _parse_eval_result(first)
|
||||||
|
if parsed is not None:
|
||||||
|
return parsed
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _analyze_edge(edge: Any, lister: Any = None) -> EdgeSegment:
|
def _analyze_edge(edge: Any, lister: Any = None) -> EdgeSegment:
|
||||||
"""
|
"""
|
||||||
Analyze an NX edge and return a typed EdgeSegment.
|
Analyze an NX edge and return a typed EdgeSegment.
|
||||||
@@ -137,13 +173,18 @@ def _analyze_edge(edge: Any, lister: Any = None) -> EdgeSegment:
|
|||||||
|
|
||||||
# Classify edge type
|
# Classify edge type
|
||||||
edge_type_str = "?"
|
edge_type_str = "?"
|
||||||
|
edge_type_val = None
|
||||||
try:
|
try:
|
||||||
edge_type_str = str(edge.SolidEdgeType)
|
edge_type_val = edge.SolidEdgeType
|
||||||
|
edge_type_str = str(edge_type_val)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
is_linear = "Linear" in edge_type_str
|
# NX returns either enum name ("Linear") or integer (1=linear, 2=circular, etc.)
|
||||||
is_circular = "Circular" in edge_type_str
|
is_linear = ("Linear" in edge_type_str or edge_type_val == 1
|
||||||
|
or edge_type_str == "1")
|
||||||
|
is_circular = ("Circular" in edge_type_str or edge_type_val == 2
|
||||||
|
or edge_type_str == "2")
|
||||||
|
|
||||||
# Linear edges — simple
|
# Linear edges — simple
|
||||||
if is_linear:
|
if is_linear:
|
||||||
@@ -198,15 +239,12 @@ def _analyze_edge(edge: Any, lister: Any = None) -> EdgeSegment:
|
|||||||
limits = eval_obj.AskLimits(evaluator)
|
limits = eval_obj.AskLimits(evaluator)
|
||||||
t_mid = (float(limits[0]) + float(limits[1])) / 2.0
|
t_mid = (float(limits[0]) + float(limits[1])) / 2.0
|
||||||
result = eval_obj.EvaluateUnitVectors(evaluator, t_mid)
|
result = eval_obj.EvaluateUnitVectors(evaluator, t_mid)
|
||||||
# Parse point from result
|
# Parse point from result — multiple possible formats:
|
||||||
if hasattr(result, '__len__') and len(result) >= 1:
|
# 1) NXOpen.Point3d with .X/.Y/.Z
|
||||||
item = result[0] if hasattr(result[0], 'X') else result
|
# 2) Tuple of (point, tangent, ...) where point has .X/.Y/.Z
|
||||||
if hasattr(item, 'X'):
|
# 3) Nested lists/tuples like ((x,y,z), (tx,ty,tz), ...)
|
||||||
mid_pt = (float(item.X), float(item.Y), float(item.Z))
|
# 4) Flat list [x,y,z,tx,ty,tz,...]
|
||||||
elif isinstance(item, (list, tuple)) and len(item) >= 3:
|
mid_pt = _parse_eval_result(result)
|
||||||
mid_pt = (float(item[0]), float(item[1]), float(item[2]))
|
|
||||||
if mid_pt is None and hasattr(result, 'X'):
|
|
||||||
mid_pt = (float(result.X), float(result.Y), float(result.Z))
|
|
||||||
except Exception as exc2:
|
except Exception as exc2:
|
||||||
_log(f"[edge] Arc midpoint sampling failed: {exc2}")
|
_log(f"[edge] Arc midpoint sampling failed: {exc2}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user