' ============================================================================= ' NX Journal: rebuild test master + diagnose why translator sees 0 solids (NX 2506) ' ' Hypothesis to test: UF CreateCyl1 built bodies that Part.Bodies counts (=2) ' but the STEP translator reports "0 solids". Suspect: unitless expressions ' ("bore=32" with no mm unit) produce degenerate/empty-shell bodies. ' ' This script: ' Phase 1 (single session, no reopen): ' OpenBaseDisplay -> ensure expressions WITH units (bore/stroke = mm) -> ' CreateCyl1 -> Update -> report body count AND face count per body -> ' add to MODEL refset -> export STEP (DisplayPart) -> Save -> ' export STEP again via ExistingPart (reads the saved file from disk). ' The face count tells us if bodies are real solids (cylinder ~3 faces) ' or empty shells (0 faces). The ExistingPart export tells us if the solids ' actually persisted to the .prt on disk. ' ' Run (run_journal takes one arg; use WorkingDirectory): ' WorkingDirectory = catalog-masters\KC (the .bat does "cd /d %~dp0") ' run_journal.exe ' Result log: \rebuild-verify-master.txt Products: \dbg_out\ ' ' Note: English comments only (avoids GBK/BOM mojibake on no-BOM .vb files). ' ============================================================================= Option Strict Off Imports System Imports System.IO Imports System.Text Imports NXOpen Imports NXOpen.UF Module RebuildVerifyMaster Dim theSession As Session = Session.GetSession() Dim sb As New StringBuilder() Sub Log(s As String) sb.AppendLine(s) End Sub Sub Main() Try Run() Catch ex As Exception Log("[FATAL] " & ex.GetType().Name & " / " & ex.Message) End Try File.WriteAllText(Path.Combine(Directory.GetCurrentDirectory(), "rebuild-verify-master.txt"), sb.ToString(), New UTF8Encoding(True)) End Sub Sub Run() Dim cur As String = Directory.GetCurrentDirectory() Dim masterPath As String = Path.Combine(cur, "KC_master.prt") Log("CWD=" & cur) Log("masterExists=" & File.Exists(masterPath)) If Not File.Exists(masterPath) Then Log("[FAIL] master file missing: " & masterPath) Return End If Try File.SetAttributes(masterPath, File.GetAttributes(masterPath) And Not FileAttributes.ReadOnly) Catch ex As Exception Log("clear readonly: " & ex.Message) End Try Dim outDir As String = Path.Combine(cur, "dbg_out") Directory.CreateDirectory(outDir) Dim pls As NXOpen.PartLoadStatus = Nothing Dim bp As NXOpen.BasePart = theSession.Parts.OpenBaseDisplay(masterPath, pls) If pls IsNot Nothing Then pls.Dispose() Dim w As Part = theSession.Parts.Work If w Is Nothing Then Log("[FAIL] OpenBaseDisplay -> Work=NULL") Return End If Log("Work=" & w.FullPath) Log("bodiesBefore=" & CountBodies(w)) ' mm unit object (for length-typed expressions). Fall back to no unit. Dim mm As NXOpen.Unit = w.UnitCollection.FindObject("MilliMeter") If mm Is Nothing Then mm = w.UnitCollection.FindObject("Millimetre") Log("unit mm=" & (If(mm Is Nothing, "NULL", mm.ToString()))) EnsureExprWithUnit(w, "bore", "32", mm) EnsureExprWithUnit(w, "stroke", "10", mm) EnsureExprNoUnit(w, "magOn", "0") EnsureExprNoUnit(w, "mountIdx", "0") Log("expr bore=" & ExprVal(w, "bore") & " stroke=" & ExprVal(w, "stroke") & " magOn=" & ExprVal(w, "magOn") & " mountIdx=" & ExprVal(w, "mountIdx")) If CountBodies(w) = 0 Then Dim ufs As UFSession = UFSession.GetUFSession() Dim origin(2) As Double Dim dir(2) As Double dir(2) = 1.0 Dim t1 As Tag Dim t2 As Tag ufs.Modl.CreateCyl1(NXOpen.UF.FeatureSigns.Nullsign, origin, "stroke", "bore+8", dir, t1) ufs.Modl.CreateCyl1(NXOpen.UF.FeatureSigns.Nullsign, origin, "stroke+30", "bore*0.33", dir, t2) Log("created 2 cylinders (tags " & t1.ToString() & ", " & t2.ToString() & ")") Else Log("solids already exist, skip creation") End If Dim u2 As UFSession = UFSession.GetUFSession() u2.Modl.Update() Log("afterUpdate bodies=" & CountBodies(w)) DumpBodyFaces(w) AddToModelRefset(w) Log("afterRefset bodies=" & CountBodies(w)) ' ---- TEST A: DisplayPart export of in-memory bodies ---- ExportStep(Path.Combine(outDir, "A_display.stp")) Log("A_display.stp size=" & FileSize(Path.Combine(outDir, "A_display.stp"))) ' ---- Save so the bodies (hopefully) persist to the .prt ---- Try Dim pss As NXOpen.PartSaveStatus = w.Save(NXOpen.BasePart.SaveComponents.True, NXOpen.BasePart.CloseAfterSave.False) If pss IsNot Nothing Then pss.Dispose() Log("save OK") Catch ex As Exception Log("save FAIL: " & ex.Message) End Try ' ---- TEST B: ExistingPart export reads the SAVED file from disk ---- ExportStepExisting(masterPath, Path.Combine(outDir, "B_existing.stp")) Log("B_existing.stp size=" & FileSize(Path.Combine(outDir, "B_existing.stp"))) Log("DONE") End Sub ' ---- helpers ---- Function CountBodies(w As Part) As Integer Dim n As Integer = 0 Try For Each b As NXOpen.Body In w.Bodies n += 1 Next Catch End Try Return n End Function ' Count faces per body. A real cylinder ~3 faces; 0 faces = empty shell. Sub DumpBodyFaces(w As Part) Dim i As Integer = 0 Try For Each b As NXOpen.Body In w.Bodies i += 1 Dim fc As Integer = 0 Try For Each f As NXOpen.Face In b.GetFaces() fc += 1 Next Catch End Try Log("body" & i & " faces=" & fc) Next Catch ex As Exception Log("DumpBodyFaces FAIL: " & ex.Message) End Try End Sub Sub EnsureExprWithUnit(w As Part, name As String, val As String, mm As NXOpen.Unit) Try If w.Expressions.FindObject(name) IsNot Nothing Then Return Catch End Try Try If mm IsNot Nothing Then w.Expressions.CreateExpressionWithUnit("Number", name & "=" & val, mm) Else w.Expressions.CreateExpression("Number", name & "=" & val) End If Catch ex As Exception Log("EnsureExprWithUnit " & name & ": " & ex.Message) End Try End Sub Sub EnsureExprNoUnit(w As Part, name As String, val As String) Try If w.Expressions.FindObject(name) IsNot Nothing Then Return Catch End Try Try w.Expressions.CreateExpression("Number", name & "=" & val) Catch ex As Exception Log("EnsureExprNoUnit " & name & ": " & ex.Message) End Try End Sub Function ExprVal(w As Part, name As String) As String Try Dim e As NXOpen.Expression = w.Expressions.FindObject(name) If e IsNot Nothing Then Return e.Value Catch End Try Return "(missing)" End Function Sub AddToModelRefset(w As Part) Try Dim bodyList As New System.Collections.Generic.List(Of NXOpen.NXObject)() For Each b As NXOpen.Body In w.Bodies bodyList.Add(b) Next If bodyList.Count = 0 Then Log("AddToModelRefset: no bodies") Return End If Dim added As Boolean = False For Each rs As NXOpen.ReferenceSet In w.GetAllReferenceSets() If rs.Name.ToUpperInvariant().Contains("MODEL") Then rs.AddObjectsToReferenceSet(bodyList.ToArray()) Log("added " & bodyList.Count & " bodies to refset '" & rs.Name & "'") added = True Exit For End If Next If Not added Then Log("AddToModelRefset: no MODEL refset (refsets: " & RefsetNames(w) & ")") End If Catch ex As Exception Log("AddToModelRefset FAIL: " & ex.Message) End Try End Sub Function RefsetNames(w As Part) As String Dim s As String = "" Try For Each rs As NXOpen.ReferenceSet In w.GetAllReferenceSets() If s.Length > 0 Then s &= ", " s &= rs.Name Next Catch End Try Return s End Function Function FileSize(p As String) As String If Not File.Exists(p) Then Return "MISSING" Return (New FileInfo(p)).Length & " bytes" End Function ' ---- export functions ---- Sub ExportStep(fileName As String) If File.Exists(fileName) Then File.Delete(fileName) Try Dim sc As NXOpen.StepCreator = theSession.DexManager.CreateStepCreator() sc.ExportFrom = NXOpen.StepCreator.ExportFromOption.DisplayPart sc.ExportAs = NXOpen.StepCreator.ExportAsOption.Ap214 sc.OutputFile = fileName sc.ColorAndLayers = True sc.Commit() sc.Destroy() Catch ex As Exception Log("ExportStep FAIL: " & ex.Message) End Try End Sub Sub ExportStepExisting(inputFile As String, fileName As String) If File.Exists(fileName) Then File.Delete(fileName) Try Dim sc As NXOpen.StepCreator = theSession.DexManager.CreateStepCreator() sc.ExportFrom = NXOpen.StepCreator.ExportFromOption.ExistingPart sc.InputFile = inputFile sc.ExportAs = NXOpen.StepCreator.ExportAsOption.Ap214 sc.OutputFile = fileName sc.ColorAndLayers = True sc.Commit() sc.Destroy() Catch ex As Exception Log("ExportStepExisting FAIL: " & ex.Message) End Try End Sub End Module