fix: strip closing duplicate points in triangulation (segfault fix), batch line creation for NX speed, 6mm endmill params

This commit is contained in:
2026-02-16 19:29:41 +00:00
parent 61dcefb5ea
commit c93239c9c6
3 changed files with 34482 additions and 86728 deletions

View File

@@ -62,7 +62,12 @@ def build_pslg(geometry, params):
hole_markers = [] hole_markers = []
# Outer boundary (no offset needed — frame is handled in profile assembly) # Outer boundary (no offset needed — frame is handled in profile assembly)
outer = geometry['outer_boundary'] outer = list(geometry['outer_boundary'])
# Strip closing duplicate if last == first
if len(outer) > 2:
d = np.linalg.norm(np.array(outer[0]) - np.array(outer[-1]))
if d < 0.01:
outer = outer[:-1]
v_start = len(vertices) v_start = len(vertices)
vertices.extend(outer) vertices.extend(outer)
n = len(outer) n = len(outer)
@@ -84,6 +89,11 @@ def build_pslg(geometry, params):
# Fallback for non-circular holes # Fallback for non-circular holes
keepout_boundary = offset_polygon(hole['boundary'], keepout_dist, inward=False) keepout_boundary = offset_polygon(hole['boundary'], keepout_dist, inward=False)
# Strip closing duplicate if present
if len(keepout_boundary) > 2:
d = np.linalg.norm(np.array(keepout_boundary[0]) - np.array(keepout_boundary[-1]))
if d < 0.01:
keepout_boundary = keepout_boundary[:-1]
v_start = len(vertices) v_start = len(vertices)
vertices.extend(keepout_boundary) vertices.extend(keepout_boundary)
n_h = len(keepout_boundary) n_h = len(keepout_boundary)

View File

@@ -246,30 +246,36 @@ def _find_or_create_sketch(
return sketch return sketch
def _draw_polyline_in_sketch( def _draw_polylines_batch(
part: Any, part: Any,
sketch: Any, sketch: Any,
points_3d: List[Tuple[float, float, float]], polylines_3d: List[List[Tuple[float, float, float]]],
lister: Any, lister: Any,
close: bool = True, close: bool = True,
) -> int: ) -> int:
""" """
Draw a closed polyline in the sketch using individual line segments. Draw multiple closed polylines in the sketch efficiently.
Returns number of lines created.
Creates all lines as NX curves first (fast), then adds them
to the sketch in one batch call (much faster than per-line builders).
Returns total number of lines created.
""" """
import NXOpen import NXOpen
all_lines = []
total_lines = 0
for points_3d in polylines_3d:
if len(points_3d) < 2: if len(points_3d) < 2:
return 0 continue
lines_created = 0
n = len(points_3d) n = len(points_3d)
# Strip closing duplicate
# If last point == first point, don't double-close if close and n >= 3:
if close and len(points_3d) >= 3:
d = math.sqrt(sum((a - b) ** 2 for a, b in zip(points_3d[0], points_3d[-1]))) d = math.sqrt(sum((a - b) ** 2 for a, b in zip(points_3d[0], points_3d[-1])))
if d < 0.001: if d < 0.001:
n = len(points_3d) - 1 # skip duplicate closing point n = n - 1
segments = n if close else (n - 1) segments = n if close else (n - 1)
@@ -278,37 +284,59 @@ def _draw_polyline_in_sketch(
p2 = points_3d[(i + 1) % n] p2 = points_3d[(i + 1) % n]
try: try:
start_pt = NXOpen.Point3d(p1[0], p1[1], p1[2]) # CurveCollection.CreateLine(start: Point, end: Point) -> Line
end_pt = NXOpen.Point3d(p2[0], p2[1], p2[2]) start_obj = part.Points.CreatePoint(
NXOpen.Point3d(p1[0], p1[1], p1[2])
# SketchCollection.CreateLineBuilder() -> SketchLineBuilder )
# SketchLineBuilder.SetStartPoint(Point3d), .SetEndPoint(Point3d) end_obj = part.Points.CreatePoint(
# Builder.Commit() -> NXObject, Builder.Destroy() NXOpen.Point3d(p2[0], p2[1], p2[2])
line_builder = part.Sketches.CreateLineBuilder() )
line_builder.SetStartPoint(start_pt)
line_builder.SetEndPoint(end_pt)
line_builder.Commit()
line_builder.Destroy()
lines_created += 1
except Exception as exc:
if lines_created == 0:
lister.WriteLine(f"[import] Line creation failed: {exc}")
# Try fallback: create curve + add to sketch
try:
start_obj = part.Points.CreatePoint(NXOpen.Point3d(p1[0], p1[1], p1[2]))
end_obj = part.Points.CreatePoint(NXOpen.Point3d(p2[0], p2[1], p2[2]))
line = part.Curves.CreateLine(start_obj, end_obj) line = part.Curves.CreateLine(start_obj, end_obj)
all_lines.append(line)
total_lines += 1
except Exception as exc:
if total_lines == 0:
lister.WriteLine(f"[import] CreateLine failed: {exc}")
# Try SketchLineBuilder as fallback for first line
try:
lb = part.Sketches.CreateLineBuilder()
lb.SetStartPoint(NXOpen.Point3d(p1[0], p1[1], p1[2]))
lb.SetEndPoint(NXOpen.Point3d(p2[0], p2[1], p2[2]))
lb.Commit()
lb.Destroy()
total_lines += 1
lister.WriteLine("[import] SketchLineBuilder fallback worked")
except Exception as exc2:
lister.WriteLine(f"[import] Both methods failed: {exc2}")
return 0
# Add all curves to sketch in one batch call
if all_lines:
try:
# Sketch.AddGeometry(infer, ellipse, curves)
sketch.AddGeometry(
NXOpen.Sketch.InferConstraintsOption.DoNotInferConstraints,
NXOpen.Sketch.AddEllipseOption.None_,
all_lines,
)
lister.WriteLine(f"[import] Added {len(all_lines)} lines to sketch via AddGeometry")
except Exception as exc:
lister.WriteLine(f"[import] AddGeometry batch failed: {exc}")
# Try adding one by one
added = 0
for line in all_lines:
try:
sketch.AddGeometry( sketch.AddGeometry(
NXOpen.Sketch.InferConstraintsOption.DoNotInferConstraints, NXOpen.Sketch.InferConstraintsOption.DoNotInferConstraints,
NXOpen.Sketch.AddEllipseOption.None_, NXOpen.Sketch.AddEllipseOption.None_,
[line], [line],
) )
lines_created += 1 added += 1
except Exception as exc2: except Exception:
lister.WriteLine(f"[import] Fallback line also failed: {exc2}") pass
lister.WriteLine(f"[import] Added {added}/{len(all_lines)} lines individually")
return lines_created return total_lines
def _draw_circle_in_sketch( def _draw_circle_in_sketch(
@@ -479,28 +507,30 @@ def main():
total_lines = 0 total_lines = 0
# Draw outer boundary # Collect all polylines to draw
all_polylines_3d = []
# Outer boundary
outer_2d = profile.get("outer_boundary", []) outer_2d = profile.get("outer_boundary", [])
if outer_2d: if outer_2d:
outer_3d = unproject_to_3d(outer_2d, transform) outer_3d = unproject_to_3d(outer_2d, transform)
n = _draw_polyline_in_sketch(work_part, sketch, outer_3d, lister, close=True) all_polylines_3d.append(outer_3d)
total_lines += n
lister.WriteLine(f"[import] Outer boundary: {n} lines")
# Draw pocket cutouts # Pocket cutouts
pockets = profile.get("pockets", []) pockets = profile.get("pockets", [])
lister.WriteLine(f"[import] Drawing {len(pockets)} pockets...") lister.WriteLine(f"[import] Preparing {len(pockets)} pockets + outer boundary...")
for pi, pocket_pts in enumerate(pockets): for pocket_pts in pockets:
if len(pocket_pts) < 3: if len(pocket_pts) < 3:
continue continue
pocket_3d = unproject_to_3d(pocket_pts, transform) pocket_3d = unproject_to_3d(pocket_pts, transform)
n = _draw_polyline_in_sketch(work_part, sketch, pocket_3d, lister, close=True) all_polylines_3d.append(pocket_3d)
total_lines += n
# Progress every 50 pockets # Draw everything in one batch
if (pi + 1) % 50 == 0: lister.WriteLine(f"[import] Creating {len(all_polylines_3d)} polylines as NX curves...")
lister.WriteLine(f"[import] ... {pi + 1}/{len(pockets)} pockets drawn") total_lines = _draw_polylines_batch(
work_part, sketch, all_polylines_3d, lister, close=True,
)
# Deactivate sketch # Deactivate sketch
try: try:

File diff suppressed because it is too large Load Diff