fix: replace face.GetLoops() with compatible API (GetEdgeLoops / UF layer / GetEdges fallback)

This commit is contained in:
2026-02-16 17:42:08 +00:00
parent 1166741ffd
commit 851a8d3df0

View File

@@ -136,12 +136,92 @@ def _close_polyline(points: List[Point3D]) -> List[Point3D]:
# Face local frame
# ---------------------------------------------------------------------------
def _face_local_frame(face: Any) -> LocalFrame:
def _get_face_loops(face: Any, lister: Any = None) -> List[Tuple[bool, List[Any]]]:
"""
Get edge loops from an NX face.
Returns list of (is_outer, [edges]) tuples.
Tries multiple NX API patterns:
1. face.GetEdgeLoops() (NX 2306+)
2. UF layer: UF.Modeling.ask_face_loops()
3. Fallback: all edges as single outer loop
"""
def _log(msg):
if lister:
lister.WriteLine(msg)
# Method 1: GetEdgeLoops (modern NX)
try:
edge_loops = face.GetEdgeLoops()
if edge_loops:
result = []
for i, el in enumerate(edge_loops):
edges = el.GetEdges() if hasattr(el, "GetEdges") else list(el)
is_outer = (i == 0) # first loop is typically outer
try:
is_outer = el.IsOuter() if hasattr(el, "IsOuter") else (i == 0)
except Exception:
pass
result.append((is_outer, list(edges)))
_log(f"[loops] GetEdgeLoops: {len(result)} loop(s)")
return result
except Exception:
pass
# Method 2: UF layer
try:
import NXOpen
session = NXOpen.Session.GetSession()
uf = session.GetUFSession()
face_tag = face.Tag
loop_count = [0]
loop_list = uf.Modeling.AskFaceLoops(face_tag)
# loop_list is (num_loops, loop_tags[])
if loop_list and len(loop_list) >= 2:
num_loops = loop_list[0]
loop_tags = loop_list[1]
result = []
for li in range(num_loops):
loop_tag = loop_tags[li]
# Get edges from loop
edge_info = uf.Modeling.AskLoopListOfEdges(loop_tag)
edges_tags = edge_info[1] if len(edge_info) >= 2 else []
edges = []
for et in edges_tags:
try:
edge_obj = NXOpen.TaggedObjectManager.GetTaggedObject(et)
edges.append(edge_obj)
except Exception:
pass
is_outer_val = uf.Modeling.AskLoopType(loop_tag)
is_outer = (is_outer_val == 1) # 1 = outer, 2 = inner typically
result.append((is_outer, edges))
_log(f"[loops] UF layer: {len(result)} loop(s)")
return result
except Exception:
pass
# Method 3: Fallback — all edges as single outer loop
try:
all_edges = face.GetEdges()
if all_edges:
edges = list(all_edges)
_log(f"[loops] Fallback: {len(edges)} edges as single outer loop")
return [(True, edges)]
except Exception:
pass
return []
def _face_local_frame(face: Any, lister: Any = None) -> LocalFrame:
"""
Build a stable local frame on a planar face.
"""
loops = face.GetLoops()
first_edge = loops[0].GetEdges()[0]
# Get a sample point from the first edge
edges = face.GetEdges()
first_edge = edges[0]
sample = _sample_edge_polyline(first_edge, chord_tol_mm=1.0)[0]
# Get face normal
@@ -387,17 +467,16 @@ def extract_sandbox_geometry(
Extract a sandbox face into a JSON-serializable dict.
Inner loops are boundary constraints (reserved geometry edges), not holes.
"""
frame = _face_local_frame(face)
frame = _face_local_frame(face, lister)
outer_2d: List[List[float]] = []
inner_boundaries: List[Dict[str, Any]] = []
loops = face.GetLoops()
loops = _get_face_loops(face, lister)
lister.WriteLine(f"[extract_sandbox] {sandbox_id}: {len(loops)} loop(s)")
for loop_index, loop in enumerate(loops):
for loop_index, (is_outer, edges) in enumerate(loops):
loop_pts3d: List[Point3D] = []
edges = loop.GetEdges()
for edge in edges:
pts = _sample_edge_polyline(edge, chord_tol_mm)
if loop_pts3d and pts:
@@ -407,13 +486,6 @@ def extract_sandbox_geometry(
loop_pts3d = _close_polyline(loop_pts3d)
loop_pts2d = project_to_2d(loop_pts3d, frame)
# Determine outer vs inner
is_outer = False
try:
is_outer = loop.IsOuter()
except Exception:
is_outer = (loop_index == 0)
if is_outer:
outer_2d = [[round(x, 6), round(y, 6)] for x, y in loop_pts2d]
lister.WriteLine(f"[extract_sandbox] outer loop: {len(outer_2d)} pts")
@@ -494,13 +566,10 @@ def main():
# Debug: print face info
lister.WriteLine(f"[extract_sandbox] Face type: {type(face).__name__}")
try:
loops = face.GetLoops()
lister.WriteLine(f"[extract_sandbox] Loops: {len(loops)}")
for li, loop in enumerate(loops):
edges = loop.GetEdges()
lister.WriteLine(f"[extract_sandbox] Loop {li}: {len(edges)} edges")
all_edges = face.GetEdges()
lister.WriteLine(f"[extract_sandbox] Total edges on face: {len(all_edges)}")
except Exception as exc:
lister.WriteLine(f"[extract_sandbox] GetLoops failed: {exc}")
lister.WriteLine(f"[extract_sandbox] GetEdges failed: {exc}")
geom = extract_sandbox_geometry(
face=face,