feat(import_profile): auto-extrude after sketch creation
Full cycle now automated: 1. Delete old extrude (if exists) 2. Delete old sketch (try ReplaceFeatureBuilder first, fallback to delete) 3. Create new sketch with rib geometry 4. Extrude new sketch by rib thickness along face normal 5. Name both features for identification on next iteration Rib thickness read from profile JSON (parameters_used.thickness) with fallback to geometry JSON or default 10mm. No more manual extrude step needed between iterations.
This commit is contained in:
@@ -31,6 +31,8 @@ from typing import Any, Dict, List, Tuple
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
SKETCH_NAME_PREFIX = "ISOGRID_RIB_" # e.g., ISOGRID_RIB_sandbox_1
|
||||
EXTRUDE_NAME_PREFIX = "ISOGRID_EXTRUDE_" # e.g., ISOGRID_EXTRUDE_sandbox_1
|
||||
DEFAULT_RIB_THICKNESS = 10.0 # mm, fallback if not in profile JSON
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -279,10 +281,25 @@ def _find_or_create_sketch(
|
||||
|
||||
lister.WriteLine(f"[import] Created sketch: {sketch_name}")
|
||||
|
||||
# If old sketch existed, replace references and delete it
|
||||
if old_feature is not None and new_feature is not None:
|
||||
lister.WriteLine(f"[import] Replacing old sketch with new one...")
|
||||
_replace_and_delete_old_sketch(part, old_feature, new_feature, lister)
|
||||
# If old sketch existed, delete it (extrude will be recreated by _extrude_sketch)
|
||||
if old_feature is not None:
|
||||
import NXOpen as _NXOpen
|
||||
_session = _NXOpen.Session.GetSession()
|
||||
|
||||
# First try ReplaceFeatureBuilder to preserve downstream references
|
||||
replaced = False
|
||||
if new_feature is not None:
|
||||
lister.WriteLine(f"[import] Attempting ReplaceFeatureBuilder (old → new)...")
|
||||
try:
|
||||
_replace_and_delete_old_sketch(part, old_feature, new_feature, lister)
|
||||
replaced = True
|
||||
except Exception as exc:
|
||||
lister.WriteLine(f"[import] ReplaceFeatureBuilder failed: {exc}")
|
||||
|
||||
# Fallback: just delete old sketch (extrude will be re-created)
|
||||
if not replaced:
|
||||
lister.WriteLine(f"[import] Deleting old sketch (extrude will be re-created)...")
|
||||
_delete_feature(_session, old_feature, lister, f"old sketch {sketch_name}")
|
||||
|
||||
return sketch
|
||||
|
||||
@@ -416,6 +433,205 @@ def _draw_structured_pocket(part, pocket, transform, lister):
|
||||
return lines_drawn, arcs_drawn
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Extrude sketch
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _find_extrude_feature(part: Any, extrude_name: str, lister: Any):
|
||||
"""Find an existing extrude feature by name. Returns Feature or None."""
|
||||
try:
|
||||
for feat in part.Features:
|
||||
try:
|
||||
if feat.Name == extrude_name:
|
||||
lister.WriteLine(f"[import] Found existing extrude: {extrude_name}")
|
||||
return feat
|
||||
except Exception:
|
||||
continue
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def _delete_feature(session: Any, feature: Any, lister: Any, label: str = "feature"):
|
||||
"""Delete a feature using the update manager."""
|
||||
import NXOpen
|
||||
try:
|
||||
mark = session.SetUndoMark(NXOpen.Session.MarkVisibility.Visible,
|
||||
f"Delete {label}")
|
||||
session.UpdateManager.AddToDeleteList(feature)
|
||||
session.UpdateManager.DoUpdate(mark)
|
||||
lister.WriteLine(f"[import] Deleted {label}: {feature.JournalIdentifier}")
|
||||
return True
|
||||
except Exception as exc:
|
||||
lister.WriteLine(f"[import] WARNING: Could not delete {label}: {exc}")
|
||||
return False
|
||||
|
||||
|
||||
def _extrude_sketch(part: Any, sketch: Any, thickness: float,
|
||||
normal: List[float], extrude_name: str, lister: Any):
|
||||
"""
|
||||
Extrude all curves in the sketch by `thickness` along the face normal.
|
||||
Creates a new Extrude feature named `extrude_name`.
|
||||
|
||||
If an old extrude with the same name exists, delete it first.
|
||||
"""
|
||||
import NXOpen
|
||||
|
||||
session = NXOpen.Session.GetSession()
|
||||
|
||||
# Delete old extrude if it exists
|
||||
old_extrude = _find_extrude_feature(part, extrude_name, lister)
|
||||
if old_extrude is not None:
|
||||
_delete_feature(session, old_extrude, lister, f"old extrude {extrude_name}")
|
||||
|
||||
lister.WriteLine(f"[import] Extruding sketch by {thickness} mm along normal")
|
||||
|
||||
mark = session.SetUndoMark(NXOpen.Session.MarkVisibility.Visible,
|
||||
f"Extrude {extrude_name}")
|
||||
|
||||
try:
|
||||
# Create ExtrudeBuilder (null feature = new extrude)
|
||||
builder = part.Features.CreateExtrudeBuilder(
|
||||
NXOpen.Features.Feature.Null
|
||||
)
|
||||
|
||||
# Set the section: use sketch curves
|
||||
# Get all curves from the sketch
|
||||
sketch_feature = sketch.Feature
|
||||
curves = []
|
||||
try:
|
||||
# Try getting sketch geometry objects
|
||||
geom = sketch.GetAllGeometry()
|
||||
for obj in geom:
|
||||
curves.append(obj)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not curves:
|
||||
# Fallback: get curves from feature's entities
|
||||
try:
|
||||
entities = sketch_feature.GetEntities()
|
||||
for ent in entities:
|
||||
if hasattr(ent, 'StartPoint') or hasattr(ent, 'GetLength'):
|
||||
curves.append(ent)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
lister.WriteLine(f"[import] Found {len(curves)} curves in sketch for extrude")
|
||||
|
||||
# Create section and add curves
|
||||
section = part.Sections.CreateSection(
|
||||
0.0095, # chaining tolerance
|
||||
0.01, # distance tolerance
|
||||
0.5, # angle tolerance
|
||||
)
|
||||
section.SetAllowedEntityTypes(
|
||||
NXOpen.Section.AllowTypes.OnlyCurves
|
||||
)
|
||||
|
||||
# Add sketch curves to the section
|
||||
sketch_feature_tag = sketch.Feature
|
||||
curves_added = False
|
||||
|
||||
# Method 1: Add the sketch feature directly as section input
|
||||
try:
|
||||
feature_rule = part.ScRuleFactory.CreateRuleFeatureCurves(
|
||||
[sketch_feature_tag]
|
||||
)
|
||||
section.AllowSelfIntersection(True)
|
||||
help_pt = NXOpen.Point3d(0, 0, 0)
|
||||
section.AddToSection(
|
||||
[feature_rule],
|
||||
NXOpen.NXObject.Null, # seed
|
||||
NXOpen.NXObject.Null, # start connector
|
||||
NXOpen.NXObject.Null, # end connector
|
||||
help_pt,
|
||||
NXOpen.Section.Mode.Create,
|
||||
False, # go to end
|
||||
)
|
||||
curves_added = True
|
||||
lister.WriteLine("[import] Added sketch curves to section via FeatureCurves rule")
|
||||
except Exception as exc:
|
||||
lister.WriteLine(f"[import] FeatureCurves rule failed: {exc}")
|
||||
|
||||
if not curves_added and curves:
|
||||
# Method 2: Add individual curves
|
||||
try:
|
||||
curve_rule = part.ScRuleFactory.CreateRuleCurveDumb(curves)
|
||||
help_pt = NXOpen.Point3d(0, 0, 0)
|
||||
section.AddToSection(
|
||||
[curve_rule],
|
||||
curves[0],
|
||||
NXOpen.NXObject.Null,
|
||||
NXOpen.NXObject.Null,
|
||||
help_pt,
|
||||
NXOpen.Section.Mode.Create,
|
||||
False,
|
||||
)
|
||||
curves_added = True
|
||||
lister.WriteLine("[import] Added curves via CurveDumb rule")
|
||||
except Exception as exc:
|
||||
lister.WriteLine(f"[import] CurveDumb rule failed: {exc}")
|
||||
|
||||
if not curves_added:
|
||||
lister.WriteLine("[import] ERROR: Could not add curves to extrude section")
|
||||
builder.Destroy()
|
||||
return None
|
||||
|
||||
builder.Section = section
|
||||
|
||||
# Set direction (along face normal)
|
||||
direction = part.Directions.CreateDirection(
|
||||
NXOpen.Point3d(0, 0, 0),
|
||||
NXOpen.Vector3d(normal[0], normal[1], normal[2]),
|
||||
NXOpen.SmartObject.UpdateOption.WithinModeling,
|
||||
)
|
||||
builder.Direction = direction
|
||||
|
||||
# Set limits: start=0, end=thickness
|
||||
builder.Limits.StartExtend.Value.RightHandSide = "0"
|
||||
builder.Limits.EndExtend.Value.RightHandSide = str(thickness)
|
||||
|
||||
# Boolean: create (no unite/subtract for now — idealized model)
|
||||
builder.BooleanOperation.Type = NXOpen.GeometricUtilities.BooleanOperation.BooleanType.Create
|
||||
|
||||
# Commit
|
||||
extrude_obj = builder.Commit()
|
||||
builder.Destroy()
|
||||
|
||||
# Rename the extrude feature
|
||||
committed = builder.GetCommittedObjects() if hasattr(builder, 'GetCommittedObjects') else []
|
||||
extrude_feature = None
|
||||
|
||||
if isinstance(extrude_obj, NXOpen.Features.Feature):
|
||||
extrude_feature = extrude_obj
|
||||
else:
|
||||
# Find the most recently created extrude feature
|
||||
for feat in part.Features:
|
||||
try:
|
||||
if "Extrude" in feat.FeatureType and feat.Name == "":
|
||||
extrude_feature = feat
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if extrude_feature is not None:
|
||||
try:
|
||||
extrude_feature.SetName(extrude_name)
|
||||
lister.WriteLine(f"[import] Extrude created and named: {extrude_name}")
|
||||
except Exception:
|
||||
lister.WriteLine(f"[import] Extrude created (could not rename)")
|
||||
else:
|
||||
lister.WriteLine(f"[import] Extrude committed (feature reference unclear)")
|
||||
|
||||
return extrude_feature
|
||||
|
||||
except Exception as exc:
|
||||
lister.WriteLine(f"[import] ERROR creating extrude: {exc}")
|
||||
import traceback
|
||||
lister.WriteLine(traceback.format_exc())
|
||||
return None
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Main
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -588,8 +804,25 @@ def main():
|
||||
|
||||
lister.WriteLine(f"[import] Pockets: {len(pockets)}")
|
||||
|
||||
# --- Auto-extrude ---
|
||||
rib_thickness = profile.get("parameters_used", {}).get("thickness",
|
||||
geometry.get("thickness", DEFAULT_RIB_THICKNESS))
|
||||
if rib_thickness is None:
|
||||
rib_thickness = DEFAULT_RIB_THICKNESS
|
||||
normal = transform["normal"]
|
||||
extrude_name = EXTRUDE_NAME_PREFIX + sandbox_id
|
||||
|
||||
extrude_feat = _extrude_sketch(
|
||||
work_part, sketch, rib_thickness, normal, extrude_name, lister
|
||||
)
|
||||
if extrude_feat is not None:
|
||||
lister.WriteLine(f"[import] ✓ Sketch + Extrude complete for {sandbox_id}")
|
||||
else:
|
||||
lister.WriteLine(f"[import] ⚠ Sketch created but extrude failed — extrude manually")
|
||||
lister.WriteLine(f"[import] Thickness: {rib_thickness} mm along normal {normal}")
|
||||
|
||||
lister.WriteLine("\n" + "=" * 60)
|
||||
lister.WriteLine(" Import complete — extrude the sketch to rib thickness")
|
||||
lister.WriteLine(" Import complete")
|
||||
lister.WriteLine("=" * 60)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user