fix(extract): discover UF curve eval methods dynamically
NXOpen Python wraps UF methods with version-specific names. Now dumps available methods on UF.Modl, UF.Eval, UF.Curve and tries them in order. Detailed logging shows which method was found and used, plus raw result format on parse failures.
This commit is contained in:
@@ -169,41 +169,118 @@ def _sample_edge_polyline(edge: Any, chord_tol_mm: float, lister: Any = None) ->
|
|||||||
f"len={length:.3f} tol={tol:.3f} n_pts={n_pts}"
|
f"len={length:.3f} tol={tol:.3f} n_pts={n_pts}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 1) Primary: UF_MODL_ask_curve_props — normalized parameter 0..1
|
# 1) Primary: UF curve evaluation — try multiple API patterns
|
||||||
try:
|
try:
|
||||||
import NXOpen
|
import NXOpen
|
||||||
import NXOpen.UF
|
import NXOpen.UF
|
||||||
|
|
||||||
uf = NXOpen.UF.UFSession.GetUFSession()
|
uf = NXOpen.UF.UFSession.GetUFSession()
|
||||||
|
|
||||||
|
# Discover the correct method name (varies by NX version)
|
||||||
|
# UF_MODL_ask_curve_props → uf.Modl.AskCurveProps or similar
|
||||||
|
modl = uf.Modl
|
||||||
|
modl_methods = [m for m in dir(modl) if 'curve' in m.lower() or 'Curve' in m]
|
||||||
|
_log(f"[edge] UF.Modl curve methods: {modl_methods}")
|
||||||
|
|
||||||
|
eval_obj = uf.Eval
|
||||||
|
eval_methods = [m for m in dir(eval_obj) if not m.startswith('_')]
|
||||||
|
_log(f"[edge] UF.Eval methods: {eval_methods}")
|
||||||
|
|
||||||
|
# Also check uf.Curve
|
||||||
|
try:
|
||||||
|
curve_obj = uf.Curve
|
||||||
|
curve_methods = [m for m in dir(curve_obj) if 'eval' in m.lower() or 'Eval' in m or 'prop' in m.lower()]
|
||||||
|
_log(f"[edge] UF.Curve eval methods: {curve_methods}")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
pts: List[Point3D] = []
|
pts: List[Point3D] = []
|
||||||
parse_failures = 0
|
parse_failures = 0
|
||||||
|
|
||||||
|
# Try each possible API in order
|
||||||
|
eval_func = None
|
||||||
|
eval_style = None
|
||||||
|
|
||||||
|
# Pattern A: uf.Modl.AskCurveProps(tag, param) — normalized 0..1
|
||||||
|
for method_name in ('AskCurveProps', 'ask_curve_props'):
|
||||||
|
fn = getattr(modl, method_name, None)
|
||||||
|
if callable(fn):
|
||||||
|
eval_func = fn
|
||||||
|
eval_style = 'modl_props'
|
||||||
|
_log(f"[edge] Using uf.Modl.{method_name}")
|
||||||
|
break
|
||||||
|
|
||||||
|
# Pattern B: uf.Eval.EvaluateUnitVectors or similar
|
||||||
|
if eval_func is None:
|
||||||
|
for method_name in eval_methods:
|
||||||
|
if 'valuat' in method_name.lower():
|
||||||
|
eval_func = getattr(eval_obj, method_name)
|
||||||
|
eval_style = 'eval_' + method_name
|
||||||
|
_log(f"[edge] Using uf.Eval.{method_name}")
|
||||||
|
break
|
||||||
|
|
||||||
|
# Pattern C: uf.Curve.EvaluateCurve(tag, param, deriv_flag)
|
||||||
|
if eval_func is None:
|
||||||
try:
|
try:
|
||||||
|
curve_obj = uf.Curve
|
||||||
|
for method_name in ('EvaluateCurve', 'evaluate_curve'):
|
||||||
|
fn = getattr(curve_obj, method_name, None)
|
||||||
|
if callable(fn):
|
||||||
|
eval_func = fn
|
||||||
|
eval_style = 'curve_eval'
|
||||||
|
_log(f"[edge] Using uf.Curve.{method_name}")
|
||||||
|
break
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if eval_func is None:
|
||||||
|
raise RuntimeError(f"No UF curve evaluation method found. Modl methods: {modl_methods}, Eval methods: {eval_methods}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
evaluator = None
|
||||||
|
if 'eval_' in (eval_style or ''):
|
||||||
|
evaluator = eval_obj.Initialize2(edge.Tag)
|
||||||
|
limits = eval_obj.AskLimits(evaluator)
|
||||||
|
t0, t1 = float(limits[0]), float(limits[1])
|
||||||
|
|
||||||
for i in range(n_pts + 1):
|
for i in range(n_pts + 1):
|
||||||
param = float(i) / float(n_pts) # 0.0 to 1.0
|
param = float(i) / float(n_pts)
|
||||||
# AskCurveProps returns: (point[3], tangent[3], normal[3], binormal[3], torsion, radius_of_curvature)
|
|
||||||
result = uf.Modl.AskCurveProps(edge.Tag, param)
|
if eval_style == 'modl_props':
|
||||||
# result[0] is the point array [x, y, z]
|
result = eval_func(edge.Tag, param)
|
||||||
if isinstance(result, (list, tuple)) and len(result) >= 1:
|
elif eval_style == 'curve_eval':
|
||||||
pt_data = result[0]
|
# UF_CURVE_evaluate_curve(tag, natural_param, deriv_flag) → output array
|
||||||
if isinstance(pt_data, (list, tuple)) and len(pt_data) >= 3:
|
# For arcs, natural param is in radians; for lines, arc length
|
||||||
pts.append((float(pt_data[0]), float(pt_data[1]), float(pt_data[2])))
|
# Use 0 = just point
|
||||||
elif hasattr(pt_data, '__len__') and len(pt_data) >= 3:
|
t = t0 + (t1 - t0) * param if evaluator else param
|
||||||
pts.append((float(pt_data[0]), float(pt_data[1]), float(pt_data[2])))
|
result = eval_func(edge.Tag, t, 0)
|
||||||
else:
|
else:
|
||||||
parse_failures += 1
|
# eval_* method on evaluator
|
||||||
|
t = t0 + (t1 - t0) * param
|
||||||
|
result = eval_func(evaluator, 0, t)
|
||||||
|
|
||||||
|
# Parse result — try multiple formats
|
||||||
|
pt = _parse_eval_point(result)
|
||||||
|
if pt is not None:
|
||||||
|
pts.append(pt)
|
||||||
else:
|
else:
|
||||||
parse_failures += 1
|
parse_failures += 1
|
||||||
|
if parse_failures <= 2:
|
||||||
|
_log(f"[edge] Parse failed at param={param:.3f}, raw type={type(result).__name__}, repr={repr(result)[:200]}")
|
||||||
finally:
|
finally:
|
||||||
|
if evaluator is not None:
|
||||||
|
try:
|
||||||
|
eval_obj.Free(evaluator)
|
||||||
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if len(pts) >= 2:
|
if len(pts) >= 2:
|
||||||
_log(f"[edge] sampled via UF_MODL ({len(pts)} pts, {parse_failures} failures)")
|
_log(f"[edge] sampled via {eval_style} ({len(pts)} pts, {parse_failures} failures)")
|
||||||
return pts
|
return pts
|
||||||
|
|
||||||
_log(f"[edge] UF_MODL insufficient points ({len(pts)}), falling back")
|
_log(f"[edge] {eval_style} insufficient points ({len(pts)}), falling back")
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
_log(f"[edge] UF_MODL failed: {exc}")
|
_log(f"[edge] UF curve eval failed: {exc}")
|
||||||
|
|
||||||
# 2) Fallback: IBaseCurve.Evaluate (signature differs by NX versions)
|
# 2) Fallback: IBaseCurve.Evaluate (signature differs by NX versions)
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user