fix: replace face.GetLoops() with compatible API (GetEdgeLoops / UF layer / GetEdges fallback)
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user