← Macro & add-in library

DXF & fabrication · Active export / V15 header

Active-Document Waterjet DXF Export

A SolidWorks VBA exporter for cut-list bodies using manufacturing properties and geometry-aware orientation.

ENGINEERING CONTRIBUTION

Integrated assembly recursion, unique part/configuration handling, export eligibility rules, and view-orientation logic.

Prerequisites

  • SolidWorks VBA on Windows; a saved part, assembly, or a drawing with the intended view selected.
  • DXF=YES manufacturing properties on eligible cut-list items or qualifying regular parts; DXY is a legacy fallback.
  • Configure local drawing templates and verify the intended source configuration and output units.

Additional setup

  • Configure CUSTOM_DRAWING_TEMPLATE when using drawing-based export routes.

SOURCE WALKTHROUGH

How the workflow fits together.

  1. 01

    Dispatch by document type

    main validates the active model, handles parts or assemblies, or resolves the selected drawing view's referenced part/configuration and orientation.

  2. 02

    Gate and deduplicate

    Assembly traversal processes unique part/configuration combinations. Evaluated DXF properties gate eligible cut-list items; regular parts use separate part-level rules.

  3. 03

    Orient manufacturing geometry

    Largest planar faces and a staged tab-aware/shared-corner/virtual-corner/longest-edge decision stack establish an export frame.

  4. 04

    Export and normalize

    Direct and temporary-part routes produce DXFs in WATERJET_DXF. Postprocessing corrects 2D roll/orientation; duplicate output names receive suffixes.

Output & model changes

  • Creates output folders, DXFs and temporary documents/files.
  • Can activate configurations, hide sketches, change views and rebuild models during export.
  • The direct temporary-part toggle forces inch units; confirm the downstream DXF scale.

CODE & ENTRY POINTS

Read the implementation.

Find a procedure, follow an API call or download the module for your SolidWorks setup.

ActiveDocumentDxf.bas

Active-document export dispatcher, cut-list eligibility checks, configuration traversal, geometry-based export orientation and DXF postprocessing.

VBA · 6,702 lines

Download .bas

Entry points
API & integration calls
Selected line 1
Attribute VB_Name = "AUTO_DXF_SAVE1"
Option Explicit

'=========================================================================================
' WATERJET_DXF_FROM_WELDMENT_CUTLIST_V15_DRAWING_VIEW_ORIENTATION
'
' PURPOSE
'   Production-oriented macro for weldment DXF export:
'
'   PART MODE
'   - Runs on the active part
'   - If the part has real cut-list folders, it is treated as weldment / cut-list mode
'   - Reads evaluated cut-list property "DXF"
'   - For single-body parts, if cut-list DXF is blank, falls back to part property DXF (then legacy DXY)
'   - Exports only qualifying cut-list items where the effective DXF flag resolves to YES
'   - If the part is a regular part (no real cut-list folders), checks part property "DXF" first, then legacy "DXY" as fallback
'   - Exports the whole part only when the part-level export flag resolves to YES
'
'   ASSEMBLY MODE
'   - Runs on the active assembly
'   - Recursively traverses all components / subassemblies
'   - Processes each unique PART + CONFIGURATION once
'   - Exports eligible cut-list items or regular parts from each qualifying part
'
'   EXPORT RULES
'   - Uses largest planar face as export normal
'   - If configuration WATERJET_CUT exists, that configuration is used for nesting/export
'   - Otherwise uses the referenced / active configuration as normal
'   - Uses the two longest perpendicular straight edges that share a corner when available
'   - If a longer non-intersecting perpendicular pair exists, it overrides the shared-corner pair to ignore chamfers
'   - Orients that shared or virtual corner as the bottom-left export corner
'   - If no shared-corner perpendicular pair exists, uses the two longest perpendicular straight edges even when separated by chamfers/gaps
'   - Falls back to longest straight edge horizontal when no suitable perpendicular pair exists
'   - Writes DXFs into <active model folder>\WATERJET_DXF
'   - Multi-body uses PART NUMBER.dxf; single-body parts use saved part file name directly
'   - Single-body parts export directly from the source part using the oriented current view
'   - Multi-body / isolated cut-list bodies still use direct temp-part DXF export by named view
'   - Hides sketches before DXF export to avoid stray sketch geometry
'   - DRAWING MODE: if the active doc is a drawing and a drawing view is selected,
'     the macro uses that view orientation for DXF export and uses the view's
'     referenced part/configuration as the source model state
'
' NOTES
'   - Duplicate output names are auto-resolved with _01, _02, etc.
'   - If a component part is used multiple times in the assembly with the same
'     referenced configuration, it is only processed once.
'   - If the same part is used in multiple different configurations, each unique
'     configuration is processed once.
'
'=========================================================================================

'------------------------------------------
' SolidWorks app/document globals
'------------------------------------------
Private swApp           As SldWorks.SldWorks
Private swModel         As SldWorks.ModelDoc2
Private swPart          As SldWorks.PartDoc
Private swExt           As SldWorks.ModelDocExtension
Private swMathUtil      As SldWorks.MathUtility

'------------------------------------------
' Settings
'------------------------------------------
Private Const OUT_FOLDER_NAME               As String = "WATERJET_DXF"
Private Const PROP_DXF                      As String = "DXF"
Private Const PROP_DXY                      As String = "DXY"
Private Const PROP_PARTNO                   As String = "PART NUMBER"
Private Const PROP_TRUE_VALUE               As String = "YES"

Private Const EPS                           As Double = 0.0000001
Private Const PT_TOL                        As Double = 0.000001
Private Const PERP_DOT_TOL                  As Double = 0.001
Private Const SHEET_MARGIN_M                As Double = 0.05
Private Const MIN_SHEET_W_M                 As Double = 0.3
Private Const MIN_SHEET_H_M                 As Double = 0.2
Private Const TEMP_PREFIX                   As String = "WJDXF_"
Private Const TEMP_VIEW_NAME                As String = "WATERJET_EXPORT_VIEW"
Private Const PI_VAL                        As Double = 3.14159265358979
Private Const CUSTOM_DRAWING_TEMPLATE       As String = "C:\Public\Templates\Blank.drwdot"

'------------------------------------------
' Direct temp-part DXF export toggles
'------------------------------------------
Private Const USE_FAST_MODE                             As Boolean = True
Private Const FAST_MODE_PRESERVE_LEGACY_OUTPUT         As Boolean = False
Private Const FAST_MODE_SINGLE_TEMP_PART_SAVE          As Boolean = True
Private Const FAST_MODE_SKIP_TEMP_DRAWING_SAVE         As Boolean = True
Private Const FAST_MODE_MINIMIZE_EXTRA_REDRAWS         As Boolean = True
Private Const USE_EXPERIMENTAL_FAST_DIRECT_DXF         As Boolean = True
Private Const EXPERIMENTAL_DIRECT_FALLBACK_TO_DRAWING  As Boolean = False
Private Const EXPERIMENTAL_DIRECT_ALLOW_CURRENT_VIEW_FALLBACK As Boolean = False
Private Const DIRECT_TEMP_PART_FORCE_INCH_UNITS        As Boolean = True

'------------------------------------------
' Orientation logic imported from SAVE_ALL_DXF_ACCORDING_TO_MATERIAL_THICKNESS_MACRO
'------------------------------------------
' Keeps AUTO DXF SAVE output/naming behavior, but uses the newer orientation decision stack:
'   1) optional tab-aware gusset manufacturing-corner detector
'   2) shared-corner right-angle pair
'   3) longer non-intersecting virtual-corner pair for chamfer-ignore behavior
'   4) longest single-edge fallback
'   5) final DXF 2D postprocess to correct SolidWorks current/named-view roll drift
Private Const AUTO_ORIENTATION_SOURCE_VERSION          As String = "SAVE_ALL_R11_ORIENTATION_STACK"
Private Const AVOID_VIEW_ZOOM_TO_FIT_DURING_BATCH      As Boolean = True

Private Const POSTPROCESS_DXF_ORIENTATION_TO_HORIZONTAL As Boolean = True
Private Const DXF_POSTPROCESS_PREFER_RIGHT_ANGLE_LEG_PAIR As Boolean = True
Private Const DXF_POSTPROCESS_PREFER_LONGER_RIGHT_ANGLE_LEG_HORIZONTAL As Boolean = True
Private Const DXF_POSTPROCESS_FORCE_WIDE_ENVELOPE       As Boolean = True
Private Const DXF_POSTPROCESS_FORCE_WIDE_ONLY_FOR_FALLBACK As Boolean = True
Private Const DXF_POSTPROCESS_TRANSLATE_TO_POSITIVE_XY  As Boolean = True
Private Const DXF_POSTPROCESS_MIN_SEGMENT_LENGTH        As Double = 0.001
Private Const DXF_POSTPROCESS_POINT_TOL                 As Double = 0.001
Private Const DXF_POSTPROCESS_PERP_DOT_TOL              As Double = 0.02
Private Const DXF_POSTPROCESS_BOTTOM_EDGE_TOL           As Double = 0.01
Private Const DXF_POSTPROCESS_OUTPUT_DECIMALS           As Long = 6
Private Const DXF_POSTPROCESS_KEEP_BACKUP_FILE          As Boolean = False

Private Const ENABLE_TAB_AWARE_GUSSET_MODE              As Boolean = True
Private Const TAB_AWARE_USER_TAB_MAX_M                  As Double = 0.0254      ' 1.00 in
Private Const TAB_AWARE_ALLOWANCE_M                     As Double = 0.03175     ' 1.25 in
Private Const TAB_AWARE_AXIS_STRIP_HALF_WIDTH_M         As Double = 0.03175     ' 1.25 in
Private Const TAB_AWARE_MIN_EFFECTIVE_LEG_M             As Double = 0.0508      ' 2.00 in
Private Const TAB_AWARE_MIN_LEG_TO_TAB_RATIO            As Double = 2#
Private Const TAB_AWARE_PREFER_LONGER_LEG_HORIZONTAL    As Boolean = True


' ExportToDWG2 action value (compile-safe)
Private Const SW_EXPORT_TO_DWG_ANNOTATION_VIEWS As Long = 3

'------------------------------------------
' Body type constants (compile-safe)
'------------------------------------------
Private Const BODYTYPE_SOLID   As Long = 0
Private Const BODYTYPE_SHEET   As Long = 1
Private Const BODYTYPE_WIRE    As Long = 2
Private Const BODYTYPE_MINIMUM As Long = 3
Private Const BODYTYPE_GENERAL As Long = 4
Private Const BODYTYPE_EMPTY   As Long = 5

'------------------------------------------
' Summary counters
'------------------------------------------
Private gTotalChecked              As Long
Private gTotalEligible             As Long
Private gTotalExported             As Long
Private gTotalSkipped              As Long
Private gTotalFailed               As Long

Private gTotalComponentInstances   As Long
Private gTotalUniquePartConfigs    As Long
Private gTotalPartDocsProcessed    As Long
Private gTotalAssemblyNodes        As Long
Private gTotalVirtualSkipped       As Long
Private gTotalSuppressedSkipped    As Long

'------------------------------------------
' Run-state / orientation override
'------------------------------------------
Private gHasOrientationOverride    As Boolean
Private gOrientationOverrideX(2)   As Double
Private gOrientationOverrideZ(2)   As Double
Private gOrientationOverrideLabel  As String

Private gForceRequestedConfig      As Boolean
Private gDrawingSelectedViewMode   As Boolean
Private gDrawingSelectedViewName   As String
Private gDrawingSelectedViewConfig As String
Private gDrawingSelectedViewModelPath As String

'=========================================================================================
' ENTRY POINT
'=========================================================================================
Public Sub main()

    On Error GoTo EH

    Set swApp = Application.SldWorks
    Set swModel = swApp.ActiveDoc
    Set swMathUtil = swApp.GetMathUtility

    Debug.Print String(110, "=")
    Debug.Print TimeStamp() & " | START | WATERJET_DXF_FROM_WELDMENT_CUTLIST_V15_DRAWING_VIEW_ORIENTATION"
    Debug.Print TimeStamp() & " | INFO  | Orientation stack imported from " & AUTO_ORIENTATION_SOURCE_VERSION
    Debug.Print TimeStamp() & " | INFO  | Tab-aware gusset orientation = " & CStr(ENABLE_TAB_AWARE_GUSSET_MODE)
    Debug.Print TimeStamp() & " | INFO  | DXF post-export orientation normalization = " & CStr(POSTPROCESS_DXF_ORIENTATION_TO_HORIZONTAL)

    ResetCounters

    If Not ValidateActiveModel(swModel) Then Exit Sub

    Dim summaryDocType As Long
    summaryDocType = swModel.GetType

    Select Case swModel.GetType
        Case swDocPART
            Set swExt = swModel.Extension
            Set swPart = swModel

            Dim partModelPath As String
            Dim partModelDir As String
            Dim partOutDir As String

            partModelPath = swModel.GetPathName
            partModelDir = GetFolderFromPath(partModelPath)
            partOutDir = EnsureFolderExists(partModelDir & "\" & OUT_FOLDER_NAME)

            If Len(partOutDir) = 0 Then
                MsgBox "Failed to create or access output folder:" & vbCrLf & partModelDir & "\" & OUT_FOLDER_NAME, vbCritical
                Exit Sub
            End If

            Debug.Print TimeStamp() & " | INFO  | Output folder = " & partOutDir
            Debug.Print TimeStamp() & " | INFO  | Running in PART mode"

            Call ProcessPartDocument(swModel, partOutDir, GetActiveConfigurationName(swModel), swModel.GetPathName, swModel.GetTitle)

        Case swDocASSEMBLY
            Set swExt = swModel.Extension

            Dim assyModelPath As String
            Dim assyModelDir As String
            Dim assyOutDir As String

            assyModelPath = swModel.GetPathName
            assyModelDir = GetFolderFromPath(assyModelPath)
            assyOutDir = EnsureFolderExists(assyModelDir & "\" & OUT_FOLDER_NAME)

            If Len(assyOutDir) = 0 Then
                MsgBox "Failed to create or access output folder:" & vbCrLf & assyModelDir & "\" & OUT_FOLDER_NAME, vbCritical
                Exit Sub
            End If

            Debug.Print TimeStamp() & " | INFO  | Output folder = " & assyOutDir
            Debug.Print TimeStamp() & " | INFO  | Running in ASSEMBLY mode"

            Call ProcessAssemblyDocument(swModel, assyOutDir)

        Case swDocDRAWING
            Debug.Print TimeStamp() & " | INFO  | Running in DRAWING selected-view mode"
            If Not ProcessSelectedDrawingViewMode(swModel) Then Exit Sub

        Case Else
            MsgBox "Unsupported active document type.", vbExclamation
            Exit Sub
    End Select

    Dim summary As String
    summary = BuildSummaryText(summaryDocType)

    Debug.Print TimeStamp() & " | DONE  | " & Replace(summary, vbCrLf, " | ")
    Debug.Print String(110, "=")

    MsgBox summary, vbInformation, "Waterjet DXF Export Summary"
    Exit Sub

EH:
    Debug.Print TimeStamp() & " | ERROR | Unhandled main error: " & Err.Number & " - " & Err.Description
    MsgBox "Macro terminated with an unexpected error:" & vbCrLf & Err.Number & " - " & Err.Description, vbCritical
End Sub
Private Function BuildSummaryText(ByVal docType As Long) As String
    Dim s As String

    s = "Waterjet DXF export complete." & vbCrLf & vbCrLf

    If docType = swDocASSEMBLY Then
        s = s & _
            "Assembly component instances seen: " & gTotalComponentInstances & vbCrLf & _
            "Assembly/subassembly nodes visited: " & gTotalAssemblyNodes & vbCrLf & _
            "Unique part+config processed: " & gTotalUniquePartConfigs & vbCrLf & _
            "Part docs processed: " & gTotalPartDocsProcessed & vbCrLf & _
            "Suppressed components skipped: " & gTotalSuppressedSkipped & vbCrLf & _
            "Virtual/unloadable components skipped: " & gTotalVirtualSkipped & vbCrLf & vbCrLf
    ElseIf docType = swDocDRAWING Then
        s = s & _
            "Drawing selected-view mode: YES" & vbCrLf & _
            "Selected drawing view: " & NzStr(gDrawingSelectedViewName) & vbCrLf & _
            "Selected view configuration: " & NzStr(gDrawingSelectedViewConfig) & vbCrLf & _
            "Selected view model path: " & NzStr(gDrawingSelectedViewModelPath) & vbCrLf & _
            "Part docs processed: " & gTotalPartDocsProcessed & vbCrLf & vbCrLf
    Else
        s = s & _
            "Part docs processed: " & gTotalPartDocsProcessed & vbCrLf & vbCrLf
    End If

    s = s & _
        "Export candidates checked: " & gTotalChecked & vbCrLf & _
        "Eligible (DXF/DXY=YES): " & gTotalEligible & vbCrLf & _
        "Exported: " & gTotalExported & vbCrLf & _
        "Skipped: " & gTotalSkipped & vbCrLf & _
        "Failed: " & gTotalFailed

    BuildSummaryText = s
End Function
'=========================================================================================
' VALIDATION / SETUP
'=========================================================================================
Private Function ValidateActiveModel(ByVal mdl As SldWorks.ModelDoc2) As Boolean
    On Error GoTo EH

    ValidateActiveModel = False

    If mdl Is Nothing Then
        MsgBox "No active SolidWorks document found.", vbExclamation
        Exit Function
    End If

    If mdl.GetType <> swDocPART And mdl.GetType <> swDocASSEMBLY And mdl.GetType <> swDocDRAWING Then
        MsgBox "Active document must be a saved PART, ASSEMBLY, or a DRAWING with a selected drawing view.", vbExclamation
        Exit Function
    End If

    If mdl.GetType <> swDocDRAWING Then
        If Len(Trim$(mdl.GetPathName)) = 0 Then
            MsgBox "The active document must be saved before running this macro.", vbExclamation
            Exit Function
        End If
    End If

    Debug.Print TimeStamp() & " | INFO  | Active model = " & mdl.GetTitle
    Debug.Print TimeStamp() & " | INFO  | Path         = " & mdl.GetPathName
    Debug.Print TimeStamp() & " | INFO  | Type         = " & DocTypeName(mdl.GetType)

    ValidateActiveModel = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ValidateActiveModel: " & Err.Number & " - " & Err.Description
End Function
Private Function DocTypeName(ByVal docType As Long) As String
    Select Case docType
        Case swDocPART:     DocTypeName = "PART"
        Case swDocASSEMBLY: DocTypeName = "ASSEMBLY"
        Case swDocDRAWING:  DocTypeName = "DRAWING"
        Case Else:          DocTypeName = "UNKNOWN"
    End Select
End Function

Private Sub ResetCounters()
    gTotalChecked = 0
    gTotalEligible = 0
    gTotalExported = 0
    gTotalSkipped = 0
    gTotalFailed = 0

    gTotalComponentInstances = 0
    gTotalUniquePartConfigs = 0
    gTotalPartDocsProcessed = 0
    gTotalAssemblyNodes = 0
    gTotalVirtualSkipped = 0
    gTotalSuppressedSkipped = 0

    ResetOrientationOverrideState
End Sub


Private Sub ResetOrientationOverrideState()
    gHasOrientationOverride = False
    gOrientationOverrideX(0) = 0#: gOrientationOverrideX(1) = 0#: gOrientationOverrideX(2) = 0#
    gOrientationOverrideZ(0) = 0#: gOrientationOverrideZ(1) = 0#: gOrientationOverrideZ(2) = 0#
    gOrientationOverrideLabel = ""

    gForceRequestedConfig = False
    gDrawingSelectedViewMode = False
    gDrawingSelectedViewName = ""
    gDrawingSelectedViewConfig = ""
    gDrawingSelectedViewModelPath = ""
End Sub

Private Function ProcessSelectedDrawingViewMode(ByVal drwMdl As SldWorks.ModelDoc2) As Boolean
    On Error GoTo EH

    ProcessSelectedDrawingViewMode = False

    If drwMdl Is Nothing Then Exit Function
    If drwMdl.GetType <> swDocDRAWING Then Exit Function

    Dim drawingTitle As String
    drawingTitle = drwMdl.GetTitle

    Dim selView As SldWorks.View
    Set selView = GetSelectedDrawingViewFromActiveDrawing(drwMdl)

    If selView Is Nothing Then
        MsgBox "Drawing mode requires one selected drawing view." & vbCrLf & _
               "Click the drawing view border or select an object that belongs to the target view and run again.", _
               vbExclamation, "Waterjet DXF Export"
        Debug.Print TimeStamp() & " | FAIL  | No selected drawing view could be resolved"
        Exit Function
    End If

    gDrawingSelectedViewMode = True
    gDrawingSelectedViewName = NzStr(selView.Name)
    Debug.Print String(100, "-")
    Debug.Print TimeStamp() & " | INFO  | DRAWING SELECTED-VIEW MODE"
    Debug.Print TimeStamp() & " | INFO  | Drawing title  | " & drawingTitle
    Debug.Print TimeStamp() & " | INFO  | Selected view  | " & NzStr(selView.Name)

    Dim refView As SldWorks.View
    Set refView = ResolveDrawingViewForReferencedDocument(selView)
    If refView Is Nothing Then
        Set refView = selView
    End If

    Dim openedByUs As Boolean
    Dim partMdl As SldWorks.ModelDoc2
    Set partMdl = GetDrawingViewReferencedPartDocument(refView, openedByUs)

    If partMdl Is Nothing Then
        MsgBox "The selected drawing view does not resolve to a saved part document." & vbCrLf & _
               "Use a part drawing view, not the sheet, and make sure the referenced model is available.", _
               vbExclamation, "Waterjet DXF Export"
        Debug.Print TimeStamp() & " | FAIL  | Selected drawing view did not resolve to a PART document"
        GoTo CleanupAndExit
    End If

    gDrawingSelectedViewModelPath = partMdl.GetPathName
    gDrawingSelectedViewConfig = GetDrawingViewReferencedConfiguration(refView)
    If Len(Trim$(gDrawingSelectedViewConfig)) = 0 Then
        gDrawingSelectedViewConfig = GetActiveConfigurationName(partMdl)
    End If

    Debug.Print TimeStamp() & " | INFO  | Referenced part | " & partMdl.GetTitle
    Debug.Print TimeStamp() & " | INFO  | Part path       | " & gDrawingSelectedViewModelPath
    Debug.Print TimeStamp() & " | INFO  | View config     | " & gDrawingSelectedViewConfig

    If Len(Trim$(gDrawingSelectedViewModelPath)) = 0 Then
        MsgBox "The selected drawing view references an unsaved part." & vbCrLf & _
               "Save the part first and run again.", vbExclamation, "Waterjet DXF Export"
        Debug.Print TimeStamp() & " | FAIL  | Referenced part path is blank"
        GoTo CleanupAndExit
    End If

    Dim outDir As String
    outDir = EnsureFolderExists(GetFolderFromPath(gDrawingSelectedViewModelPath) & "\" & OUT_FOLDER_NAME)

    If Len(outDir) = 0 Then
        MsgBox "Failed to create or access output folder:" & vbCrLf & _
               GetFolderFromPath(gDrawingSelectedViewModelPath) & "\" & OUT_FOLDER_NAME, vbCritical
        Debug.Print TimeStamp() & " | FAIL  | Could not create output folder for drawing-selected-view mode"
        GoTo CleanupAndExit
    End If

    Debug.Print TimeStamp() & " | INFO  | Output folder   | " & outDir

    If Not SetOrientationOverrideFromDrawingView(selView) Then
        MsgBox "Could not read orientation from the selected drawing view.", vbCritical, "Waterjet DXF Export"
        Debug.Print TimeStamp() & " | FAIL  | Could not set drawing-view orientation override"
        GoTo CleanupAndExit
    End If

    gForceRequestedConfig = True
    Set swExt = partMdl.Extension
    Set swPart = partMdl

    Call ProcessPartDocument(partMdl, outDir, gDrawingSelectedViewConfig, gDrawingSelectedViewModelPath, _
                             "DRAWING VIEW | " & NzStr(selView.Name))

    ProcessSelectedDrawingViewMode = True

CleanupAndExit:
    gForceRequestedConfig = False
    gHasOrientationOverride = False

    If openedByUs Then
        Debug.Print TimeStamp() & " | INFO  | Closing drawing-opened referenced part: " & gDrawingSelectedViewModelPath
        CloseDocIfOpen gDrawingSelectedViewModelPath
    End If

    If Len(Trim$(drawingTitle)) > 0 Then
        Call ActivateDocumentByTitle(drawingTitle)
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ProcessSelectedDrawingViewMode: " & Err.Number & " - " & Err.Description
    Resume CleanupAndExit
End Function

Private Function GetSelectedDrawingViewFromActiveDrawing(ByVal drwMdl As SldWorks.ModelDoc2) As SldWorks.View
    On Error GoTo EH

    If drwMdl Is Nothing Then Exit Function
    If drwMdl.GetType <> swDocDRAWING Then Exit Function

    Dim selMgr As SldWorks.SelectionMgr
    Set selMgr = drwMdl.SelectionManager
    If selMgr Is Nothing Then
        Debug.Print TimeStamp() & " | WARN  | Drawing SelectionManager is Nothing"
        Exit Function
    End If

    Dim selCount As Long
    selCount = selMgr.GetSelectedObjectCount2(-1)
    Debug.Print TimeStamp() & " | INFO  | Drawing selection count = " & CStr(selCount)

    If selCount < 1 Then Exit Function

    Dim selObj As Object
    Set selObj = selMgr.GetSelectedObject6(1, -1)

    If Not selObj Is Nothing Then
        Debug.Print TimeStamp() & " | INFO  | First selected object type = " & typeName(selObj)
        If typeName(selObj) = "View" Then
            Set GetSelectedDrawingViewFromActiveDrawing = selObj
            Exit Function
        End If
    End If

    Dim objView As Object
    Set objView = Nothing

    On Error Resume Next
    Set objView = CallByName(selMgr, "GetSelectedObjectsDrawingView2", VbMethod, 1, -1)
    If objView Is Nothing Or Err.Number <> 0 Then
        Err.Clear
        Set objView = CallByName(selMgr, "GetSelectedObjectsDrawingView", VbMethod, 1)
    End If
    On Error GoTo EH

    If Not objView Is Nothing Then
        Debug.Print TimeStamp() & " | INFO  | Resolved drawing view from selected object context"
        Set GetSelectedDrawingViewFromActiveDrawing = objView
        Exit Function
    End If

    Debug.Print TimeStamp() & " | WARN  | Could not resolve selected drawing view"
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetSelectedDrawingViewFromActiveDrawing: " & Err.Number & " - " & Err.Description
End Function

Private Function ResolveDrawingViewForReferencedDocument(ByVal srcView As SldWorks.View) As SldWorks.View
    On Error GoTo EH

    Set ResolveDrawingViewForReferencedDocument = srcView

    Dim curView As SldWorks.View
    Set curView = srcView

    Dim depth As Long
    For depth = 1 To 20
        If curView Is Nothing Then Exit For

        Dim mdl As SldWorks.ModelDoc2
        Set mdl = curView.ReferencedDocument
        If Not mdl Is Nothing Then
            Set ResolveDrawingViewForReferencedDocument = curView
            Exit Function
        End If

        Dim baseView As SldWorks.View
        Set baseView = curView.GetBaseView
        If baseView Is Nothing Then Exit For

        Debug.Print TimeStamp() & " | INFO  | ReferencedDocument unavailable on view [" & NzStr(curView.Name) & "] -> trying base view [" & NzStr(baseView.Name) & "]"
        Set curView = baseView
    Next depth

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ResolveDrawingViewForReferencedDocument: " & Err.Number & " - " & Err.Description
End Function

Private Function GetDrawingViewReferencedConfiguration(ByVal refView As SldWorks.View) As String
    On Error GoTo EH

    GetDrawingViewReferencedConfiguration = ""

    If refView Is Nothing Then Exit Function

    On Error Resume Next
    GetDrawingViewReferencedConfiguration = Trim$(refView.ReferencedConfiguration)
    If Err.Number <> 0 Then
        Debug.Print TimeStamp() & " | WARN  | Could not read ReferencedConfiguration from drawing view [" & NzStr(refView.Name) & "]: " & Err.Number & " - " & Err.Description
        Err.Clear
    End If
    On Error GoTo EH

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetDrawingViewReferencedConfiguration: " & Err.Number & " - " & Err.Description
End Function

Private Function GetDrawingViewReferencedPartDocument(ByVal refView As SldWorks.View, _
                                                      ByRef openedByUs As Boolean) As SldWorks.ModelDoc2
    On Error GoTo EH

    openedByUs = False

    If refView Is Nothing Then Exit Function

    Dim mdl As SldWorks.ModelDoc2
    Set mdl = refView.ReferencedDocument

    If Not mdl Is Nothing Then
        Debug.Print TimeStamp() & " | INFO  | ReferencedDocument returned loaded model [" & mdl.GetTitle & "] type=" & DocTypeName(mdl.GetType)
        If mdl.GetType = swDocPART Then
            Set GetDrawingViewReferencedPartDocument = mdl
        Else
            Debug.Print TimeStamp() & " | FAIL  | Selected drawing view references non-part model type " & DocTypeName(mdl.GetType)
        End If
        Exit Function
    End If

    Dim refModelName As String
    refModelName = ""

    On Error Resume Next
    refModelName = Trim$(refView.GetReferencedModelName)
    If Err.Number <> 0 Then
        Debug.Print TimeStamp() & " | WARN  | GetReferencedModelName failed on drawing view [" & NzStr(refView.Name) & "]: " & Err.Number & " - " & Err.Description
        Err.Clear
    End If
    On Error GoTo EH

    Debug.Print TimeStamp() & " | INFO  | Referenced model name/path from drawing view = " & refModelName

    If Len(refModelName) = 0 Then Exit Function

    Dim docType As Long
    docType = GetDocTypeFromPath(refModelName)

    If docType <> swDocPART Then
        Debug.Print TimeStamp() & " | FAIL  | Selected drawing view referenced file is not a part: " & refModelName
        Exit Function
    End If

    Dim alreadyOpen As Boolean
    alreadyOpen = Not (swApp.GetOpenDocumentByName(refModelName) Is Nothing)

    Dim errs As Long
    Dim warns As Long
    errs = 0
    warns = 0

    Debug.Print TimeStamp() & " | INFO  | Opening drawing-referenced part silently: " & refModelName
    Set mdl = swApp.OpenDoc6(refModelName, swDocPART, swOpenDocOptions_Silent Or swOpenDocOptions_ReadOnly, "", errs, warns)

    If mdl Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | OpenDoc6 failed for drawing-referenced part. errs=" & errs & " warns=" & warns
        Exit Function
    End If

    If Not alreadyOpen Then openedByUs = True
    Set GetDrawingViewReferencedPartDocument = mdl
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetDrawingViewReferencedPartDocument: " & Err.Number & " - " & Err.Description
End Function

Private Function SetOrientationOverrideFromDrawingView(ByVal srcView As SldWorks.View) As Boolean
    On Error GoTo EH

    SetOrientationOverrideFromDrawingView = False

    If srcView Is Nothing Then Exit Function

    Dim xDir(2) As Double
    Dim zDir(2) As Double

    If Not GetOrientationAxesFromDrawingView(srcView, xDir, zDir) Then
        Debug.Print TimeStamp() & " | FAIL  | Could not derive orientation axes from drawing view [" & NzStr(srcView.Name) & "]"
        Exit Function
    End If

    gHasOrientationOverride = True
    gOrientationOverrideX(0) = xDir(0)
    gOrientationOverrideX(1) = xDir(1)
    gOrientationOverrideX(2) = xDir(2)

    gOrientationOverrideZ(0) = zDir(0)
    gOrientationOverrideZ(1) = zDir(1)
    gOrientationOverrideZ(2) = zDir(2)

    gOrientationOverrideLabel = "DRAWING VIEW [" & NzStr(srcView.Name) & "]"

    Debug.Print TimeStamp() & " | INFO  | Drawing-view orientation override enabled"
    Debug.Print TimeStamp() & " | INFO  |   X override = (" & Dbl3ToStr(gOrientationOverrideX) & ")"
    Debug.Print TimeStamp() & " | INFO  |   Z override = (" & Dbl3ToStr(gOrientationOverrideZ) & ")"

    SetOrientationOverrideFromDrawingView = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | SetOrientationOverrideFromDrawingView: " & Err.Number & " - " & Err.Description
End Function

Private Function GetOrientationAxesFromDrawingView(ByVal srcView As SldWorks.View, _
                                                   ByRef xDir() As Double, _
                                                   ByRef zDir() As Double) As Boolean
    On Error GoTo EH

    GetOrientationAxesFromDrawingView = False

    If srcView Is Nothing Then Exit Function

    Dim mtv As SldWorks.MathTransform
    Set mtv = srcView.ModelToViewTransform
    If mtv Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | Drawing view ModelToViewTransform is Nothing"
        Exit Function
    End If

    Dim arr As Variant
    arr = mtv.ArrayData

    If Not VariantHasAtLeast9Numbers(arr) Then
        Debug.Print TimeStamp() & " | FAIL  | Drawing view transform array did not contain at least 9 numbers"
        Exit Function
    End If

    xDir(0) = CDbl(arr(0))
    xDir(1) = CDbl(arr(1))
    xDir(2) = CDbl(arr(2))

    Dim yDir(2) As Double
    yDir(0) = CDbl(arr(3))
    yDir(1) = CDbl(arr(4))
    yDir(2) = CDbl(arr(5))

    zDir(0) = CDbl(arr(6))
    zDir(1) = CDbl(arr(7))
    zDir(2) = CDbl(arr(8))

    Debug.Print TimeStamp() & " | INFO  | Drawing view raw transform rows:"
    Debug.Print TimeStamp() & " | INFO  |   RowX = (" & Dbl3ToStr(xDir) & ")"
    Debug.Print TimeStamp() & " | INFO  |   RowY = (" & Dbl3ToStr(yDir) & ")"
    Debug.Print TimeStamp() & " | INFO  |   RowZ = (" & Dbl3ToStr(zDir) & ")"

    If VecLength(xDir) <= EPS Or VecLength(zDir) <= EPS Then
        Debug.Print TimeStamp() & " | FAIL  | Drawing view transform produced zero-length orientation vectors"
        Exit Function
    End If

    NormalizeVec xDir
    NormalizeVec yDir
    NormalizeVec zDir

    Dim crossZ(2) As Double
    CrossProduct xDir, yDir, crossZ
    If VecLength(crossZ) > EPS Then
        NormalizeVec crossZ
        If DotProduct(crossZ, zDir) < 0# Then
            FlipVec zDir
        End If
    End If

    If Abs(DotProduct(xDir, zDir)) > 0.9999 Then
        Debug.Print TimeStamp() & " | FAIL  | Drawing view transform produced near-parallel X/Z vectors"
        Exit Function
    End If

    Debug.Print TimeStamp() & " | INFO  | Drawing view normalized orientation axes:"
    Debug.Print TimeStamp() & " | INFO  |   X = (" & Dbl3ToStr(xDir) & ")"
    Debug.Print TimeStamp() & " | INFO  |   Z = (" & Dbl3ToStr(zDir) & ")"

    GetOrientationAxesFromDrawingView = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetOrientationAxesFromDrawingView: " & Err.Number & " - " & Err.Description
End Function

'=========================================================================================
' PART / ASSEMBLY DISPATCH
'=========================================================================================
Private Sub ProcessPartDocument(ByVal partMdl As SldWorks.ModelDoc2, _
                                ByVal outDir As String, _
                                ByVal targetConfig As String, _
                                ByVal sourcePath As String, _
                                ByVal sourceLabel As String)
    On Error GoTo EH

    If partMdl Is Nothing Then Exit Sub
    If partMdl.GetType <> swDocPART Then Exit Sub

    gTotalPartDocsProcessed = gTotalPartDocsProcessed + 1

    Dim oldCfg As String
    Dim switchedCfg As Boolean
    Dim effectiveConfig As String
    Dim hasRealCutList As Boolean

    oldCfg = GetActiveConfigurationName(partMdl)
    switchedCfg = False

    If gForceRequestedConfig Then
        effectiveConfig = Trim$(targetConfig)
        If Len(effectiveConfig) = 0 Then effectiveConfig = oldCfg
        Debug.Print TimeStamp() & " | INFO  | Drawing-selected-view mode forcing requested configuration [" & effectiveConfig & "]"
    Else
        effectiveConfig = ResolveNestingConfiguration(partMdl, targetConfig, True)
    End If

    If Len(Trim$(effectiveConfig)) > 0 Then
        If StrComp(oldCfg, effectiveConfig, vbTextCompare) <> 0 Then
            Debug.Print TimeStamp() & " | INFO  | Switching part config from [" & oldCfg & "] to [" & effectiveConfig & "] for " & sourceLabel
            If ActivateModelConfiguration(partMdl, effectiveConfig) Then
                switchedCfg = True
            Else
                Debug.Print TimeStamp() & " | WARN  | Could not switch to configuration [" & effectiveConfig & "] for " & sourceLabel & ". Continuing with active config [" & oldCfg & "]"
            End If
        End If
    End If

    partMdl.ForceRebuild3 True

    Debug.Print String(100, "-")
    Debug.Print TimeStamp() & " | INFO  | PROCESS PART | " & sourceLabel
    Debug.Print TimeStamp() & " | INFO  | Source path  | " & sourcePath
    Debug.Print TimeStamp() & " | INFO  | Requested cfg| " & targetConfig
    Debug.Print TimeStamp() & " | INFO  | Nesting cfg  | " & effectiveConfig
    Debug.Print TimeStamp() & " | INFO  | Active cfg   | " & GetActiveConfigurationName(partMdl)
    If gHasOrientationOverride Then
        Debug.Print TimeStamp() & " | INFO  | Orientation | OVERRIDE ACTIVE -> " & gOrientationOverrideLabel
    End If

    If Not UpdateAllCutLists(partMdl) Then
        Debug.Print TimeStamp() & " | WARN  | Cut-list update returned False / partial"
    End If

    hasRealCutList = PartHasRealCutList(partMdl)
    Debug.Print TimeStamp() & " | INFO  | Real cut-list detected = " & CStr(hasRealCutList)

    If hasRealCutList Then
        ProcessCutLists partMdl, outDir
    Else
        ProcessRegularPart partMdl, outDir
    End If

Cleanup:
    If switchedCfg Then
        Debug.Print TimeStamp() & " | INFO  | Restoring original part config [" & oldCfg & "] for " & sourceLabel
        Call ActivateModelConfiguration(partMdl, oldCfg)
        partMdl.ForceRebuild3 True
    End If
    Exit Sub

EH:
    Debug.Print TimeStamp() & " | ERROR | ProcessPartDocument(" & sourceLabel & "): " & Err.Number & " - " & Err.Description
    Resume Cleanup
End Sub

Private Sub ProcessAssemblyDocument(ByVal assyMdl As SldWorks.ModelDoc2, ByVal outDir As String)
    On Error GoTo EH

    If assyMdl Is Nothing Then Exit Sub
    If assyMdl.GetType <> swDocASSEMBLY Then Exit Sub

    Dim assy As SldWorks.AssemblyDoc
    Set assy = assyMdl

    ResolveAssemblyLightweight assyMdl

    Dim rootComp As SldWorks.Component2
    Set rootComp = GetAssemblyRootComponent(assyMdl)

    If rootComp Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | Could not obtain root component from active assembly"
        Exit Sub
    End If

    Dim dictPartCfg As Object
    Dim dictAsmCfg As Object
    Set dictPartCfg = CreateObject("Scripting.Dictionary")
    Set dictAsmCfg = CreateObject("Scripting.Dictionary")

    Debug.Print TimeStamp() & " | INFO  | Beginning recursive assembly traversal from root: " & rootComp.Name2

    WalkAssemblyTree rootComp, outDir, dictPartCfg, dictAsmCfg

    Exit Sub

EH:
    Debug.Print TimeStamp() & " | ERROR | ProcessAssemblyDocument: " & Err.Number & " - " & Err.Description
End Sub

Private Sub ResolveAssemblyLightweight(ByVal assyMdl As SldWorks.ModelDoc2)
    On Error GoTo EH

    Dim assy As SldWorks.AssemblyDoc
    Set assy = assyMdl

    Debug.Print TimeStamp() & " | INFO  | Attempting to resolve lightweight assembly components"

    On Error Resume Next
    assy.ResolveAllLightWeightComponents True
    Err.Clear
    On Error GoTo EH

    assyMdl.ForceRebuild3 True
    Exit Sub

EH:
    Debug.Print TimeStamp() & " | WARN  | ResolveAssemblyLightweight: " & Err.Number & " - " & Err.Description
End Sub

Private Function GetAssemblyRootComponent(ByVal assyMdl As SldWorks.ModelDoc2) As SldWorks.Component2
    On Error GoTo EH

    Dim cfg As SldWorks.Configuration
    Set cfg = assyMdl.ConfigurationManager.ActiveConfiguration
    If cfg Is Nothing Then Exit Function

    Set GetAssemblyRootComponent = cfg.GetRootComponent3(True)
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetAssemblyRootComponent: " & Err.Number & " - " & Err.Description
End Function

Private Sub WalkAssemblyTree(ByVal parentComp As SldWorks.Component2, _
                             ByVal outDir As String, _
                             ByVal dictPartCfg As Object, _
                             ByVal dictAsmCfg As Object)
    On Error GoTo EH

    If parentComp Is Nothing Then Exit Sub

    gTotalAssemblyNodes = gTotalAssemblyNodes + 1

    Dim vChildren As Variant
    vChildren = parentComp.GetChildren

    If IsEmpty(vChildren) Then Exit Sub
    If Not IsArray(vChildren) Then Exit Sub

    Dim i As Long
    For i = LBound(vChildren) To UBound(vChildren)

        Dim child As SldWorks.Component2
        Set child = vChildren(i)

        gTotalComponentInstances = gTotalComponentInstances + 1

        If child Is Nothing Then
            Debug.Print TimeStamp() & " | WARN  | Child component is Nothing"
            GoTo NextChild
        End If

        If IsComponentSuppressedSafe(child) Then
            gTotalSuppressedSkipped = gTotalSuppressedSkipped + 1
            Debug.Print TimeStamp() & " | SKIP  | Suppressed component: " & child.Name2
            GoTo NextChild
        End If

        Dim openedByUs As Boolean
        Dim compMdl As SldWorks.ModelDoc2
        Set compMdl = EnsureComponentModelLoaded(child, openedByUs)

        If compMdl Is Nothing Then
            gTotalVirtualSkipped = gTotalVirtualSkipped + 1
            Debug.Print TimeStamp() & " | SKIP  | Could not load component model: " & child.Name2
            GoTo NextChild
        End If

        Dim compPath As String
        Dim compCfg As String
        Dim effectivePartCfg As String
        Dim uniqueKey As String

        compPath = GetComponentBestPath(child, compMdl)
        compCfg = Trim$(child.ReferencedConfiguration)
        If Len(compCfg) = 0 Then compCfg = GetActiveConfigurationName(compMdl)

        If compMdl.GetType = swDocPART Then
            effectivePartCfg = ResolveNestingConfiguration(compMdl, compCfg, False)
            uniqueKey = UCase$(compPath) & "|" & UCase$(effectivePartCfg)

            If Not dictPartCfg.Exists(uniqueKey) Then
                dictPartCfg.Add uniqueKey, True
                gTotalUniquePartConfigs = gTotalUniquePartConfigs + 1

                Debug.Print String(90, "-")
                Debug.Print TimeStamp() & " | INFO  | UNIQUE PART+CFG | " & child.Name2
                Debug.Print TimeStamp() & " | INFO  | Part path       | " & compPath
                Debug.Print TimeStamp() & " | INFO  | Ref config      | " & compCfg
                Debug.Print TimeStamp() & " | INFO  | Nesting config  | " & effectivePartCfg

                ProcessPartDocument compMdl, outDir, effectivePartCfg, compPath, child.Name2
            Else
                Debug.Print TimeStamp() & " | SKIP  | Duplicate part+cfg already processed: " & child.Name2 & " | " & compPath & " | " & effectivePartCfg
            End If

        ElseIf compMdl.GetType = swDocASSEMBLY Then
            uniqueKey = UCase$(compPath) & "|" & UCase$(compCfg)

            If Not dictAsmCfg.Exists(uniqueKey) Then
                dictAsmCfg.Add uniqueKey, True

                Debug.Print String(90, "-")
                Debug.Print TimeStamp() & " | INFO  | ENTER SUBASM    | " & child.Name2
                Debug.Print TimeStamp() & " | INFO  | Asm path        | " & compPath
                Debug.Print TimeStamp() & " | INFO  | Ref config      | " & compCfg

                WalkAssemblyTree child, outDir, dictPartCfg, dictAsmCfg
            Else
                Debug.Print TimeStamp() & " | SKIP  | Duplicate subassembly+cfg already traversed: " & child.Name2 & " | " & compPath & " | " & compCfg
            End If

        Else
            Debug.Print TimeStamp() & " | SKIP  | Unsupported component doc type: " & child.Name2 & " | " & DocTypeName(compMdl.GetType)
        End If

        If openedByUs Then
            CloseDocIfOpen compPath
        End If

NextChild:
    Next i

    Exit Sub

EH:
    Debug.Print TimeStamp() & " | ERROR | WalkAssemblyTree(" & parentComp.Name2 & "): " & Err.Number & " - " & Err.Description
End Sub

Private Function EnsureComponentModelLoaded(ByVal comp As SldWorks.Component2, ByRef openedByUs As Boolean) As SldWorks.ModelDoc2
    On Error GoTo EH

    openedByUs = False

    If comp Is Nothing Then Exit Function

    Dim mdl As SldWorks.ModelDoc2
    Set mdl = comp.GetModelDoc2
    If Not mdl Is Nothing Then
        Set EnsureComponentModelLoaded = mdl
        Exit Function
    End If

    Dim path As String
    path = Trim$(comp.GetPathName)
    If Len(path) = 0 Then
        Debug.Print TimeStamp() & " | WARN  | Component path is blank (likely virtual/unresolved): " & comp.Name2
        Exit Function
    End If

    Dim alreadyOpen As Boolean
    alreadyOpen = Not (swApp.GetOpenDocumentByName(path) Is Nothing)

    Dim docType As Long
    docType = GetDocTypeFromPath(path)
    If docType = 0 Then
        Debug.Print TimeStamp() & " | WARN  | Unsupported component file type: " & path
        Exit Function
    End If

    Dim errs As Long, warns As Long
    errs = 0: warns = 0

    Debug.Print TimeStamp() & " | INFO  | Opening component silently: " & path

    Set mdl = swApp.OpenDoc6(path, docType, swOpenDocOptions_Silent Or swOpenDocOptions_ReadOnly, "", errs, warns)

    If mdl Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | OpenDoc6 failed. errs=" & errs & " warns=" & warns & " | " & path
        Exit Function
    End If

    If Not alreadyOpen Then openedByUs = True

    Set EnsureComponentModelLoaded = mdl
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | EnsureComponentModelLoaded(" & comp.Name2 & "): " & Err.Number & " - " & Err.Description
End Function

Private Function GetDocTypeFromPath(ByVal filePath As String) As Long
    Dim ext As String
    ext = LCase$(GetExtensionFromPath(filePath))

    Select Case ext
        Case "sldprt": GetDocTypeFromPath = swDocPART
        Case "sldasm": GetDocTypeFromPath = swDocASSEMBLY
        Case "slddrw": GetDocTypeFromPath = swDocDRAWING
        Case Else:     GetDocTypeFromPath = 0
    End Select
End Function

Private Function GetExtensionFromPath(ByVal filePath As String) As String
    Dim p As Long
    p = InStrRev(filePath, ".")
    If p > 0 Then
        GetExtensionFromPath = Mid$(filePath, p + 1)
    Else
        GetExtensionFromPath = ""
    End If
End Function

Private Function GetComponentBestPath(ByVal comp As SldWorks.Component2, ByVal mdl As SldWorks.ModelDoc2) As String
    On Error GoTo EH

    Dim s As String
    s = Trim$(comp.GetPathName)

    If Len(s) > 0 Then
        GetComponentBestPath = s
        Exit Function
    End If

    If Not mdl Is Nothing Then
        s = Trim$(mdl.GetPathName)
        If Len(s) > 0 Then
            GetComponentBestPath = s
            Exit Function
        End If

        GetComponentBestPath = "[VIRTUAL] " & mdl.GetTitle
        Exit Function
    End If

    GetComponentBestPath = "[UNKNOWN_COMPONENT]"
    Exit Function

EH:
    GetComponentBestPath = "[UNKNOWN_COMPONENT]"
End Function

Private Function IsComponentSuppressedSafe(ByVal comp As SldWorks.Component2) As Boolean
    On Error GoTo EH

    IsComponentSuppressedSafe = False
    If comp Is Nothing Then Exit Function

    On Error Resume Next
    IsComponentSuppressedSafe = CBool(comp.IsSuppressed)
    If Err.Number <> 0 Then
        Err.Clear
        IsComponentSuppressedSafe = False
    End If
    On Error GoTo EH
    Exit Function

EH:
    IsComponentSuppressedSafe = False
End Function

Private Function GetActiveConfigurationName(ByVal mdl As SldWorks.ModelDoc2) As String
    On Error GoTo EH

    GetActiveConfigurationName = ""

    If mdl Is Nothing Then Exit Function
    If mdl.ConfigurationManager Is Nothing Then Exit Function
    If mdl.ConfigurationManager.ActiveConfiguration Is Nothing Then Exit Function

    GetActiveConfigurationName = Trim$(mdl.ConfigurationManager.ActiveConfiguration.Name)
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetActiveConfigurationName: " & Err.Number & " - " & Err.Description
End Function


Private Function FindPreferredWaterjetConfiguration(ByVal mdl As SldWorks.ModelDoc2) As String
    On Error GoTo EH

    FindPreferredWaterjetConfiguration = ""

    If mdl Is Nothing Then Exit Function

    Dim vCfgNames As Variant
    vCfgNames = mdl.GetConfigurationNames

    If IsEmpty(vCfgNames) Then Exit Function
    If Not IsArray(vCfgNames) Then Exit Function

    Dim i As Long
    Dim cfgName As String

    For i = LBound(vCfgNames) To UBound(vCfgNames)
        cfgName = Trim$(CStr(vCfgNames(i)))
        If Len(cfgName) > 0 Then
            If StrComp(cfgName, "WATERJET_CUT", vbTextCompare) = 0 Then
                FindPreferredWaterjetConfiguration = CStr(vCfgNames(i))
                Exit Function
            End If
        End If
    Next i

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | FindPreferredWaterjetConfiguration: " & Err.Number & " - " & Err.Description
End Function

Private Function ResolveNestingConfiguration(ByVal mdl As SldWorks.ModelDoc2, _
                                             ByVal requestedConfig As String, _
                                             Optional ByVal writeLog As Boolean = False) As String
    On Error GoTo EH

    ResolveNestingConfiguration = ""

    If mdl Is Nothing Then Exit Function

    Dim preferredCfg As String
    Dim fallbackCfg As String

    preferredCfg = Trim$(FindPreferredWaterjetConfiguration(mdl))
    fallbackCfg = Trim$(requestedConfig)

    If Len(fallbackCfg) = 0 Then
        fallbackCfg = GetActiveConfigurationName(mdl)
    End If

    If Len(preferredCfg) > 0 Then
        ResolveNestingConfiguration = preferredCfg
        If writeLog Then
            Debug.Print TimeStamp() & " | INFO  | Nesting config override detected: using [" & preferredCfg & "] instead of requested [" & fallbackCfg & "]"
        End If
    Else
        ResolveNestingConfiguration = fallbackCfg
        If writeLog Then
            Debug.Print TimeStamp() & " | INFO  | No WATERJET_CUT config found. Using requested/active config [" & ResolveNestingConfiguration & "]"
        End If
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ResolveNestingConfiguration: " & Err.Number & " - " & Err.Description
End Function

Private Function ActivateModelConfiguration(ByVal mdl As SldWorks.ModelDoc2, ByVal cfgName As String) As Boolean
    On Error GoTo EH

    ActivateModelConfiguration = False

    If mdl Is Nothing Then Exit Function
    If Len(Trim$(cfgName)) = 0 Then Exit Function

    Dim ok As Boolean
    ok = mdl.ShowConfiguration2(cfgName)

    If ok Then
        mdl.ForceRebuild3 True
        mdl.GraphicsRedraw2
        ActivateModelConfiguration = True
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ActivateModelConfiguration(" & cfgName & "): " & Err.Number & " - " & Err.Description
End Function

'=========================================================================================
' CUT-LIST TRAVERSAL
'=========================================================================================
Private Sub ProcessCutLists(ByVal mdl As SldWorks.ModelDoc2, ByVal outDir As String)
    On Error GoTo EH

    Dim feat As SldWorks.Feature
    Set feat = mdl.FirstFeature

    Dim foundAnyCutList As Boolean
    foundAnyCutList = False

    Do While Not feat Is Nothing
        If IsRealCutListFolderFeature(feat) Then
            foundAnyCutList = True
            ProcessSingleCutList mdl, feat, outDir
        End If
        Set feat = feat.GetNextFeature
    Loop

    If Not foundAnyCutList Then
        Debug.Print TimeStamp() & " | WARN  | No real cut-list folders found in part: " & mdl.GetTitle
    End If

    Exit Sub

EH:
    Debug.Print TimeStamp() & " | ERROR | ProcessCutLists: " & Err.Number & " - " & Err.Description
End Sub

Private Function PartHasRealCutList(ByVal mdl As SldWorks.ModelDoc2) As Boolean
    On Error GoTo EH

    PartHasRealCutList = False

    If mdl Is Nothing Then Exit Function
    If mdl.GetType <> swDocPART Then Exit Function

    Dim feat As SldWorks.Feature
    Set feat = mdl.FirstFeature

    Do While Not feat Is Nothing
        If IsRealCutListFolderFeature(feat) Then
            PartHasRealCutList = True
            Exit Function
        End If
        Set feat = feat.GetNextFeature
    Loop

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | PartHasRealCutList: " & Err.Number & " - " & Err.Description
End Function

Private Sub ProcessRegularPart(ByVal mdl As SldWorks.ModelDoc2, ByVal outDir As String)
    On Error GoTo EH

    gTotalChecked = gTotalChecked + 1

    Debug.Print String(80, "-")
    Debug.Print TimeStamp() & " | INFO  | Processing regular part (non-weldment): " & mdl.GetTitle

    Dim exportPropName As String
    Dim exportRaw As String
    Dim exportResolved As String
    Dim partNoRaw As String
    Dim partNoResolved As String
    Dim bodyCount As Long

    exportResolved = GetEffectivePartLevelDxfFlag(mdl, exportPropName, exportRaw)
    partNoResolved = GetEvaluatedModelProperty(mdl, PROP_PARTNO, partNoRaw)
    bodyCount = CountUsableBodiesInPart(mdl)

    Debug.Print TimeStamp() & " | INFO  | Effective regular-part export property = [" & exportPropName & "] raw=[" & exportRaw & "] eval=[" & exportResolved & "]"
    Debug.Print TimeStamp() & " | INFO  | PART PROP " & PROP_PARTNO & " raw=[" & partNoRaw & "] eval=[" & partNoResolved & "]"
    Debug.Print TimeStamp() & " | INFO  | Regular part usable body count = " & CStr(bodyCount)

    If UCase$(Trim$(exportResolved)) <> PROP_TRUE_VALUE Then
        gTotalSkipped = gTotalSkipped + 1
        Debug.Print TimeStamp() & " | SKIP  | Regular part effective export property is not YES"
        Exit Sub
    End If

    gTotalEligible = gTotalEligible + 1

    Dim repBody As SldWorks.Body2
    Set repBody = GetRepresentativeBodyFromPart(mdl)

    If repBody Is Nothing Then
        gTotalFailed = gTotalFailed + 1
        Debug.Print TimeStamp() & " | FAIL  | No valid representative body found for regular part"
        Exit Sub
    End If

    Dim faceN(2) As Double
    Dim xDir(2) As Double
    Dim usedFallbackEdge As Boolean
    Dim usedPerpCorner As Boolean

    If Not GetExportOrientationForBody(repBody, "regular part [" & mdl.GetTitle & "]", faceN, xDir, usedFallbackEdge, usedPerpCorner) Then
        gTotalFailed = gTotalFailed + 1
        Exit Sub
    End If

    If gHasOrientationOverride Then
        Debug.Print TimeStamp() & " | INFO  | Regular part orientation mode = selected drawing view override"
    ElseIf usedPerpCorner Then
        Debug.Print TimeStamp() & " | INFO  | Regular part orientation mode = perpendicular edge pair -> shared or virtual corner driven bottom-left"
    ElseIf usedFallbackEdge Then
        Debug.Print TimeStamp() & " | WARN  | Regular part orientation mode = fallback axis (no usable linear edge found)"
    Else
        Debug.Print TimeStamp() & " | INFO  | Regular part orientation mode = longest single linear edge horizontal fallback"
    End If

    Dim baseName As String
    baseName = ResolveDxfBaseNameForPart(mdl, partNoResolved, bodyCount, "regular part")

    Dim finalDxfPath As String
    finalDxfPath = GetUniqueOutputPath(outDir, baseName, "dxf")

    If bodyCount = 1 Then
        Debug.Print TimeStamp() & " | INFO  | Export path = DIRECT_SOURCE_SINGLE_BODY"
        If ExportSingleBodyPartAsOrientedDxfFromSource(mdl, faceN, xDir, finalDxfPath, mdl.GetTitle, usedPerpCorner) Then
            gTotalExported = gTotalExported + 1
            Debug.Print TimeStamp() & " | OK    | Regular part exported directly from source => " & finalDxfPath
        Else
            gTotalFailed = gTotalFailed + 1
            Debug.Print TimeStamp() & " | FAIL  | Regular part direct-from-source export failed => " & finalDxfPath
        End If
    Else
        Debug.Print TimeStamp() & " | INFO  | Export path = TEMP_PART_ISOLATED_BODY"
        If ExportBodyAsOrientedDxf(repBody, faceN, xDir, finalDxfPath, mdl.GetTitle, usedPerpCorner) Then
            gTotalExported = gTotalExported + 1
            Debug.Print TimeStamp() & " | OK    | Regular part exported => " & finalDxfPath
        Else
            gTotalFailed = gTotalFailed + 1
            Debug.Print TimeStamp() & " | FAIL  | Regular part export failed => " & finalDxfPath
        End If
    End If

    Exit Sub

EH:
    gTotalFailed = gTotalFailed + 1
    Debug.Print TimeStamp() & " | ERROR | ProcessRegularPart(" & mdl.GetTitle & "): " & Err.Number & " - " & Err.Description
End Sub
Private Function UpdateAllCutLists(ByVal mdl As SldWorks.ModelDoc2) As Boolean
    On Error GoTo EH

    UpdateAllCutLists = False

    Debug.Print TimeStamp() & " | INFO  | Rebuilding model before cut-list update"
    mdl.ForceRebuild3 True

    Dim feat As SldWorks.Feature
    Set feat = mdl.FirstFeature

    Dim updatedAny As Boolean
    updatedAny = False

    Do While Not feat Is Nothing
        Dim typeName As String
        typeName = feat.GetTypeName2

        If StrComp(typeName, "SolidBodyFolder", vbTextCompare) = 0 _
        Or StrComp(typeName, "CutListFolder", vbTextCompare) = 0 _
        Or StrComp(typeName, "SubWeldFolder", vbTextCompare) = 0 Then

            Dim bf As Object
            Set bf = Nothing

            On Error Resume Next
            Set bf = feat.GetSpecificFeature2
            On Error GoTo EH

            If Not bf Is Nothing Then
                Dim vRet As Variant
                On Error Resume Next
                vRet = bf.UpdateCutList
                On Error GoTo EH

                Debug.Print TimeStamp() & " | INFO  | UpdateCutList on feature [" & feat.Name & "] => " & CStr(vRet)

                If Not IsEmpty(vRet) Then
                    If CBool(vRet) Then updatedAny = True
                End If
            End If
        End If

        Set feat = feat.GetNextFeature
    Loop

    mdl.ForceRebuild3 True
    UpdateAllCutLists = True

    If Not updatedAny Then
        Debug.Print TimeStamp() & " | WARN  | No body folders explicitly updated; rebuild still performed"
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | UpdateAllCutLists: " & Err.Number & " - " & Err.Description
End Function

Private Function IsRealCutListFolderFeature(ByVal feat As SldWorks.Feature) As Boolean
    On Error GoTo EH

    IsRealCutListFolderFeature = False

    If feat Is Nothing Then Exit Function
    If StrComp(feat.GetTypeName2, "CutListFolder", vbTextCompare) <> 0 Then Exit Function

    Dim bf As Object
    Set bf = feat.GetSpecificFeature2
    If bf Is Nothing Then Exit Function

    Dim bodyCount As Long
    bodyCount = 0

    On Error Resume Next
    bodyCount = CLng(bf.GetBodyCount)
    On Error GoTo EH

    Debug.Print TimeStamp() & " | INFO  | Cut-list [" & feat.Name & "] body count = " & bodyCount

    If bodyCount > 0 Then
        IsRealCutListFolderFeature = True
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | IsRealCutListFolderFeature(" & feat.Name & "): " & Err.Number & " - " & Err.Description
End Function

Private Sub ProcessSingleCutList(ByVal mdl As SldWorks.ModelDoc2, ByVal cutFeat As SldWorks.Feature, ByVal outDir As String)
    On Error GoTo EH

    gTotalChecked = gTotalChecked + 1

    Debug.Print String(80, "-")
    Debug.Print TimeStamp() & " | INFO  | Processing cut-list feature: " & cutFeat.Name

    Dim cpMgr As SldWorks.CustomPropertyManager
    Set cpMgr = cutFeat.CustomPropertyManager

    Dim dxfRaw As String
    Dim dxfResolved As String
    Dim effectiveDxfRaw As String
    Dim effectiveDxfResolved As String
    Dim effectiveDxfSource As String
    Dim partNoRaw As String
    Dim partNoResolved As String
    Dim bodyCount As Long

    dxfResolved = GetEvaluatedCutListProperty(cpMgr, PROP_DXF, dxfRaw)
    effectiveDxfRaw = dxfRaw
    effectiveDxfResolved = dxfResolved
    effectiveDxfSource = "CUTLIST." & PROP_DXF
    partNoResolved = GetEvaluatedCutListProperty(cpMgr, PROP_PARTNO, partNoRaw)
    bodyCount = CountUsableBodiesInPart(mdl)

    Debug.Print TimeStamp() & " | INFO  | PROP " & PROP_DXF & " raw=[" & dxfRaw & "] eval=[" & dxfResolved & "]"
    Debug.Print TimeStamp() & " | INFO  | PROP " & PROP_PARTNO & " raw=[" & partNoRaw & "] eval=[" & partNoResolved & "]"
    Debug.Print TimeStamp() & " | INFO  | Part usable body count = " & CStr(bodyCount)

    If Len(Trim$(effectiveDxfResolved)) = 0 Then
        If bodyCount = 1 Then
            Dim partExportPropName As String
            effectiveDxfResolved = GetEffectivePartLevelDxfFlag(mdl, partExportPropName, effectiveDxfRaw)
            effectiveDxfSource = "PART." & partExportPropName
            Debug.Print TimeStamp() & " | INFO  | Single-body cut-list fallback to part property [" & partExportPropName & "] raw=[" & effectiveDxfRaw & "] eval=[" & effectiveDxfResolved & "]"
        Else
            Debug.Print TimeStamp() & " | INFO  | Cut-list DXF blank and part is not single-body; no part-level fallback used"
        End If
    End If

    Debug.Print TimeStamp() & " | INFO  | Effective DXF source = " & effectiveDxfSource & " raw=[" & effectiveDxfRaw & "] eval=[" & effectiveDxfResolved & "]"

    If UCase$(Trim$(effectiveDxfResolved)) <> PROP_TRUE_VALUE Then
        gTotalSkipped = gTotalSkipped + 1
        Debug.Print TimeStamp() & " | SKIP  | Effective DXF property is not YES"
        Exit Sub
    End If

    gTotalEligible = gTotalEligible + 1

    Dim repBody As SldWorks.Body2
    Set repBody = GetRepresentativeBodyFromCutList(cutFeat)

    If repBody Is Nothing Then
        gTotalFailed = gTotalFailed + 1
        Debug.Print TimeStamp() & " | FAIL  | No representative body found for cut-list [" & cutFeat.Name & "]"
        Exit Sub
    End If

    Dim faceN(2) As Double
    Dim xDir(2) As Double
    Dim usedFallbackEdge As Boolean
    Dim usedPerpCorner As Boolean

    If Not GetExportOrientationForBody(repBody, "cut-list [" & cutFeat.Name & "]", faceN, xDir, usedFallbackEdge, usedPerpCorner) Then
        gTotalFailed = gTotalFailed + 1
        Exit Sub
    End If

    If gHasOrientationOverride Then
        Debug.Print TimeStamp() & " | INFO  | Cut-list orientation mode = selected drawing view override"
    ElseIf usedPerpCorner Then
        Debug.Print TimeStamp() & " | INFO  | Cut-list orientation mode = perpendicular edge pair -> shared or virtual corner driven bottom-left"
    ElseIf usedFallbackEdge Then
        Debug.Print TimeStamp() & " | WARN  | Cut-list orientation mode = fallback axis (no usable linear edge found)"
    Else
        Debug.Print TimeStamp() & " | INFO  | Cut-list orientation mode = longest single linear edge horizontal fallback"
    End If

    Dim baseName As String
    baseName = ResolveDxfBaseNameForPart(mdl, partNoResolved, bodyCount, "cut-list [" & cutFeat.Name & "]")

    Dim outputPath As String
    outputPath = GetUniqueOutputPath(outDir, baseName, "dxf")

    If bodyCount = 1 Then
        Debug.Print TimeStamp() & " | INFO  | Export path = DIRECT_SOURCE_SINGLE_BODY"
        If ExportSingleBodyPartAsOrientedDxfFromSource(mdl, faceN, xDir, outputPath, cutFeat.Name, usedPerpCorner) Then
            gTotalExported = gTotalExported + 1
            Debug.Print TimeStamp() & " | OK    | Exported directly from source => " & outputPath
        Else
            gTotalFailed = gTotalFailed + 1
            Debug.Print TimeStamp() & " | FAIL  | Direct-from-source export failed => " & outputPath
        End If
    Else
        Debug.Print TimeStamp() & " | INFO  | Export path = TEMP_PART_ISOLATED_BODY"
        If ExportBodyAsOrientedDxf(repBody, faceN, xDir, outputPath, cutFeat.Name, usedPerpCorner) Then
            gTotalExported = gTotalExported + 1
            Debug.Print TimeStamp() & " | OK    | Exported => " & outputPath
        Else
            gTotalFailed = gTotalFailed + 1
            Debug.Print TimeStamp() & " | FAIL  | Export failed => " & outputPath
        End If
    End If

    Exit Sub

EH:
    gTotalFailed = gTotalFailed + 1
    Debug.Print TimeStamp() & " | ERROR | ProcessSingleCutList(" & cutFeat.Name & "): " & Err.Number & " - " & Err.Description
End Sub
Private Function ResolveDxfBaseNameForPart(ByVal mdl As SldWorks.ModelDoc2, _
                                           ByVal preferredPartNo As String, _
                                           ByVal bodyCount As Long, _
                                           ByVal contextLabel As String) As String
    On Error GoTo EH

    Dim baseName As String

    baseName = ""

    If bodyCount = 1 Then
        baseName = GetFileStemFromPath(mdl.GetPathName)
        Debug.Print TimeStamp() & " | INFO  | Single-body " & contextLabel & " uses saved part file name directly for DXF base name => [" & baseName & "]"
    Else
        baseName = Trim$(preferredPartNo)

        If Len(baseName) > 0 Then
            Debug.Print TimeStamp() & " | INFO  | Multi-body " & contextLabel & " uses PART NUMBER for DXF base name => [" & baseName & "]"
        Else
            baseName = GetFileStemFromPath(mdl.GetPathName)
            Debug.Print TimeStamp() & " | WARN  | PART NUMBER missing/blank on " & contextLabel & ", using file name fallback => [" & baseName & "]"
        End If
    End If

    baseName = SanitizeFileName(baseName)
    If Len(baseName) = 0 Then
        baseName = "PART"
        Debug.Print TimeStamp() & " | WARN  | Sanitized DXF base name became blank for " & contextLabel & "; using [PART]"
    End If

    ResolveDxfBaseNameForPart = baseName
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ResolveDxfBaseNameForPart(" & contextLabel & "): " & Err.Number & " - " & Err.Description
    ResolveDxfBaseNameForPart = "PART"
End Function

Private Function GetRepresentativeBodyFromCutList(ByVal cutFeat As SldWorks.Feature) As SldWorks.Body2
    On Error GoTo EH

    Dim bf As Object
    Set bf = cutFeat.GetSpecificFeature2

    If bf Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | GetSpecificFeature2 returned Nothing for cut-list [" & cutFeat.Name & "]"
        Exit Function
    End If

    Dim bodyCount As Long
    bodyCount = 0

    On Error Resume Next
    bodyCount = CLng(bf.GetBodyCount)
    On Error GoTo EH

    Debug.Print TimeStamp() & " | INFO  | [" & cutFeat.Name & "] GetBodyCount = " & bodyCount

    If bodyCount <= 0 Then
        Debug.Print TimeStamp() & " | FAIL  | [" & cutFeat.Name & "] has no bodies"
        Exit Function
    End If

    Dim vBodies As Variant
    vBodies = bf.GetBodies

    If IsEmpty(vBodies) Then
        Debug.Print TimeStamp() & " | FAIL  | [" & cutFeat.Name & "] GetBodies returned Empty"
        Exit Function
    End If

    If Not IsArray(vBodies) Then
        Debug.Print TimeStamp() & " | FAIL  | [" & cutFeat.Name & "] GetBodies did not return an array"
        Exit Function
    End If

    Dim i As Long
    Dim b As SldWorks.Body2
    Dim bt As Long

    For i = LBound(vBodies) To UBound(vBodies)
        Set b = Nothing
        On Error Resume Next
        Set b = vBodies(i)
        On Error GoTo EH

        If Not b Is Nothing Then
            bt = SafeGetBodyType(b)
            Debug.Print TimeStamp() & " | INFO  | [" & cutFeat.Name & "] Body(" & i & ") type = " & bt & " [" & BodyTypeName(bt) & "]"

            If bt = BODYTYPE_SOLID Then
                Set GetRepresentativeBodyFromCutList = b
                Debug.Print TimeStamp() & " | INFO  | [" & cutFeat.Name & "] representative = SOLID body index " & i
                Exit Function
            End If
        Else
            Debug.Print TimeStamp() & " | WARN  | [" & cutFeat.Name & "] Body(" & i & ") is Nothing"
        End If
    Next i

    For i = LBound(vBodies) To UBound(vBodies)
        Set b = Nothing
        On Error Resume Next
        Set b = vBodies(i)
        On Error GoTo EH

        If Not b Is Nothing Then
            bt = SafeGetBodyType(b)

            If bt = BODYTYPE_SHEET Or bt = BODYTYPE_GENERAL Then
                Set GetRepresentativeBodyFromCutList = b
                Debug.Print TimeStamp() & " | INFO  | [" & cutFeat.Name & "] representative = fallback body index " & i & " [" & BodyTypeName(bt) & "]"
                Exit Function
            End If
        End If
    Next i

    Debug.Print TimeStamp() & " | FAIL  | [" & cutFeat.Name & "] no usable representative body found"
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetRepresentativeBodyFromCutList(" & cutFeat.Name & "): " & Err.Number & " - " & Err.Description
End Function

Private Function GetRepresentativeBodyFromPart(ByVal mdl As SldWorks.ModelDoc2) As SldWorks.Body2
    On Error GoTo EH

    If mdl Is Nothing Then Exit Function
    If mdl.GetType <> swDocPART Then Exit Function

    Dim p As SldWorks.PartDoc
    Set p = mdl

    Dim vBodies As Variant
    vBodies = p.GetBodies2(swSolidBody, True)

    If IsEmpty(vBodies) Then
        Debug.Print TimeStamp() & " | WARN  | No solid bodies found. Trying all bodies for regular part."
        vBodies = p.GetBodies2(swAllBodies, True)
    End If

    If IsEmpty(vBodies) Then
        Debug.Print TimeStamp() & " | FAIL  | GetBodies2 returned Empty for regular part"
        Exit Function
    End If

    If Not IsArray(vBodies) Then
        Debug.Print TimeStamp() & " | FAIL  | GetBodies2 did not return an array for regular part"
        Exit Function
    End If

    Dim i As Long
    Dim b As SldWorks.Body2
    Dim bt As Long

    For i = LBound(vBodies) To UBound(vBodies)
        Set b = Nothing
        On Error Resume Next
        Set b = vBodies(i)
        On Error GoTo EH

        If Not b Is Nothing Then
            bt = SafeGetBodyType(b)
            Debug.Print TimeStamp() & " | INFO  | Regular part Body(" & i & ") type = " & bt & " [" & BodyTypeName(bt) & "]"

            If bt = BODYTYPE_SOLID Then
                Set GetRepresentativeBodyFromPart = b
                Debug.Print TimeStamp() & " | INFO  | Regular part representative = SOLID body index " & i
                Exit Function
            End If
        Else
            Debug.Print TimeStamp() & " | WARN  | Regular part Body(" & i & ") is Nothing"
        End If
    Next i

    For i = LBound(vBodies) To UBound(vBodies)
        Set b = Nothing
        On Error Resume Next
        Set b = vBodies(i)
        On Error GoTo EH

        If Not b Is Nothing Then
            bt = SafeGetBodyType(b)

            If bt = BODYTYPE_SHEET Or bt = BODYTYPE_GENERAL Then
                Set GetRepresentativeBodyFromPart = b
                Debug.Print TimeStamp() & " | INFO  | Regular part representative = fallback body index " & i & " [" & BodyTypeName(bt) & "]"
                Exit Function
            End If
        End If
    Next i

    Debug.Print TimeStamp() & " | FAIL  | No usable representative body found for regular part"
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetRepresentativeBodyFromPart(" & mdl.GetTitle & "): " & Err.Number & " - " & Err.Description
End Function


Private Function SafeGetBodyType(ByVal body As SldWorks.Body2) As Long
    On Error GoTo EH
    SafeGetBodyType = body.GetType
    Exit Function
EH:
    Debug.Print TimeStamp() & " | ERROR | SafeGetBodyType: " & Err.Number & " - " & Err.Description
    SafeGetBodyType = -999
End Function

Private Function BodyTypeName(ByVal bodyType As Long) As String
    Select Case bodyType
        Case BODYTYPE_SOLID:   BodyTypeName = "SOLID"
        Case BODYTYPE_SHEET:   BodyTypeName = "SHEET"
        Case BODYTYPE_WIRE:    BodyTypeName = "WIRE"
        Case BODYTYPE_MINIMUM: BodyTypeName = "MINIMUM"
        Case BODYTYPE_GENERAL: BodyTypeName = "GENERAL"
        Case BODYTYPE_EMPTY:   BodyTypeName = "EMPTY"
        Case Else:             BodyTypeName = "UNKNOWN"
    End Select
End Function

Private Function CountUsableBodiesInPart(ByVal mdl As SldWorks.ModelDoc2) As Long
    On Error GoTo EH

    CountUsableBodiesInPart = 0

    If mdl Is Nothing Then Exit Function
    If mdl.GetType <> swDocPART Then Exit Function

    Dim p As SldWorks.PartDoc
    Set p = mdl

    Dim vBodies As Variant
    vBodies = p.GetBodies2(swAllBodies, True)

    If IsEmpty(vBodies) Then
        Debug.Print TimeStamp() & " | WARN  | CountUsableBodiesInPart: GetBodies2 returned Empty"
        Exit Function
    End If

    If Not IsArray(vBodies) Then
        Debug.Print TimeStamp() & " | WARN  | CountUsableBodiesInPart: GetBodies2 did not return an array"
        Exit Function
    End If

    Dim i As Long
    Dim b As SldWorks.Body2
    Dim bt As Long

    For i = LBound(vBodies) To UBound(vBodies)
        Set b = Nothing
        On Error Resume Next
        Set b = vBodies(i)
        On Error GoTo EH

        If Not b Is Nothing Then
            bt = SafeGetBodyType(b)
            If bt = BODYTYPE_SOLID Or bt = BODYTYPE_SHEET Or bt = BODYTYPE_GENERAL Then
                CountUsableBodiesInPart = CountUsableBodiesInPart + 1
            End If
        End If
    Next i

    Debug.Print TimeStamp() & " | INFO  | CountUsableBodiesInPart = " & CStr(CountUsableBodiesInPart)
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | CountUsableBodiesInPart(" & mdl.GetTitle & "): " & Err.Number & " - " & Err.Description
End Function

Private Function GetEffectivePartLevelDxfFlag(ByVal mdl As SldWorks.ModelDoc2, _
                                              ByRef sourcePropName As String, _
                                              ByRef rawValOut As String) As String
    On Error GoTo EH

    Dim rawPrimary As String
    Dim rawLegacy As String
    Dim evalPrimary As String
    Dim evalLegacy As String

    sourcePropName = PROP_DXF
    rawValOut = ""
    GetEffectivePartLevelDxfFlag = ""

    evalPrimary = GetEvaluatedModelProperty(mdl, PROP_DXF, rawPrimary)
    Debug.Print TimeStamp() & " | INFO  | Effective part export lookup primary [" & PROP_DXF & "] raw=[" & rawPrimary & "] eval=[" & evalPrimary & "]"

    If Len(Trim$(evalPrimary)) > 0 Or Len(Trim$(rawPrimary)) > 0 Then
        sourcePropName = PROP_DXF
        rawValOut = rawPrimary
        GetEffectivePartLevelDxfFlag = evalPrimary
        Exit Function
    End If

    evalLegacy = GetEvaluatedModelProperty(mdl, PROP_DXY, rawLegacy)
    Debug.Print TimeStamp() & " | INFO  | Effective part export lookup legacy [" & PROP_DXY & "] raw=[" & rawLegacy & "] eval=[" & evalLegacy & "]"

    sourcePropName = PROP_DXY
    rawValOut = rawLegacy
    GetEffectivePartLevelDxfFlag = evalLegacy
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetEffectivePartLevelDxfFlag: " & Err.Number & " - " & Err.Description
End Function

'=========================================================================================
' PROPERTY HELPERS
'=========================================================================================
Private Function GetEvaluatedCutListProperty(ByVal cpMgr As SldWorks.CustomPropertyManager, _
                                             ByVal propName As String, _
                                             ByRef rawValOut As String) As String
    On Error GoTo EH

    rawValOut = ""

    If cpMgr Is Nothing Then Exit Function

    Dim rawVal As String
    Dim evalVal As String
    Dim wasResolved As Boolean
    Dim isLinked As Boolean
    Dim ret As Long

    rawVal = ""
    evalVal = ""
    wasResolved = False
    isLinked = False

    ret = cpMgr.Get6(propName, False, rawVal, evalVal, wasResolved, isLinked)

    rawValOut = NzStr(rawVal)

    If Len(Trim$(evalVal)) > 0 Then
        GetEvaluatedCutListProperty = Trim$(evalVal)
    Else
        GetEvaluatedCutListProperty = Trim$(rawVal)
    End If

    Exit Function
EH:
    Debug.Print TimeStamp() & " | ERROR | GetEvaluatedCutListProperty(" & propName & "): " & Err.Number & " - " & Err.Description
End Function

Private Function GetEvaluatedModelProperty(ByVal mdl As SldWorks.ModelDoc2, _
                                           ByVal propName As String, _
                                           ByRef rawValOut As String) As String
    On Error GoTo EH

    rawValOut = ""
    GetEvaluatedModelProperty = ""

    If mdl Is Nothing Then Exit Function

    Dim cfgName As String
    Dim cpMgr As SldWorks.CustomPropertyManager
    Dim tempRaw As String
    Dim tempEval As String

    cfgName = GetActiveConfigurationName(mdl)

    If Len(cfgName) > 0 Then
        Set cpMgr = mdl.Extension.CustomPropertyManager(cfgName)
        If Not cpMgr Is Nothing Then
            tempEval = GetEvaluatedPropertyValue(cpMgr, propName, tempRaw)
            Debug.Print TimeStamp() & " | INFO  | Config property lookup [" & cfgName & "] " & propName & " raw=[" & tempRaw & "] eval=[" & tempEval & "]"
            If Len(Trim$(tempEval)) > 0 Or Len(Trim$(tempRaw)) > 0 Then
                rawValOut = tempRaw
                GetEvaluatedModelProperty = tempEval
                Exit Function
            End If
        End If
    End If

    Set cpMgr = mdl.Extension.CustomPropertyManager("")
    If Not cpMgr Is Nothing Then
        tempEval = GetEvaluatedPropertyValue(cpMgr, propName, tempRaw)
        Debug.Print TimeStamp() & " | INFO  | File property lookup " & propName & " raw=[" & tempRaw & "] eval=[" & tempEval & "]"
        rawValOut = tempRaw
        GetEvaluatedModelProperty = tempEval
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetEvaluatedModelProperty(" & propName & "): " & Err.Number & " - " & Err.Description
End Function

Private Function GetEvaluatedPropertyValue(ByVal cpMgr As SldWorks.CustomPropertyManager, _
                                           ByVal propName As String, _
                                           ByRef rawValOut As String) As String
    On Error GoTo EH

    rawValOut = ""

    If cpMgr Is Nothing Then Exit Function

    Dim rawVal As String
    Dim evalVal As String
    Dim wasResolved As Boolean
    Dim isLinked As Boolean
    Dim ret As Long

    rawVal = ""
    evalVal = ""
    wasResolved = False
    isLinked = False

    ret = cpMgr.Get6(propName, False, rawVal, evalVal, wasResolved, isLinked)

    rawValOut = NzStr(rawVal)

    If Len(Trim$(evalVal)) > 0 Then
        GetEvaluatedPropertyValue = Trim$(evalVal)
    Else
        GetEvaluatedPropertyValue = Trim$(rawVal)
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetEvaluatedPropertyValue(" & propName & "): " & Err.Number & " - " & Err.Description
End Function



Private Function GetExportOrientationForBody(ByVal srcBody As SldWorks.Body2, _
                                             ByVal contextLabel As String, _
                                             ByRef faceN() As Double, _
                                             ByRef xDir() As Double, _
                                             ByRef usedFallbackEdge As Boolean, _
                                             ByRef usedPerpCorner As Boolean) As Boolean
    On Error GoTo EH

    GetExportOrientationForBody = False
    usedFallbackEdge = False
    usedPerpCorner = False

    If srcBody Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | GetExportOrientationForBody: srcBody is Nothing for " & contextLabel
        Exit Function
    End If

    If gHasOrientationOverride Then
        faceN(0) = gOrientationOverrideZ(0)
        faceN(1) = gOrientationOverrideZ(1)
        faceN(2) = gOrientationOverrideZ(2)

        xDir(0) = gOrientationOverrideX(0)
        xDir(1) = gOrientationOverrideX(1)
        xDir(2) = gOrientationOverrideX(2)

        Debug.Print TimeStamp() & " | INFO  | Orientation mode = DRAWING_SELECTED_VIEW override"
        Debug.Print TimeStamp() & " | INFO  | Override label   = " & gOrientationOverrideLabel
        Debug.Print TimeStamp() & " | INFO  | Override X       = (" & Dbl3ToStr(xDir) & ")"
        Debug.Print TimeStamp() & " | INFO  | Override Z       = (" & Dbl3ToStr(faceN) & ")"

        GetExportOrientationForBody = True
        Exit Function
    End If

    Dim refFace As SldWorks.Face2
    Set refFace = FindLargestPlanarFace(srcBody)

    If refFace Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | No planar face found on representative body for " & contextLabel
        Exit Function
    End If

    If Not GetStableFaceNormal(refFace, faceN) Then
        Debug.Print TimeStamp() & " | FAIL  | Could not obtain face normal for " & contextLabel
        Exit Function
    End If

    If Not FindHorizontalDirectionFromFace(refFace, faceN, xDir, usedFallbackEdge, usedPerpCorner) Then
        Debug.Print TimeStamp() & " | FAIL  | Could not determine horizontal direction for " & contextLabel
        Exit Function
    End If

    GetExportOrientationForBody = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetExportOrientationForBody(" & contextLabel & "): " & Err.Number & " - " & Err.Description
End Function

'=========================================================================================
' GEOMETRY / ORIENTATION
'=========================================================================================
Private Function FindLargestPlanarFace(ByVal body As SldWorks.Body2) As SldWorks.Face2
    On Error GoTo EH

    Dim vFaces As Variant
    vFaces = body.GetFaces

    If IsEmpty(vFaces) Then Exit Function
    If Not IsArray(vFaces) Then Exit Function

    Dim i As Long
    Dim bestArea As Double
    bestArea = -1#

    For i = LBound(vFaces) To UBound(vFaces)
        Dim f As SldWorks.Face2
        Set f = vFaces(i)

        If Not f Is Nothing Then
            Dim surf As SldWorks.Surface
            Set surf = f.GetSurface

            If Not surf Is Nothing Then
                If surf.IsPlane Then
                    Dim a As Double
                    a = 0#
                    On Error Resume Next
                    a = f.GetArea
                    On Error GoTo EH

                    If a > bestArea Then
                        bestArea = a
                        Set FindLargestPlanarFace = f
                    End If
                End If
            End If
        End If
    Next i

    Debug.Print TimeStamp() & " | INFO  | Largest planar face area = " & FormatNumber(bestArea, 8)
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | FindLargestPlanarFace: " & Err.Number & " - " & Err.Description
End Function

Private Function GetStableFaceNormal(ByVal face As SldWorks.Face2, ByRef n() As Double) As Boolean
    On Error GoTo EH

    GetStableFaceNormal = False

    Debug.Print TimeStamp() & " | INFO  | GetStableFaceNormal: start"

    If face Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | GetStableFaceNormal: face is Nothing"
        Exit Function
    End If

    If TryGetNormalFromFaceVertices(face, n) Then
        NormalizeVec n
        If VecLength(n) > EPS Then
            StabilizeVectorSign n
            Debug.Print TimeStamp() & " | INFO  | Face normal from face vertices = (" & Dbl3ToStr(n) & ")"
            GetStableFaceNormal = True
            Exit Function
        End If
    End If

    Debug.Print TimeStamp() & " | WARN  | Face vertex normal method failed, trying Face2.Normal"

    Dim vNorm As Variant
    On Error Resume Next
    vNorm = face.Normal
    On Error GoTo EH

    If VariantHas3Numbers(vNorm) Then
        n(0) = CDbl(vNorm(0))
        n(1) = CDbl(vNorm(1))
        n(2) = CDbl(vNorm(2))
        NormalizeVec n
        If VecLength(n) > EPS Then
            StabilizeVectorSign n
            Debug.Print TimeStamp() & " | INFO  | Face normal from Face2.Normal = (" & Dbl3ToStr(n) & ")"
            GetStableFaceNormal = True
            Exit Function
        End If
    Else
        Debug.Print TimeStamp() & " | WARN  | Face2.Normal did not return usable data"
    End If

    Debug.Print TimeStamp() & " | WARN  | Face2.Normal failed, trying Surface.PlaneParams"

    Dim surf As SldWorks.Surface
    Set surf = face.GetSurface

    If Not surf Is Nothing Then
        Dim planeProps As Variant
        On Error Resume Next
        planeProps = surf.PlaneParams
        On Error GoTo EH

        If VariantHasAtLeast6Numbers(planeProps) Then
            n(0) = CDbl(planeProps(3))
            n(1) = CDbl(planeProps(4))
            n(2) = CDbl(planeProps(5))
            NormalizeVec n
            If VecLength(n) > EPS Then
                StabilizeVectorSign n
                Debug.Print TimeStamp() & " | INFO  | Face normal from Surface.PlaneParams = (" & Dbl3ToStr(n) & ")"
                GetStableFaceNormal = True
                Exit Function
            End If
        Else
            Debug.Print TimeStamp() & " | WARN  | Surface.PlaneParams did not return usable data"
        End If
    Else
        Debug.Print TimeStamp() & " | WARN  | face.GetSurface returned Nothing inside GetStableFaceNormal"
    End If

    Debug.Print TimeStamp() & " | FAIL  | GetStableFaceNormal exhausted all methods"
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetStableFaceNormal: " & Err.Number & " - " & Err.Description
End Function

Private Function TryGetNormalFromFaceVertices(ByVal face As SldWorks.Face2, ByRef n() As Double) As Boolean
    On Error GoTo EH

    TryGetNormalFromFaceVertices = False

    Dim vEdges As Variant
    vEdges = face.GetEdges

    If IsEmpty(vEdges) Then
        Debug.Print TimeStamp() & " | WARN  | TryGetNormalFromFaceVertices: face.GetEdges returned Empty"
        Exit Function
    End If

    If Not IsArray(vEdges) Then
        Debug.Print TimeStamp() & " | WARN  | TryGetNormalFromFaceVertices: face.GetEdges did not return array"
        Exit Function
    End If

    Dim pts() As Double
    Dim ptCount As Long
    ptCount = 0

    Dim i As Long
    For i = LBound(vEdges) To UBound(vEdges)
        Dim ed As SldWorks.Edge
        Set ed = vEdges(i)

        If Not ed Is Nothing Then
            Dim p0(2) As Double, p1(2) As Double
            If GetEdgeEndPoints(ed, p0, p1) Then
                AddUniquePoint3 pts, ptCount, p0
                AddUniquePoint3 pts, ptCount, p1
            End If
        End If
    Next i

    Debug.Print TimeStamp() & " | INFO  | TryGetNormalFromFaceVertices: unique point count = " & ptCount

    If ptCount < 3 Then
        Debug.Print TimeStamp() & " | WARN  | TryGetNormalFromFaceVertices: fewer than 3 unique points"
        Exit Function
    End If

    Dim i0 As Long, i1 As Long, i2 As Long
    For i0 = 0 To ptCount - 3
        For i1 = i0 + 1 To ptCount - 2
            For i2 = i1 + 1 To ptCount - 1

                Dim a(2) As Double, b(2) As Double, cr(2) As Double
                a(0) = pts(0, i1) - pts(0, i0)
                a(1) = pts(1, i1) - pts(1, i0)
                a(2) = pts(2, i1) - pts(2, i0)

                b(0) = pts(0, i2) - pts(0, i0)
                b(1) = pts(1, i2) - pts(1, i0)
                b(2) = pts(2, i2) - pts(2, i0)

                CrossProduct a, b, cr

                If VecLength(cr) > EPS Then
                    NormalizeVec cr
                    n(0) = cr(0)
                    n(1) = cr(1)
                    n(2) = cr(2)

                    Debug.Print TimeStamp() & " | INFO  | TryGetNormalFromFaceVertices: using point indices " & i0 & "," & i1 & "," & i2
                    TryGetNormalFromFaceVertices = True
                    Exit Function
                End If
            Next i2
        Next i1
    Next i0

    Debug.Print TimeStamp() & " | WARN  | TryGetNormalFromFaceVertices: no non-collinear triplet found"
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | TryGetNormalFromFaceVertices: " & Err.Number & " - " & Err.Description
End Function

Private Sub AddUniquePoint3(ByRef pts() As Double, ByRef ptCount As Long, ByRef p() As Double)
    Dim i As Long

    For i = 0 To ptCount - 1
        If Abs(pts(0, i) - p(0)) <= PT_TOL _
        And Abs(pts(1, i) - p(1)) <= PT_TOL _
        And Abs(pts(2, i) - p(2)) <= PT_TOL Then
            Exit Sub
        End If
    Next i

    If ptCount = 0 Then
        ReDim pts(0 To 2, 0 To 0)
    Else
        ReDim Preserve pts(0 To 2, 0 To ptCount)
    End If

    pts(0, ptCount) = p(0)
    pts(1, ptCount) = p(1)
    pts(2, ptCount) = p(2)
    ptCount = ptCount + 1
End Sub

Private Function VariantHas3Numbers(ByVal v As Variant) As Boolean
    On Error GoTo EH

    VariantHas3Numbers = False
    If IsEmpty(v) Then Exit Function
    If Not IsArray(v) Then Exit Function

    Dim lb As Long, ub As Long
    lb = LBound(v)
    ub = UBound(v)

    If (ub - lb + 1) < 3 Then Exit Function

    Dim t0 As Double, t1 As Double, t2 As Double
    t0 = CDbl(v(lb + 0))
    t1 = CDbl(v(lb + 1))
    t2 = CDbl(v(lb + 2))

    VariantHas3Numbers = True
    Exit Function

EH:
    VariantHas3Numbers = False
End Function

Private Function VariantHasAtLeast6Numbers(ByVal v As Variant) As Boolean
    On Error GoTo EH

    VariantHasAtLeast6Numbers = False
    If IsEmpty(v) Then Exit Function
    If Not IsArray(v) Then Exit Function

    Dim lb As Long, ub As Long
    lb = LBound(v)
    ub = UBound(v)

    If (ub - lb + 1) < 6 Then Exit Function

    Dim i As Long, tmp As Double
    For i = 0 To 5
        tmp = CDbl(v(lb + i))
    Next i

    VariantHasAtLeast6Numbers = True
    Exit Function

EH:
    VariantHasAtLeast6Numbers = False
End Function

Private Function FindHorizontalDirectionFromFace(ByVal face As SldWorks.Face2, _
                                                 ByRef faceNormal() As Double, _
                                                 ByRef xDir() As Double, _
                                                 ByRef usedFallback As Boolean, _
                                                 ByRef usedPerpCorner As Boolean) As Boolean
    On Error GoTo EH

    FindHorizontalDirectionFromFace = False
    usedFallback = False
    usedPerpCorner = False

    Dim tabAwareFound As Boolean
    Dim sharedFound As Boolean
    Dim virtualFound As Boolean

    Dim tabPrimaryLen As Double
    Dim tabSecondaryLen As Double
    Dim tabX(2) As Double
    Dim tabY(2) As Double
    Dim tabCorner(2) As Double

    Dim sharedPrimaryLen As Double
    Dim sharedSecondaryLen As Double
    Dim sharedX(2) As Double
    Dim sharedY(2) As Double
    Dim sharedCorner(2) As Double

    Dim virtualPrimaryLen As Double
    Dim virtualSecondaryLen As Double
    Dim virtualX(2) As Double
    Dim virtualY(2) As Double
    Dim virtualCorner(2) As Double

    If ENABLE_TAB_AWARE_GUSSET_MODE Then
        LogEvent " | INFO  | Tab-aware gusset orientation scan: start"
        tabAwareFound = GetBestTabAwareGussetOrientationCandidate(face, faceNormal, tabPrimaryLen, tabSecondaryLen, tabX, tabY, tabCorner)

        If tabAwareFound Then
            LogEvent " | INFO  | Tab-aware gusset orientation candidate accepted before legacy pair-length logic"
            If ApplyBottomLeftOrientationCandidate(faceNormal, xDir, tabX, tabY, tabCorner, tabPrimaryLen, tabSecondaryLen, "Tab-aware gusset orientation", "Manufacturing corner") Then
                usedPerpCorner = True
                FindHorizontalDirectionFromFace = True
                Exit Function
            Else
                LogEvent " | WARN  | Tab-aware gusset candidate was found but could not be applied"
            End If
        Else
            LogEvent " | INFO  | Tab-aware gusset orientation scan found no qualifying manufacturing corner"
        End If
    End If

    sharedFound = GetBestSharedCornerOrientationCandidate(face, faceNormal, sharedPrimaryLen, sharedSecondaryLen, sharedX, sharedY, sharedCorner)

    If sharedFound Then
        LogEvent " | INFO  | Shared-corner perpendicular pair found; checking non-intersecting perpendicular pairs for chamfer override"
        virtualFound = GetBestVirtualCornerOrientationCandidate(face, faceNormal, virtualPrimaryLen, virtualSecondaryLen, virtualX, virtualY, virtualCorner)

        If virtualFound Then
            LogEvent " | INFO  | Best shared-corner pair lengths     = " & FormatNumber(sharedPrimaryLen, 8) & " / " & FormatNumber(sharedSecondaryLen, 8)
            LogEvent " | INFO  | Best non-intersecting pair lengths = " & FormatNumber(virtualPrimaryLen, 8) & " / " & FormatNumber(virtualSecondaryLen, 8)

            If IsPairLengthBetter(virtualPrimaryLen, virtualSecondaryLen, sharedPrimaryLen, sharedSecondaryLen) Then
                LogEvent " | INFO  | Non-intersecting perpendicular pair is longer than shared-corner pair; using chamfer-ignore virtual corner orientation"
                If ApplyBottomLeftOrientationCandidate(faceNormal, xDir, virtualX, virtualY, virtualCorner, virtualPrimaryLen, virtualSecondaryLen, "Virtual corner orientation", "Virtual corner") Then
                    usedPerpCorner = True
                    FindHorizontalDirectionFromFace = True
                    Exit Function
                End If
            Else
                LogEvent " | INFO  | Shared-corner pair remains preferred because non-intersecting pair is not longer"
                If ApplyBottomLeftOrientationCandidate(faceNormal, xDir, sharedX, sharedY, sharedCorner, sharedPrimaryLen, sharedSecondaryLen, "Corner orientation", "Shared corner") Then
                    usedPerpCorner = True
                    FindHorizontalDirectionFromFace = True
                    Exit Function
                End If
            End If
        Else
            LogEvent " | INFO  | No qualifying non-intersecting perpendicular pair found; using shared-corner pair"
            If ApplyBottomLeftOrientationCandidate(faceNormal, xDir, sharedX, sharedY, sharedCorner, sharedPrimaryLen, sharedSecondaryLen, "Corner orientation", "Shared corner") Then
                usedPerpCorner = True
                FindHorizontalDirectionFromFace = True
                Exit Function
            End If
        End If
    Else
        LogEvent " | INFO  | No valid perpendicular shared-corner pair found; trying non-intersecting perpendicular pair fallback"

        virtualFound = GetBestVirtualCornerOrientationCandidate(face, faceNormal, virtualPrimaryLen, virtualSecondaryLen, virtualX, virtualY, virtualCorner)
        If virtualFound Then
            If ApplyBottomLeftOrientationCandidate(faceNormal, xDir, virtualX, virtualY, virtualCorner, virtualPrimaryLen, virtualSecondaryLen, "Virtual corner orientation", "Virtual corner") Then
                usedPerpCorner = True
                FindHorizontalDirectionFromFace = True
                Exit Function
            End If
        End If
    End If

    LogEvent " | INFO  | No usable perpendicular edge pair found; trying longest single edge fallback"

    Dim vEdges As Variant
    vEdges = face.GetEdges

    Dim bestLen As Double
    bestLen = -1#

    Dim bestVec(2) As Double
    Dim foundLine As Boolean
    foundLine = False

    If Not IsEmpty(vEdges) Then
        If IsArray(vEdges) Then
            Dim i As Long
            For i = LBound(vEdges) To UBound(vEdges)
                Dim ed As SldWorks.Edge
                Set ed = vEdges(i)
                If Not ed Is Nothing Then
                    If EdgeIsLinear(ed) Then
                        Dim p0(2) As Double, p1(2) As Double
                        If GetEdgeEndPoints(ed, p0, p1) Then
                            Dim v(2) As Double
                            v(0) = p1(0) - p0(0)
                            v(1) = p1(1) - p0(1)
                            v(2) = p1(2) - p0(2)

                            ProjectVectorOntoPlane v, faceNormal, v
                            Dim L As Double
                            L = VecLength(v)

                            If L > EPS Then
                                NormalizeVec v
                                StabilizeVectorSign v

                                Dim trueLen As Double
                                trueLen = Distance3(p0, p1)

                                If (trueLen > bestLen + EPS) Or _
                                   (Abs(trueLen - bestLen) <= EPS And CompareVectorLex(v, bestVec) > 0) Then
                                    bestLen = trueLen
                                    bestVec(0) = v(0)
                                    bestVec(1) = v(1)
                                    bestVec(2) = v(2)
                                    foundLine = True
                                End If
                            End If
                        End If
                    End If
                End If
            Next i
        End If
    End If

    If foundLine Then
        xDir(0) = bestVec(0)
        xDir(1) = bestVec(1)
        xDir(2) = bestVec(2)
        NormalizeVec xDir
        LogEvent " | INFO  | Longest edge dir fallback = (" & Dbl3ToStr(xDir) & "), length = " & FormatNumber(bestLen, 8)
        FindHorizontalDirectionFromFace = True
        Exit Function
    End If

    LogEvent " | WARN  | No valid linear edge found on face; using fallback orientation axis"
    ChooseFallbackXAxis faceNormal, xDir
    usedFallback = True
    FindHorizontalDirectionFromFace = True
    Exit Function

EH:
    LogEvent " | ERROR | FindHorizontalDirectionFromFace: " & Err.Number & " - " & Err.Description
End Function

Private Function EdgeIsLinear(ByVal ed As SldWorks.Edge) As Boolean
    On Error GoTo EH

    EdgeIsLinear = False

    Dim crv As SldWorks.Curve
    Set crv = ed.GetCurve
    If crv Is Nothing Then Exit Function

    EdgeIsLinear = crv.IsLine
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | EdgeIsLinear: " & Err.Number & " - " & Err.Description
End Function

Private Function GetEdgeEndPoints(ByVal ed As SldWorks.Edge, ByRef p0() As Double, ByRef p1() As Double) As Boolean
    On Error GoTo EH

    GetEdgeEndPoints = False

    Dim vStart As SldWorks.Vertex
    Dim vEnd As SldWorks.Vertex

    Set vStart = ed.GetStartVertex
    Set vEnd = ed.GetEndVertex

    If vStart Is Nothing Or vEnd Is Nothing Then Exit Function

    Dim a As Variant, b As Variant
    a = vStart.GetPoint
    b = vEnd.GetPoint

    If IsEmpty(a) Or IsEmpty(b) Then Exit Function

    p0(0) = CDbl(a(0)): p0(1) = CDbl(a(1)): p0(2) = CDbl(a(2))
    p1(0) = CDbl(b(0)): p1(1) = CDbl(b(1)): p1(2) = CDbl(b(2))

    GetEdgeEndPoints = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetEdgeEndPoints: " & Err.Number & " - " & Err.Description
End Function

Private Function TryGetBottomLeftCornerOrientation(ByVal face As SldWorks.Face2, _
                                                   ByRef faceNormal() As Double, _
                                                   ByRef xDir() As Double) As Boolean
    On Error GoTo EH

    Dim bestPrimaryLen As Double
    Dim bestSecondaryLen As Double
    Dim bestX(2) As Double
    Dim bestY(2) As Double
    Dim bestCorner(2) As Double

    TryGetBottomLeftCornerOrientation = False

    If GetBestSharedCornerOrientationCandidate(face, faceNormal, bestPrimaryLen, bestSecondaryLen, bestX, bestY, bestCorner) Then
        TryGetBottomLeftCornerOrientation = ApplyBottomLeftOrientationCandidate(faceNormal, xDir, bestX, bestY, bestCorner, bestPrimaryLen, bestSecondaryLen, "Corner orientation", "Shared corner")
    Else
        Debug.Print TimeStamp() & " | INFO  | Corner orientation scan: no perpendicular shared-corner pair satisfied tolerance"
    End If
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | TryGetBottomLeftCornerOrientation: " & Err.Number & " - " & Err.Description
End Function

Private Function GetBestTabAwareGussetOrientationCandidate(ByVal face As SldWorks.Face2, _
                                                           ByRef faceNormal() As Double, _
                                                           ByRef bestPrimaryLen As Double, _
                                                           ByRef bestSecondaryLen As Double, _
                                                           ByRef bestX() As Double, _
                                                           ByRef bestY() As Double, _
                                                           ByRef bestCorner() As Double) As Boolean
    On Error GoTo EH

    GetBestTabAwareGussetOrientationCandidate = False

    If face Is Nothing Then Exit Function

    Dim pts() As Double
    Dim ptCount As Long
    ptCount = 0

    If Not CollectUniqueFaceBoundaryPoints(face, pts, ptCount) Then
        LogEvent " | INFO  | Tab-aware gusset scan: no usable boundary points"
        Exit Function
    End If

    LogEvent " | INFO  | Tab-aware gusset scan: boundary point count = " & ptCount

    Dim vEdges As Variant
    vEdges = face.GetEdges

    If IsEmpty(vEdges) Then Exit Function
    If Not IsArray(vEdges) Then Exit Function

    bestPrimaryLen = -1#
    bestSecondaryLen = -1#

    Dim bestArea As Double
    Dim bestNegMax As Double
    bestArea = -1#
    bestNegMax = 1E+30

    Dim i As Long
    Dim j As Long

    For i = LBound(vEdges) To UBound(vEdges)
        Dim ed1 As SldWorks.Edge
        Set ed1 = vEdges(i)

        If Not ed1 Is Nothing Then
            If EdgeIsLinear(ed1) Then
                Dim e1p0(2) As Double, e1p1(2) As Double

                If GetEdgeEndPoints(ed1, e1p0, e1p1) Then
                    For j = i + 1 To UBound(vEdges)
                        Dim ed2 As SldWorks.Edge
                        Set ed2 = vEdges(j)

                        If Not ed2 Is Nothing Then
                            If EdgeIsLinear(ed2) Then
                                Dim e2p0(2) As Double, e2p1(2) As Double

                                If GetEdgeEndPoints(ed2, e2p0, e2p1) Then
                                    Dim corner(2) As Double
                                    Dim e1Far(2) As Double
                                    Dim e2Far(2) As Double

                                    If TryGetSharedCornerFromEdgeEndpoints(e1p0, e1p1, e2p0, e2p1, corner, e1Far, e2Far) Then
                                        Dim dir1(2) As Double
                                        Dim dir2(2) As Double
                                        Dim len1 As Double
                                        Dim len2 As Double

                                        dir1(0) = e1Far(0) - corner(0)
                                        dir1(1) = e1Far(1) - corner(1)
                                        dir1(2) = e1Far(2) - corner(2)

                                        dir2(0) = e2Far(0) - corner(0)
                                        dir2(1) = e2Far(1) - corner(1)
                                        dir2(2) = e2Far(2) - corner(2)

                                        ProjectVectorOntoPlane dir1, faceNormal, dir1
                                        ProjectVectorOntoPlane dir2, faceNormal, dir2

                                        len1 = VecLength(dir1)
                                        len2 = VecLength(dir2)

                                        If len1 > EPS And len2 > EPS Then
                                            NormalizeVec dir1
                                            NormalizeVec dir2

                                            Dim perpDot As Double
                                            perpDot = Abs(DotProduct(dir1, dir2))

                                            If perpDot <= PERP_DOT_TOL Then
                                                Dim candPrimaryLen As Double
                                                Dim candSecondaryLen As Double
                                                Dim candX(2) As Double
                                                Dim candY(2) As Double
                                                Dim candNegMax As Double
                                                Dim candArea As Double

                                                If EvaluateTabAwareCornerCandidate(pts, ptCount, corner, dir1, dir2, candPrimaryLen, candSecondaryLen, candX, candY, candNegMax, candArea) Then
                                                    LogEvent " | INFO  | Tab-aware candidate accepted | EdgeIdx=" & i & "/" & j & _
                                                                " | corner=(" & Dbl3ToStr(corner) & ")" & _
                                                                " | primary=" & FormatNumber(candPrimaryLen, 8) & _
                                                                " | secondary=" & FormatNumber(candSecondaryLen, 8) & _
                                                                " | negMax=" & FormatNumber(candNegMax, 8) & _
                                                                " | area=" & FormatNumber(candArea, 8)

                                                    If IsTabAwareCandidateBetter(candPrimaryLen, candSecondaryLen, candArea, candNegMax, candX, _
                                                                                 bestPrimaryLen, bestSecondaryLen, bestArea, bestNegMax, bestX) Then
                                                        bestPrimaryLen = candPrimaryLen
                                                        bestSecondaryLen = candSecondaryLen
                                                        bestArea = candArea
                                                        bestNegMax = candNegMax

                                                        bestX(0) = candX(0): bestX(1) = candX(1): bestX(2) = candX(2)
                                                        bestY(0) = candY(0): bestY(1) = candY(1): bestY(2) = candY(2)
                                                        bestCorner(0) = corner(0): bestCorner(1) = corner(1): bestCorner(2) = corner(2)

                                                        GetBestTabAwareGussetOrientationCandidate = True
                                                    End If
                                                Else
                                                    LogEvent " | INFO  | Tab-aware candidate rejected | EdgeIdx=" & i & "/" & j & _
                                                                " | corner=(" & Dbl3ToStr(corner) & ")"
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next j
                End If
            End If
        End If
    Next i

    Exit Function

EH:
    LogEvent " | ERROR | GetBestTabAwareGussetOrientationCandidate: " & Err.Number & " - " & Err.Description
End Function

Private Function CollectUniqueFaceBoundaryPoints(ByVal face As SldWorks.Face2, _
                                                 ByRef pts() As Double, _
                                                 ByRef ptCount As Long) As Boolean
    On Error GoTo EH

    CollectUniqueFaceBoundaryPoints = False
    ptCount = 0

    If face Is Nothing Then Exit Function

    Dim vEdges As Variant
    vEdges = face.GetEdges

    If IsEmpty(vEdges) Then Exit Function
    If Not IsArray(vEdges) Then Exit Function

    Dim i As Long
    For i = LBound(vEdges) To UBound(vEdges)
        Dim ed As SldWorks.Edge
        Set ed = vEdges(i)

        If Not ed Is Nothing Then
            Dim p0(2) As Double, p1(2) As Double
            If GetEdgeEndPoints(ed, p0, p1) Then
                AddUniquePoint3 pts, ptCount, p0
                AddUniquePoint3 pts, ptCount, p1
            End If
        End If
    Next i

    CollectUniqueFaceBoundaryPoints = (ptCount >= 3)
    Exit Function

EH:
    LogEvent " | ERROR | CollectUniqueFaceBoundaryPoints: " & Err.Number & " - " & Err.Description
End Function

Private Function EvaluateTabAwareCornerCandidate(ByRef pts() As Double, _
                                                 ByVal ptCount As Long, _
                                                 ByRef corner() As Double, _
                                                 ByRef dir1() As Double, _
                                                 ByRef dir2() As Double, _
                                                 ByRef bestPrimaryLen As Double, _
                                                 ByRef bestSecondaryLen As Double, _
                                                 ByRef bestX() As Double, _
                                                 ByRef bestY() As Double, _
                                                 ByRef bestNegMax As Double, _
                                                 ByRef bestArea As Double) As Boolean
    On Error GoTo EH

    EvaluateTabAwareCornerCandidate = False

    If ptCount < 3 Then Exit Function

    Dim requiredLeg As Double
    requiredLeg = TAB_AWARE_MIN_EFFECTIVE_LEG_M

    Dim ratioLeg As Double
    ratioLeg = TAB_AWARE_USER_TAB_MAX_M * TAB_AWARE_MIN_LEG_TO_TAB_RATIO
    If ratioLeg > requiredLeg Then requiredLeg = ratioLeg

    bestPrimaryLen = -1#
    bestSecondaryLen = -1#
    bestNegMax = 1E+30
    bestArea = -1#

    Dim sx As Long
    Dim sy As Long

    For sx = -1 To 1 Step 2
        For sy = -1 To 1 Step 2

            Dim candX(2) As Double
            Dim candY(2) As Double

            candX(0) = sx * dir1(0)
            candX(1) = sx * dir1(1)
            candX(2) = sx * dir1(2)

            candY(0) = sy * dir2(0)
            candY(1) = sy * dir2(1)
            candY(2) = sy * dir2(2)

            NormalizeVec candX
            NormalizeVec candY

            Dim maxNegX As Double
            Dim maxNegY As Double
            Dim effX As Double
            Dim effY As Double

            maxNegX = 0#
            maxNegY = 0#
            effX = 0#
            effY = 0#

            Dim i As Long
            For i = 0 To ptCount - 1
                Dim rel(2) As Double
                rel(0) = pts(0, i) - corner(0)
                rel(1) = pts(1, i) - corner(1)
                rel(2) = pts(2, i) - corner(2)

                Dim u As Double
                Dim v As Double
                u = DotProduct(rel, candX)
                v = DotProduct(rel, candY)

                If u < 0# Then
                    If -u > maxNegX Then maxNegX = -u
                Else
                    If Abs(v) <= TAB_AWARE_AXIS_STRIP_HALF_WIDTH_M + EPS Then
                        If u > effX Then effX = u
                    End If
                End If

                If v < 0# Then
                    If -v > maxNegY Then maxNegY = -v
                Else
                    If Abs(u) <= TAB_AWARE_AXIS_STRIP_HALF_WIDTH_M + EPS Then
                        If v > effY Then effY = v
                    End If
                End If
            Next i

            Dim candNegMax As Double
            candNegMax = maxNegX
            If maxNegY > candNegMax Then candNegMax = maxNegY

            Dim candPrimary As Double
            Dim candSecondary As Double
            Dim candArea As Double
            Dim finalX(2) As Double
            Dim finalY(2) As Double

            If TAB_AWARE_PREFER_LONGER_LEG_HORIZONTAL Then
                If effY > effX + EPS Then
                    candPrimary = effY
                    candSecondary = effX
                    finalX(0) = candY(0): finalX(1) = candY(1): finalX(2) = candY(2)
                    finalY(0) = candX(0): finalY(1) = candX(1): finalY(2) = candX(2)
                Else
                    candPrimary = effX
                    candSecondary = effY
                    finalX(0) = candX(0): finalX(1) = candX(1): finalX(2) = candX(2)
                    finalY(0) = candY(0): finalY(1) = candY(1): finalY(2) = candY(2)
                End If
            Else
                candPrimary = effX
                candSecondary = effY
                finalX(0) = candX(0): finalX(1) = candX(1): finalX(2) = candX(2)
                finalY(0) = candY(0): finalY(1) = candY(1): finalY(2) = candY(2)
            End If

            candArea = candPrimary * candSecondary

            LogEvent " | INFO  | Tab-aware sign combo | sx=" & sx & " sy=" & sy & _
                        " | negX=" & FormatNumber(maxNegX, 8) & _
                        " | negY=" & FormatNumber(maxNegY, 8) & _
                        " | effX=" & FormatNumber(effX, 8) & _
                        " | effY=" & FormatNumber(effY, 8) & _
                        " | chosenPrimary=" & FormatNumber(candPrimary, 8) & _
                        " | chosenSecondary=" & FormatNumber(candSecondary, 8)

            If candNegMax <= TAB_AWARE_ALLOWANCE_M + EPS Then
                If candPrimary >= requiredLeg - EPS And candSecondary >= requiredLeg - EPS Then
                    If IsTabAwareCandidateBetter(candPrimary, candSecondary, candArea, candNegMax, finalX, _
                                                 bestPrimaryLen, bestSecondaryLen, bestArea, bestNegMax, bestX) Then
                        bestPrimaryLen = candPrimary
                        bestSecondaryLen = candSecondary
                        bestNegMax = candNegMax
                        bestArea = candArea

                        bestX(0) = finalX(0): bestX(1) = finalX(1): bestX(2) = finalX(2)
                        bestY(0) = finalY(0): bestY(1) = finalY(1): bestY(2) = finalY(2)

                        EvaluateTabAwareCornerCandidate = True
                    End If
                Else
                    LogEvent " | INFO  | Tab-aware sign combo rejected by minimum effective leg requirement = " & FormatNumber(requiredLeg, 8)
                End If
            Else
                LogEvent " | INFO  | Tab-aware sign combo rejected by negative extent allowance = " & FormatNumber(candNegMax, 8)
            End If
        Next sy
    Next sx

    Exit Function

EH:
    LogEvent " | ERROR | EvaluateTabAwareCornerCandidate: " & Err.Number & " - " & Err.Description
End Function

Private Function IsTabAwareCandidateBetter(ByVal candPrimary As Double, _
                                           ByVal candSecondary As Double, _
                                           ByVal candArea As Double, _
                                           ByVal candNegMax As Double, _
                                           ByRef candX() As Double, _
                                           ByVal bestPrimary As Double, _
                                           ByVal bestSecondary As Double, _
                                           ByVal bestArea As Double, _
                                           ByVal bestNegMax As Double, _
                                           ByRef bestX() As Double) As Boolean
    IsTabAwareCandidateBetter = False

    If candSecondary > bestSecondary + EPS Then
        IsTabAwareCandidateBetter = True
        Exit Function
    End If

    If Abs(candSecondary - bestSecondary) <= EPS Then
        If candArea > bestArea + EPS Then
            IsTabAwareCandidateBetter = True
            Exit Function
        End If

        If Abs(candArea - bestArea) <= EPS Then
            If candPrimary > bestPrimary + EPS Then
                IsTabAwareCandidateBetter = True
                Exit Function
            End If

            If Abs(candPrimary - bestPrimary) <= EPS Then
                If candNegMax < bestNegMax - EPS Then
                    IsTabAwareCandidateBetter = True
                    Exit Function
                End If

                If Abs(candNegMax - bestNegMax) <= EPS Then
                    If CompareVectorLex(candX, bestX) > 0 Then
                        IsTabAwareCandidateBetter = True
                        Exit Function
                    End If
                End If
            End If
        End If
    End If
End Function

Private Function GetBestSharedCornerOrientationCandidate(ByVal face As SldWorks.Face2, _
                                                         ByRef faceNormal() As Double, _
                                                         ByRef bestPrimaryLen As Double, _
                                                         ByRef bestSecondaryLen As Double, _
                                                         ByRef bestX() As Double, _
                                                         ByRef bestY() As Double, _
                                                         ByRef bestCorner() As Double) As Boolean
    On Error GoTo EH

    GetBestSharedCornerOrientationCandidate = False

    If face Is Nothing Then Exit Function

    Dim vEdges As Variant
    vEdges = face.GetEdges

    If IsEmpty(vEdges) Then
        Debug.Print TimeStamp() & " | INFO  | Corner orientation scan: face has no edges"
        Exit Function
    End If

    If Not IsArray(vEdges) Then
        Debug.Print TimeStamp() & " | INFO  | Corner orientation scan: face edges are not an array"
        Exit Function
    End If

    Dim foundPair As Boolean
    foundPair = False

    bestPrimaryLen = -1#
    bestSecondaryLen = -1#

    Dim i As Long
    Dim j As Long

    For i = LBound(vEdges) To UBound(vEdges)
        Dim ed1 As SldWorks.Edge
        Set ed1 = vEdges(i)

        If Not ed1 Is Nothing Then
            If EdgeIsLinear(ed1) Then

                Dim e1p0(2) As Double, e1p1(2) As Double
                If GetEdgeEndPoints(ed1, e1p0, e1p1) Then

                    For j = i + 1 To UBound(vEdges)
                        Dim ed2 As SldWorks.Edge
                        Set ed2 = vEdges(j)

                        If Not ed2 Is Nothing Then
                            If EdgeIsLinear(ed2) Then

                                Dim e2p0(2) As Double, e2p1(2) As Double
                                If GetEdgeEndPoints(ed2, e2p0, e2p1) Then

                                    Dim corner(2) As Double
                                    Dim e1Far(2) As Double
                                    Dim e2Far(2) As Double

                                    If TryGetSharedCornerFromEdgeEndpoints(e1p0, e1p1, e2p0, e2p1, corner, e1Far, e2Far) Then

                                        Dim dir1(2) As Double, dir2(2) As Double
                                        dir1(0) = e1Far(0) - corner(0)
                                        dir1(1) = e1Far(1) - corner(1)
                                        dir1(2) = e1Far(2) - corner(2)

                                        dir2(0) = e2Far(0) - corner(0)
                                        dir2(1) = e2Far(1) - corner(1)
                                        dir2(2) = e2Far(2) - corner(2)

                                        ProjectVectorOntoPlane dir1, faceNormal, dir1
                                        ProjectVectorOntoPlane dir2, faceNormal, dir2

                                        Dim len1 As Double, len2 As Double
                                        len1 = VecLength(dir1)
                                        len2 = VecLength(dir2)

                                        If len1 > EPS And len2 > EPS Then
                                            NormalizeVec dir1
                                            NormalizeVec dir2

                                            Dim perpDot As Double
                                            perpDot = Abs(DotProduct(dir1, dir2))

                                            Debug.Print TimeStamp() & " | INFO  | Corner pair candidate | EdgeIdx=" & i & "/" & j & _
                                                        " | corner=(" & Dbl3ToStr(corner) & ")" & _
                                                        " | len1=" & FormatNumber(len1, 8) & _
                                                        " | len2=" & FormatNumber(len2, 8) & _
                                                        " | |dot|=" & FormatNumber(perpDot, 8)

                                            If perpDot <= PERP_DOT_TOL Then

                                                Dim primaryLen As Double
                                                Dim secondaryLen As Double
                                                Dim candX(2) As Double
                                                Dim candY(2) As Double

                                                If (len1 > len2 + EPS) Or _
                                                   (Abs(len1 - len2) <= EPS And CompareVectorLex(dir1, dir2) >= 0) Then
                                                    primaryLen = len1
                                                    secondaryLen = len2
                                                    candX(0) = dir1(0): candX(1) = dir1(1): candX(2) = dir1(2)
                                                    candY(0) = dir2(0): candY(1) = dir2(1): candY(2) = dir2(2)
                                                Else
                                                    primaryLen = len2
                                                    secondaryLen = len1
                                                    candX(0) = dir2(0): candX(1) = dir2(1): candX(2) = dir2(2)
                                                    candY(0) = dir1(0): candY(1) = dir1(1): candY(2) = dir1(2)
                                                End If

                                                If (primaryLen > bestPrimaryLen + EPS) Or _
                                                   (Abs(primaryLen - bestPrimaryLen) <= EPS And secondaryLen > bestSecondaryLen + EPS) Or _
                                                   (Abs(primaryLen - bestPrimaryLen) <= EPS And Abs(secondaryLen - bestSecondaryLen) <= EPS And CompareVectorLex(candX, bestX) > 0) Then

                                                    bestPrimaryLen = primaryLen
                                                    bestSecondaryLen = secondaryLen

                                                    bestX(0) = candX(0): bestX(1) = candX(1): bestX(2) = candX(2)
                                                    bestY(0) = candY(0): bestY(1) = candY(1): bestY(2) = candY(2)

                                                    bestCorner(0) = corner(0)
                                                    bestCorner(1) = corner(1)
                                                    bestCorner(2) = corner(2)

                                                    foundPair = True
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next j
                End If
            End If
        End If
    Next i

    GetBestSharedCornerOrientationCandidate = foundPair
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetBestSharedCornerOrientationCandidate: " & Err.Number & " - " & Err.Description
End Function

Private Function TryGetBottomLeftVirtualCornerOrientation(ByVal face As SldWorks.Face2, _
                                                         ByRef faceNormal() As Double, _
                                                         ByRef xDir() As Double) As Boolean
    On Error GoTo EH

    Dim bestPrimaryLen As Double
    Dim bestSecondaryLen As Double
    Dim bestX(2) As Double
    Dim bestY(2) As Double
    Dim bestCorner(2) As Double

    TryGetBottomLeftVirtualCornerOrientation = False

    If GetBestVirtualCornerOrientationCandidate(face, faceNormal, bestPrimaryLen, bestSecondaryLen, bestX, bestY, bestCorner) Then
        TryGetBottomLeftVirtualCornerOrientation = ApplyBottomLeftOrientationCandidate(faceNormal, xDir, bestX, bestY, bestCorner, bestPrimaryLen, bestSecondaryLen, "Virtual corner orientation", "Virtual corner")
    Else
        Debug.Print TimeStamp() & " | INFO  | Virtual corner orientation scan: no non-intersecting perpendicular pair satisfied tolerance"
    End If
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | TryGetBottomLeftVirtualCornerOrientation: " & Err.Number & " - " & Err.Description
End Function

Private Function GetBestVirtualCornerOrientationCandidate(ByVal face As SldWorks.Face2, _
                                                          ByRef faceNormal() As Double, _
                                                          ByRef bestPrimaryLen As Double, _
                                                          ByRef bestSecondaryLen As Double, _
                                                          ByRef bestX() As Double, _
                                                          ByRef bestY() As Double, _
                                                          ByRef bestCorner() As Double) As Boolean
    On Error GoTo EH

    GetBestVirtualCornerOrientationCandidate = False

    If face Is Nothing Then Exit Function

    Dim vEdges As Variant
    vEdges = face.GetEdges

    If IsEmpty(vEdges) Then
        Debug.Print TimeStamp() & " | INFO  | Virtual corner orientation scan: face has no edges"
        Exit Function
    End If

    If Not IsArray(vEdges) Then
        Debug.Print TimeStamp() & " | INFO  | Virtual corner orientation scan: face edges are not an array"
        Exit Function
    End If

    Dim foundPair As Boolean
    foundPair = False

    bestPrimaryLen = -1#
    bestSecondaryLen = -1#

    Dim i As Long
    Dim j As Long

    For i = LBound(vEdges) To UBound(vEdges)
        Dim ed1 As SldWorks.Edge
        Set ed1 = vEdges(i)

        If Not ed1 Is Nothing Then
            If EdgeIsLinear(ed1) Then
                Dim e1p0(2) As Double, e1p1(2) As Double

                If GetEdgeEndPoints(ed1, e1p0, e1p1) Then
                    For j = i + 1 To UBound(vEdges)
                        Dim ed2 As SldWorks.Edge
                        Set ed2 = vEdges(j)

                        If Not ed2 Is Nothing Then
                            If EdgeIsLinear(ed2) Then
                                Dim e2p0(2) As Double, e2p1(2) As Double

                                If GetEdgeEndPoints(ed2, e2p0, e2p1) Then
                                    Dim sharedCorner(2) As Double
                                    Dim sharedFar1(2) As Double
                                    Dim sharedFar2(2) As Double

                                    If Not TryGetSharedCornerFromEdgeEndpoints(e1p0, e1p1, e2p0, e2p1, sharedCorner, sharedFar1, sharedFar2) Then
                                        Dim dir1Raw(2) As Double
                                        Dim dir2Raw(2) As Double
                                        Dim trueLen1 As Double
                                        Dim trueLen2 As Double

                                        dir1Raw(0) = e1p1(0) - e1p0(0)
                                        dir1Raw(1) = e1p1(1) - e1p0(1)
                                        dir1Raw(2) = e1p1(2) - e1p0(2)

                                        dir2Raw(0) = e2p1(0) - e2p0(0)
                                        dir2Raw(1) = e2p1(1) - e2p0(1)
                                        dir2Raw(2) = e2p1(2) - e2p0(2)

                                        ProjectVectorOntoPlane dir1Raw, faceNormal, dir1Raw
                                        ProjectVectorOntoPlane dir2Raw, faceNormal, dir2Raw

                                        trueLen1 = Distance3(e1p0, e1p1)
                                        trueLen2 = Distance3(e2p0, e2p1)

                                        If VecLength(dir1Raw) > EPS And VecLength(dir2Raw) > EPS Then
                                            NormalizeVec dir1Raw
                                            NormalizeVec dir2Raw

                                            Dim perpDot As Double
                                            perpDot = Abs(DotProduct(dir1Raw, dir2Raw))

                                            Debug.Print TimeStamp() & " | INFO  | Virtual corner pair candidate | EdgeIdx=" & i & "/" & j & _
                                                        " | len1=" & FormatNumber(trueLen1, 8) & _
                                                        " | len2=" & FormatNumber(trueLen2, 8) & _
                                                        " | |dot|=" & FormatNumber(perpDot, 8)

                                            If perpDot <= PERP_DOT_TOL Then
                                                Dim virtualCorner(2) As Double

                                                If TryGetProjectedLineIntersection(e1p0, dir1Raw, e2p0, dir2Raw, faceNormal, virtualCorner) Then
                                                    Dim dir1(2) As Double
                                                    Dim dir2(2) As Double

                                                    If GetEdgeDirectionAwayFromReference(e1p0, e1p1, virtualCorner, dir1) Then
                                                        If GetEdgeDirectionAwayFromReference(e2p0, e2p1, virtualCorner, dir2) Then
                                                            Dim primaryLen As Double
                                                            Dim secondaryLen As Double
                                                            Dim candX(2) As Double
                                                            Dim candY(2) As Double

                                                            If (trueLen1 > trueLen2 + EPS) Or _
                                                               (Abs(trueLen1 - trueLen2) <= EPS And CompareVectorLex(dir1, dir2) >= 0) Then
                                                                primaryLen = trueLen1
                                                                secondaryLen = trueLen2
                                                                candX(0) = dir1(0): candX(1) = dir1(1): candX(2) = dir1(2)
                                                                candY(0) = dir2(0): candY(1) = dir2(1): candY(2) = dir2(2)
                                                            Else
                                                                primaryLen = trueLen2
                                                                secondaryLen = trueLen1
                                                                candX(0) = dir2(0): candX(1) = dir2(1): candX(2) = dir2(2)
                                                                candY(0) = dir1(0): candY(1) = dir1(1): candY(2) = dir1(2)
                                                            End If

                                                            If (primaryLen > bestPrimaryLen + EPS) Or _
                                                               (Abs(primaryLen - bestPrimaryLen) <= EPS And secondaryLen > bestSecondaryLen + EPS) Or _
                                                               (Abs(primaryLen - bestPrimaryLen) <= EPS And Abs(secondaryLen - bestSecondaryLen) <= EPS And CompareVectorLex(candX, bestX) > 0) Then
                                                                bestPrimaryLen = primaryLen
                                                                bestSecondaryLen = secondaryLen

                                                                bestX(0) = candX(0): bestX(1) = candX(1): bestX(2) = candX(2)
                                                                bestY(0) = candY(0): bestY(1) = candY(1): bestY(2) = candY(2)

                                                                bestCorner(0) = virtualCorner(0)
                                                                bestCorner(1) = virtualCorner(1)
                                                                bestCorner(2) = virtualCorner(2)

                                                                foundPair = True
                                                            End If
                                                        End If
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next j
                End If
            End If
        End If
    Next i

    GetBestVirtualCornerOrientationCandidate = foundPair
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetBestVirtualCornerOrientationCandidate: " & Err.Number & " - " & Err.Description
End Function

Private Function IsPairLengthBetter(ByVal candidatePrimaryLen As Double, _
                                    ByVal candidateSecondaryLen As Double, _
                                    ByVal referencePrimaryLen As Double, _
                                    ByVal referenceSecondaryLen As Double) As Boolean
    IsPairLengthBetter = False

    If candidatePrimaryLen > referencePrimaryLen + EPS Then
        IsPairLengthBetter = True
        Exit Function
    End If

    If Abs(candidatePrimaryLen - referencePrimaryLen) <= EPS Then
        If candidateSecondaryLen > referenceSecondaryLen + EPS Then
            IsPairLengthBetter = True
            Exit Function
        End If
    End If
End Function

Private Function ApplyBottomLeftOrientationCandidate(ByRef faceNormal() As Double, _
                                                     ByRef xDir() As Double, _
                                                     ByRef bestX() As Double, _
                                                     ByRef bestY() As Double, _
                                                     ByRef bestCorner() As Double, _
                                                     ByVal bestPrimaryLen As Double, _
                                                     ByVal bestSecondaryLen As Double, _
                                                     ByVal selectionLabel As String, _
                                                     ByVal cornerLabel As String) As Boolean
    On Error GoTo EH

    ApplyBottomLeftOrientationCandidate = False

    xDir(0) = bestX(0)
    xDir(1) = bestX(1)
    xDir(2) = bestX(2)
    NormalizeVec xDir

    Dim currentY(2) As Double
    CrossProduct faceNormal, xDir, currentY
    NormalizeVec currentY

    Dim flippedNormal As Boolean
    flippedNormal = False

    If DotProduct(currentY, bestY) < 0# Then
        FlipVec faceNormal
        flippedNormal = True
        CrossProduct faceNormal, xDir, currentY
        NormalizeVec currentY
    End If

    Debug.Print TimeStamp() & " | INFO  | " & selectionLabel & " selected"
    Debug.Print TimeStamp() & " | INFO  |   " & cornerLabel & " = (" & Dbl3ToStr(bestCorner) & ")"
    Debug.Print TimeStamp() & " | INFO  |   Bottom edge X = (" & Dbl3ToStr(xDir) & ") | len = " & FormatNumber(bestPrimaryLen, 8)
    Debug.Print TimeStamp() & " | INFO  |   Left edge Y   = (" & Dbl3ToStr(bestY) & ") | len = " & FormatNumber(bestSecondaryLen, 8)
    Debug.Print TimeStamp() & " | INFO  |   Face normal   = (" & Dbl3ToStr(faceNormal) & ") | flipped=" & CStr(flippedNormal)

    ApplyBottomLeftOrientationCandidate = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ApplyBottomLeftOrientationCandidate: " & Err.Number & " - " & Err.Description
End Function


Private Function TryGetProjectedLineIntersection(ByRef line1Point() As Double, _
                                                 ByRef line1DirUnit() As Double, _
                                                 ByRef line2Point() As Double, _
                                                 ByRef line2DirUnit() As Double, _
                                                 ByRef faceNormal() As Double, _
                                                 ByRef intersection() As Double) As Boolean
    On Error GoTo EH

    TryGetProjectedLineIntersection = False

    Dim uv As Double
    uv = DotProduct(line1DirUnit, line2DirUnit)

    Dim denom As Double
    denom = 1# - (uv * uv)

    If denom <= EPS Then Exit Function

    Dim delta(2) As Double
    delta(0) = line2Point(0) - line1Point(0)
    delta(1) = line2Point(1) - line1Point(1)
    delta(2) = line2Point(2) - line1Point(2)
    ProjectVectorOntoPlane delta, faceNormal, delta

    Dim du As Double
    Dim dv As Double
    du = DotProduct(delta, line1DirUnit)
    dv = DotProduct(delta, line2DirUnit)

    Dim t As Double
    t = (du - (uv * dv)) / denom

    intersection(0) = line1Point(0) + (line1DirUnit(0) * t)
    intersection(1) = line1Point(1) + (line1DirUnit(1) * t)
    intersection(2) = line1Point(2) + (line1DirUnit(2) * t)

    TryGetProjectedLineIntersection = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | TryGetProjectedLineIntersection: " & Err.Number & " - " & Err.Description
End Function

Private Function GetEdgeDirectionAwayFromReference(ByRef p0() As Double, _
                                                   ByRef p1() As Double, _
                                                   ByRef refPoint() As Double, _
                                                   ByRef dirOut() As Double) As Boolean
    On Error GoTo EH

    GetEdgeDirectionAwayFromReference = False

    Dim d0 As Double
    Dim d1 As Double
    d0 = Distance3(p0, refPoint)
    d1 = Distance3(p1, refPoint)

    If (d0 <= PT_TOL) And (d1 <= PT_TOL) Then Exit Function

    If d0 < d1 - PT_TOL Then
        dirOut(0) = p1(0) - p0(0)
        dirOut(1) = p1(1) - p0(1)
        dirOut(2) = p1(2) - p0(2)
    ElseIf d1 < d0 - PT_TOL Then
        dirOut(0) = p0(0) - p1(0)
        dirOut(1) = p0(1) - p1(1)
        dirOut(2) = p0(2) - p1(2)
    Else
        dirOut(0) = p1(0) - p0(0)
        dirOut(1) = p1(1) - p0(1)
        dirOut(2) = p1(2) - p0(2)
        StabilizeVectorSign dirOut
    End If

    If VecLength(dirOut) <= EPS Then Exit Function

    NormalizeVec dirOut
    GetEdgeDirectionAwayFromReference = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetEdgeDirectionAwayFromReference: " & Err.Number & " - " & Err.Description
End Function

Private Function TryGetSharedCornerFromEdgeEndpoints(ByRef a0() As Double, _
                                                     ByRef a1() As Double, _
                                                     ByRef b0() As Double, _
                                                     ByRef b1() As Double, _
                                                     ByRef corner() As Double, _
                                                     ByRef aFar() As Double, _
                                                     ByRef bFar() As Double) As Boolean
    TryGetSharedCornerFromEdgeEndpoints = False

    If PointsCoincident3(a0, b0) Then
        CopyPoint3 a0, corner
        CopyPoint3 a1, aFar
        CopyPoint3 b1, bFar
        TryGetSharedCornerFromEdgeEndpoints = True
        Exit Function
    End If

    If PointsCoincident3(a0, b1) Then
        CopyPoint3 a0, corner
        CopyPoint3 a1, aFar
        CopyPoint3 b0, bFar
        TryGetSharedCornerFromEdgeEndpoints = True
        Exit Function
    End If

    If PointsCoincident3(a1, b0) Then
        CopyPoint3 a1, corner
        CopyPoint3 a0, aFar
        CopyPoint3 b1, bFar
        TryGetSharedCornerFromEdgeEndpoints = True
        Exit Function
    End If

    If PointsCoincident3(a1, b1) Then
        CopyPoint3 a1, corner
        CopyPoint3 a0, aFar
        CopyPoint3 b0, bFar
        TryGetSharedCornerFromEdgeEndpoints = True
        Exit Function
    End If
End Function

Private Function PointsCoincident3(ByRef p1() As Double, ByRef p2() As Double) As Boolean
    PointsCoincident3 = (Distance3(p1, p2) <= PT_TOL)
End Function

Private Sub CopyPoint3(ByRef src() As Double, ByRef dst() As Double)
    dst(0) = src(0)
    dst(1) = src(1)
    dst(2) = src(2)
End Sub

Private Sub ChooseFallbackXAxis(ByRef n() As Double, ByRef x() As Double)
    Dim ref(2) As Double

    If Abs(n(2)) < 0.9 Then
        ref(0) = 0#: ref(1) = 0#: ref(2) = 1#
    Else
        ref(0) = 0#: ref(1) = 1#: ref(2) = 0#
    End If

    CrossProduct ref, n, x
    NormalizeVec x
    StabilizeVectorSign x
End Sub

Private Function BuildViewOrientationTransform(ByRef xAxis() As Double, _
                                               ByRef zAxis() As Double) As SldWorks.MathTransform
    On Error GoTo EH

    Dim x(2) As Double, y(2) As Double, z(2) As Double

    x(0) = xAxis(0): x(1) = xAxis(1): x(2) = xAxis(2)
    z(0) = zAxis(0): z(1) = zAxis(1): z(2) = zAxis(2)

    NormalizeVec x
    NormalizeVec z

    ProjectVectorOntoPlane x, z, x
    NormalizeVec x

    CrossProduct z, x, y
    NormalizeVec y

    CrossProduct y, z, x
    NormalizeVec x

    Dim data(15) As Double
    Dim i As Long
    For i = 0 To 15
        data(i) = 0#
    Next i

    ' Basis vectors as COLUMNS
    data(0) = x(0): data(1) = y(0): data(2) = z(0)
    data(3) = x(1): data(4) = y(1): data(5) = z(1)
    data(6) = x(2): data(7) = y(2): data(8) = z(2)

    data(9) = 0#
    data(10) = 0#
    data(11) = 0#
    data(12) = 1#
    data(13) = 0#
    data(14) = 0#
    data(15) = 0#

    Debug.Print TimeStamp() & " | INFO  | BuildViewOrientationTransform axes:"
    Debug.Print TimeStamp() & " | INFO  |   X = (" & Dbl3ToStr(x) & ")"
    Debug.Print TimeStamp() & " | INFO  |   Y = (" & Dbl3ToStr(y) & ")"
    Debug.Print TimeStamp() & " | INFO  |   Z = (" & Dbl3ToStr(z) & ")"

    Set BuildViewOrientationTransform = swMathUtil.CreateTransform(data)
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | BuildViewOrientationTransform: " & Err.Number & " - " & Err.Description
End Function

'=========================================================================================
' EXPORT
'=========================================================================================


Private Function ExportSingleBodyPartAsOrientedDxfFromSource(ByVal srcDoc As SldWorks.ModelDoc2, _
                                                             ByRef faceNormal() As Double, _
                                                             ByRef xDir() As Double, _
                                                             ByVal finalDxfPath As String, _
                                                             ByVal contextLabel As String, _
                                                             ByVal preserveCornerOrientation As Boolean) As Boolean
    On Error GoTo EH

    ExportSingleBodyPartAsOrientedDxfFromSource = False

    If srcDoc Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | Direct single-body source export: srcDoc is Nothing"
        Exit Function
    End If

    If srcDoc.GetType <> swDocPART Then
        Debug.Print TimeStamp() & " | FAIL  | Direct single-body source export requires PART doc, got " & DocTypeName(srcDoc.GetType)
        Exit Function
    End If

    If Len(Trim$(srcDoc.GetPathName)) = 0 Then
        Debug.Print TimeStamp() & " | FAIL  | Direct single-body source export requires saved part path"
        Exit Function
    End If

    If Not ShouldAttemptFastDirectDxfExport(preserveCornerOrientation) Then
        Debug.Print TimeStamp() & " | FAIL  | Direct single-body source export is disabled by current toggle settings"
        Exit Function
    End If

    Dim originalUnits As Long
    Dim restoreUnits As Boolean
    Dim originalViewXf As Object
    Dim alignmentData(0 To 11) As Double
    Dim varAlignment As Variant
    Dim swSrcPart As SldWorks.PartDoc

    Set swSrcPart = srcDoc
    BuildIdentityDwgAlignment alignmentData
    varAlignment = alignmentData

    Debug.Print TimeStamp() & " | INFO  | Direct single-body source export start"
    Debug.Print TimeStamp() & " | INFO  |   contextLabel = " & contextLabel
    Debug.Print TimeStamp() & " | INFO  |   sourcePath   = " & srcDoc.GetPathName
    Debug.Print TimeStamp() & " | INFO  |   finalDxfPath = " & finalDxfPath
    Debug.Print TimeStamp() & " | INFO  |   mode         = *Current view on source part"
    Debug.Print TimeStamp() & " | INFO  |   preserveCornerOrientation = " & CStr(preserveCornerOrientation)

    If Not ActivateDocumentByTitle(srcDoc.GetTitle) Then
        Debug.Print TimeStamp() & " | WARN  | Could not explicitly activate source part before direct export"
    End If

    Set originalViewXf = GetCurrentModelViewTransform(srcDoc)
    If originalViewXf Is Nothing Then
        Debug.Print TimeStamp() & " | WARN  | Could not capture original source-part view transform"
    Else
        Debug.Print TimeStamp() & " | INFO  | Captured original source-part view transform"
    End If

    originalUnits = GetModelLinearUnitsSafe(srcDoc)
    restoreUnits = (originalUnits <> -1)

    If Not OrientModelCurrentView(srcDoc, xDir, faceNormal) Then
        Debug.Print TimeStamp() & " | FAIL  | Could not orient source part current view for direct export"
        GoTo CleanupAndExit
    End If

    If Not HideAllSketchesInModel(srcDoc) Then
        Debug.Print TimeStamp() & " | WARN  | HideAllSketchesInModel returned False on source part before direct export"
    End If

    If DIRECT_TEMP_PART_FORCE_INCH_UNITS Then
        If ForceModelLinearUnitsToInches(srcDoc) Then
            Debug.Print TimeStamp() & " | INFO  | Source part linear units forced to inches for direct export"
        Else
            Debug.Print TimeStamp() & " | WARN  | Source part units could not be forced to inches before direct export"
        End If
    End If

    srcDoc.ForceRebuild3 True
    srcDoc.GraphicsRedraw2
    srcDoc.ViewZoomtofit2

    If TryDirectExportToDxfByViewName(swSrcPart, srcDoc.GetPathName, finalDxfPath, "*Current", varAlignment) Then
        Call FinalizeWaterjetDxfAfterExport(finalDxfPath, contextLabel, preserveCornerOrientation)
        ExportSingleBodyPartAsOrientedDxfFromSource = True
    Else
        Debug.Print TimeStamp() & " | FAIL  | Direct single-body source export failed using *Current view"
    End If

CleanupAndExit:
    If restoreUnits Then
        If RestoreModelLinearUnits(srcDoc, originalUnits) Then
            Debug.Print TimeStamp() & " | INFO  | Restored source part linear units after direct export"
        Else
            Debug.Print TimeStamp() & " | WARN  | Could not restore source part linear units after direct export"
        End If
    End If

    If Not originalViewXf Is Nothing Then
        If RestoreCurrentModelViewTransform(srcDoc, originalViewXf) Then
            Debug.Print TimeStamp() & " | INFO  | Restored source part original view transform after direct export"
        Else
            Debug.Print TimeStamp() & " | WARN  | Could not restore source part original view transform"
        End If
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ExportSingleBodyPartAsOrientedDxfFromSource(" & contextLabel & "): " & Err.Number & " - " & Err.Description
End Function

Private Function OrientModelCurrentView(ByVal mdl As SldWorks.ModelDoc2, _
                                        ByRef xDir() As Double, _
                                        ByRef faceNormal() As Double) As Boolean
    On Error GoTo EH

    OrientModelCurrentView = False

    If mdl Is Nothing Then Exit Function

    Dim viewXf As SldWorks.MathTransform
    Set viewXf = BuildViewOrientationTransform(xDir, faceNormal)

    If viewXf Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | BuildViewOrientationTransform returned Nothing"
        Exit Function
    End If

    Dim mvObj As Object
    Set mvObj = mdl.ActiveView

    If mvObj Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | mdl.ActiveView returned Nothing"
        Exit Function
    End If

    Debug.Print TimeStamp() & " | INFO  | Setting current model view orientation without temp-part save/reopen"
    On Error Resume Next
    CallByName mvObj, "Orientation3", VbSet, viewXf
    If Err.Number <> 0 Then
        Debug.Print TimeStamp() & " | FAIL  | Setting current view Orientation3 failed: " & Err.Number & " - " & Err.Description
        Err.Clear
        On Error GoTo EH
        Exit Function
    End If
    On Error GoTo EH

    mdl.GraphicsRedraw2
    mdl.ViewZoomtofit2
    OrientModelCurrentView = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | OrientModelCurrentView: " & Err.Number & " - " & Err.Description
End Function

Private Function GetCurrentModelViewTransform(ByVal mdl As SldWorks.ModelDoc2) As Object
    On Error GoTo EH

    Set GetCurrentModelViewTransform = Nothing

    If mdl Is Nothing Then Exit Function

    Dim mvObj As Object
    Dim xfObj As Object

    Set mvObj = mdl.ActiveView
    If mvObj Is Nothing Then
        Debug.Print TimeStamp() & " | WARN  | GetCurrentModelViewTransform: ActiveView is Nothing"
        Exit Function
    End If

    On Error Resume Next
    Set xfObj = CallByName(mvObj, "Orientation3", VbGet)
    If Err.Number <> 0 Then
        Debug.Print TimeStamp() & " | WARN  | GetCurrentModelViewTransform failed: " & Err.Number & " - " & Err.Description
        Err.Clear
        On Error GoTo EH
        Exit Function
    End If
    On Error GoTo EH

    Set GetCurrentModelViewTransform = xfObj
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetCurrentModelViewTransform: " & Err.Number & " - " & Err.Description
End Function

Private Function RestoreCurrentModelViewTransform(ByVal mdl As SldWorks.ModelDoc2, ByVal xfObj As Object) As Boolean
    On Error GoTo EH

    RestoreCurrentModelViewTransform = False

    If mdl Is Nothing Then Exit Function
    If xfObj Is Nothing Then Exit Function

    Dim mvObj As Object
    Set mvObj = mdl.ActiveView

    If mvObj Is Nothing Then
        Debug.Print TimeStamp() & " | WARN  | RestoreCurrentModelViewTransform: ActiveView is Nothing"
        Exit Function
    End If

    On Error Resume Next
    CallByName mvObj, "Orientation3", VbSet, xfObj
    If Err.Number <> 0 Then
        Debug.Print TimeStamp() & " | WARN  | RestoreCurrentModelViewTransform failed: " & Err.Number & " - " & Err.Description
        Err.Clear
        On Error GoTo EH
        Exit Function
    End If
    On Error GoTo EH

    mdl.GraphicsRedraw2
    mdl.ViewZoomtofit2
    RestoreCurrentModelViewTransform = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | RestoreCurrentModelViewTransform: " & Err.Number & " - " & Err.Description
End Function

Private Function GetModelLinearUnitsSafe(ByVal mdl As SldWorks.ModelDoc2) As Long
    On Error GoTo EH

    GetModelLinearUnitsSafe = -1

    If mdl Is Nothing Then Exit Function

    On Error Resume Next
    GetModelLinearUnitsSafe = mdl.GetUserPreferenceIntegerValue(swUnitsLinear)
    If Err.Number <> 0 Then
        Debug.Print TimeStamp() & " | WARN  | GetModelLinearUnitsSafe failed: " & Err.Number & " - " & Err.Description
        Err.Clear
        GetModelLinearUnitsSafe = -1
    End If
    On Error GoTo EH

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetModelLinearUnitsSafe: " & Err.Number & " - " & Err.Description
    GetModelLinearUnitsSafe = -1
End Function

Private Function RestoreModelLinearUnits(ByVal mdl As SldWorks.ModelDoc2, ByVal targetUnits As Long) As Boolean
    On Error GoTo EH

    RestoreModelLinearUnits = False

    If mdl Is Nothing Then Exit Function
    If targetUnits < 0 Then Exit Function

    mdl.SetUserPreferenceIntegerValue swUnitsLinear, targetUnits
    RestoreModelLinearUnits = (GetModelLinearUnitsSafe(mdl) = targetUnits)
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | RestoreModelLinearUnits: " & Err.Number & " - " & Err.Description
End Function

Private Function ExportBodyAsOrientedDxf(ByVal srcBody As SldWorks.Body2, _
                                         ByRef faceNormal() As Double, _
                                         ByRef xDir() As Double, _
                                         ByVal finalDxfPath As String, _
                                         ByVal cutListName As String, _
                                         ByVal preserveCornerOrientation As Boolean) As Boolean
    On Error GoTo EH

    ExportBodyAsOrientedDxf = False

    Dim tempRoot As String
    tempRoot = GetLocalTempRoot()

    If Len(tempRoot) = 0 Then
        Debug.Print TimeStamp() & " | FAIL  | Could not create local temp root"
        Exit Function
    End If

    Debug.Print TimeStamp() & " | INFO  | Local temp workspace = " & tempRoot
    Debug.Print TimeStamp() & " | INFO  | DXF export mode = " & GetDxfExportModeName()

    Dim tempPartPath As String
    tempPartPath = tempRoot & "\body_temp.sldprt"

    Dim tempPartDoc As SldWorks.ModelDoc2
    Dim tempBody As SldWorks.Body2

    Set tempBody = srcBody.Copy
    If tempBody Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | Body copy returned Nothing"
        GoTo CleanupAndExit
    End If

    Set tempPartDoc = CreateTempPartFromBody(tempBody, tempPartPath, Not (USE_FAST_MODE And FAST_MODE_SINGLE_TEMP_PART_SAVE))
    If tempPartDoc Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | Temp part creation failed"
        GoTo CleanupAndExit
    End If

    If Not OrientAndNameTempPartView(tempPartDoc, xDir, faceNormal, TEMP_VIEW_NAME) Then
        Debug.Print TimeStamp() & " | FAIL  | Could not orient/name temp part view"
        GoTo CleanupAndExit
    End If

    If Not HideAllSketchesInModel(tempPartDoc) Then
        Debug.Print TimeStamp() & " | WARN  | HideAllSketchesInModel returned False after view orientation"
    End If

    Debug.Print TimeStamp() & " | INFO  | Saving temp part after custom named view creation"
    If Not TrySaveModelToPath(tempPartDoc, tempPartPath) Then
        Debug.Print TimeStamp() & " | FAIL  | Could not persist custom named view to temp part file"
        GoTo CleanupAndExit
    End If

    If Not ShouldAttemptFastDirectDxfExport(preserveCornerOrientation) Then
        Debug.Print TimeStamp() & " | FAIL  | Direct part DXF export is disabled by current toggle settings"
        GoTo CleanupAndExit
    End If

    Set tempPartDoc = ReopenTempPartForDirectExport(tempPartDoc, tempPartPath)
    If tempPartDoc Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | Could not reopen temp part for direct export"
        GoTo CleanupAndExit
    End If

    If Not HideAllSketchesInModel(tempPartDoc) Then
        Debug.Print TimeStamp() & " | WARN  | HideAllSketchesInModel returned False after temp-part reopen"
    End If

    Debug.Print TimeStamp() & " | INFO  | Trying direct part DXF export by named annotation view"
    If ExportTempPartToDxf_DirectByAnnotationView(tempPartDoc, tempPartPath, finalDxfPath, TEMP_VIEW_NAME, preserveCornerOrientation) Then
        Call FinalizeWaterjetDxfAfterExport(finalDxfPath, cutListName, preserveCornerOrientation)
        ExportBodyAsOrientedDxf = True
        GoTo CleanupAndExit
    End If

    If EXPERIMENTAL_DIRECT_FALLBACK_TO_DRAWING Then
        Debug.Print TimeStamp() & " | WARN  | Direct part DXF export failed; manual drawing fallback is enabled"
        Debug.Print TimeStamp() & " | WARN  | This macro revision keeps the legacy drawing helper code, but the active production path is direct part export"
    Else
        Debug.Print TimeStamp() & " | FAIL  | Direct part DXF export failed and drawing fallback is disabled"
    End If

CleanupAndExit:
    CloseModelDocSafe tempPartDoc
    DeleteFileIfExists tempPartPath
    DeleteFolderIfEmpty tempRoot
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ExportBodyAsOrientedDxf(" & cutListName & "): " & Err.Number & " - " & Err.Description
End Function


'=========================================================================================
' Imported SAVE_ALL DXF post-export orientation normalization
'=========================================================================================

Private Sub FinalizeWaterjetDxfAfterExport(ByVal dxfPath As String, _
                                           ByVal contextLabel As String, _
                                           ByVal preserveCornerOrientation As Boolean)
    On Error GoTo EH

    If Not POSTPROCESS_DXF_ORIENTATION_TO_HORIZONTAL Then
        LogEvent " | INFO  | DXF post-process orientation normalization disabled"
        Exit Sub
    End If

    If Len(Trim$(dxfPath)) = 0 Then
        LogEvent " | WARN  | DXF post-process skipped: output path is blank"
        Exit Sub
    End If

    If Not FileExists(dxfPath) Then
        LogEvent " | WARN  | DXF post-process skipped: file does not exist => " & dxfPath
        Exit Sub
    End If

    LogEvent " | CHECK | R10 DXF post-process orientation start | context=" & contextLabel & _
             " | preserveCornerOrientation=" & CStr(preserveCornerOrientation)

    If NormalizeDxfForHorizontalNesting(dxfPath, contextLabel) Then
        LogEvent " | OK    | R10 DXF post-process orientation completed => " & dxfPath
    Else
        LogEvent " | WARN  | R10 DXF post-process orientation could not normalize this file. Keeping SolidWorks DXF as exported => " & dxfPath
    End If

    Exit Sub

EH:
    LogEvent " | WARN  | FinalizeWaterjetDxfAfterExport(" & contextLabel & "): " & Err.Number & " - " & Err.Description
End Sub

Private Function NormalizeDxfForHorizontalNesting(ByVal dxfPath As String, _
                                                  ByVal contextLabel As String) As Boolean
    On Error GoTo EH

    NormalizeDxfForHorizontalNesting = False

    Dim lines() As String
    Dim lineCount As Long

    If Not ReadTextFileLinesANSI(dxfPath, lines, lineCount) Then
        LogEvent " | WARN  | DXF normalize: could not read file => " & dxfPath
        Exit Function
    End If

    If lineCount < 4 Then
        LogEvent " | WARN  | DXF normalize: file has too few lines => " & dxfPath
        Exit Function
    End If

    Dim entStartIndex As Long
    Dim entEndIndex As Long

    If Not FindDxfEntitiesRange(lines, lineCount, entStartIndex, entEndIndex) Then
        LogEvent " | WARN  | DXF normalize: ENTITIES section not found. File left unchanged | context=" & contextLabel
        Exit Function
    End If

    LogEvent " | INFO  | DXF normalize ENTITIES range | startLineIndex=" & CStr(entStartIndex) & _
             " | endLineIndex=" & CStr(entEndIndex)

    Dim rotationRad As Double
    Dim selectedLen As Double
    Dim secondaryLen As Double
    Dim segmentCount As Long
    Dim selectionMode As String
    Dim usedRightAnglePair As Boolean

    If Not FindProductionDxfNestingRotation(lines, lineCount, entStartIndex, entEndIndex, _
                                            rotationRad, selectedLen, secondaryLen, segmentCount, _
                                            selectionMode, usedRightAnglePair) Then
        LogEvent " | WARN  | DXF normalize: no usable linear segments found | context=" & contextLabel
        Exit Function
    End If

    LogEvent " | INFO  | DXF normalize selected orientation | context=" & contextLabel & _
             " | mode=" & selectionMode & _
             " | segments=" & CStr(segmentCount) & _
             " | primaryLen=" & FormatDxfLogNumber(selectedLen) & _
             " | secondaryLen=" & FormatDxfLogNumber(secondaryLen) & _
             " | rotationDeg=" & FormatDxfLogNumber(RadToDeg(rotationRad)) & _
             " | rightAnglePair=" & CStr(usedRightAnglePair)

    Dim minX As Double, minY As Double, maxX As Double, maxY As Double
    Dim pointCount As Long

    If Not GetRotatedDxfPointBounds(lines, lineCount, entStartIndex, entEndIndex, rotationRad, minX, minY, maxX, maxY, pointCount) Then
        LogEvent " | WARN  | DXF normalize: could not calculate rotated bounds | context=" & contextLabel
        Exit Function
    End If

    LogEvent " | INFO  | DXF normalize bounds after production rotation | W=" & FormatDxfLogNumber(maxX - minX) & _
             " | H=" & FormatDxfLogNumber(maxY - minY) & _
             " | points=" & CStr(pointCount)

    If DXF_POSTPROCESS_FORCE_WIDE_ENVELOPE Then
        If (Not DXF_POSTPROCESS_FORCE_WIDE_ONLY_FOR_FALLBACK) Or (Not usedRightAnglePair) Then
            If (maxY - minY) > (maxX - minX) + EPS Then
                rotationRad = rotationRad + (PI_VAL / 2#)

                If Not GetRotatedDxfPointBounds(lines, lineCount, entStartIndex, entEndIndex, rotationRad, minX, minY, maxX, maxY, pointCount) Then
                    LogEvent " | WARN  | DXF normalize: could not calculate bounds after secondary 90-degree correction"
                    Exit Function
                End If

                LogEvent " | INFO  | DXF normalize applied secondary +90 deg correction for fallback wide nesting envelope"
                LogEvent " | INFO  | DXF normalize bounds after secondary correction | W=" & FormatDxfLogNumber(maxX - minX) & _
                         " | H=" & FormatDxfLogNumber(maxY - minY)
            End If
        Else
            LogEvent " | INFO  | DXF normalize skipped automatic wide-envelope correction because right-angle bottom-leg orientation was selected"
        End If
    End If

    Dim offsetX As Double
    Dim offsetY As Double
    offsetX = 0#
    offsetY = 0#

    If DXF_POSTPROCESS_TRANSLATE_TO_POSITIVE_XY Then
        offsetX = -minX
        offsetY = -minY
        LogEvent " | INFO  | DXF normalize translate to positive XY | offsetX=" & FormatDxfLogNumber(offsetX) & _
                 " | offsetY=" & FormatDxfLogNumber(offsetY)
    End If

    If DXF_POSTPROCESS_KEEP_BACKUP_FILE Then
        CopyFileIfExists dxfPath, dxfPath & ".pre_R10_orientation_backup"
    End If

    If Not ApplyDxf2DRotationToLines(lines, lineCount, entStartIndex, entEndIndex, rotationRad, offsetX, offsetY) Then
        LogEvent " | WARN  | DXF normalize: coordinate rewrite failed | context=" & contextLabel
        Exit Function
    End If

    If Not WriteTextFileLinesANSI(dxfPath, lines, lineCount) Then
        LogEvent " | WARN  | DXF normalize: failed to write normalized DXF => " & dxfPath
        Exit Function
    End If

    NormalizeDxfForHorizontalNesting = True
    Exit Function

EH:
    LogEvent " | WARN  | NormalizeDxfForHorizontalNesting(" & contextLabel & "): " & Err.Number & " - " & Err.Description
End Function

Private Function FindProductionDxfNestingRotation(ByRef lines() As String, _
                                                  ByVal lineCount As Long, _
                                                  ByVal entStartIndex As Long, _
                                                  ByVal entEndIndex As Long, _
                                                  ByRef rotationRad As Double, _
                                                  ByRef selectedLen As Double, _
                                                  ByRef secondaryLen As Double, _
                                                  ByRef segmentCount As Long, _
                                                  ByRef selectionMode As String, _
                                                  ByRef usedRightAnglePair As Boolean) As Boolean
    On Error GoTo EH

    FindProductionDxfNestingRotation = False
    rotationRad = 0#
    selectedLen = 0#
    secondaryLen = 0#
    segmentCount = 0
    selectionMode = ""
    usedRightAnglePair = False

    Dim sx0() As Double
    Dim sy0() As Double
    Dim sx1() As Double
    Dim sy1() As Double
    Dim slen() As Double

    If Not CollectDxfLinearSegments(lines, lineCount, entStartIndex, entEndIndex, sx0, sy0, sx1, sy1, slen, segmentCount) Then
        LogEvent " | WARN  | Production DXF rotation: no linear segments collected"
        Exit Function
    End If

    LogEvent " | INFO  | Production DXF rotation: linear segment count = " & CStr(segmentCount)

    If DXF_POSTPROCESS_PREFER_RIGHT_ANGLE_LEG_PAIR Then
        If SelectDxfRightAngleBottomLegRotation(sx0, sy0, sx1, sy1, slen, segmentCount, _
                                                rotationRad, selectedLen, secondaryLen) Then
            selectionMode = "RIGHT_ANGLE_LEG_PAIR_BOTTOM_EDGE"
            usedRightAnglePair = True
            FindProductionDxfNestingRotation = True
            Exit Function
        End If

        LogEvent " | INFO  | Production DXF rotation: no qualifying right-angle leg pair found; falling back to dominant edge"
    End If

    If SelectDxfDominantBottomEdgeRotation(sx0, sy0, sx1, sy1, slen, segmentCount, _
                                           rotationRad, selectedLen, secondaryLen) Then
        selectionMode = "DOMINANT_EDGE_BOTTOM_FALLBACK"
        usedRightAnglePair = False
        FindProductionDxfNestingRotation = True
        Exit Function
    End If

    Exit Function

EH:
    LogEvent " | WARN  | FindProductionDxfNestingRotation: " & Err.Number & " - " & Err.Description
End Function

Private Function CollectDxfLinearSegments(ByRef lines() As String, _
                                          ByVal lineCount As Long, _
                                          ByVal entStartIndex As Long, _
                                          ByVal entEndIndex As Long, _
                                          ByRef sx0() As Double, _
                                          ByRef sy0() As Double, _
                                          ByRef sx1() As Double, _
                                          ByRef sy1() As Double, _
                                          ByRef slen() As Double, _
                                          ByRef segmentCount As Long) As Boolean
    On Error GoTo EH

    CollectDxfLinearSegments = False
    segmentCount = 0

    Dim currentEntity As String
    Dim inOldPolyline As Boolean
    Dim oldPolylineClosed As Boolean

    Dim lineHaveStart As Boolean
    Dim lineHaveEnd As Boolean
    Dim lineX0 As Double, lineY0 As Double
    Dim lineX1 As Double, lineY1 As Double

    Dim polyX() As Double
    Dim polyY() As Double
    Dim polyCount As Long
    Dim polyClosed As Boolean

    Dim oldPolyX() As Double
    Dim oldPolyY() As Double
    Dim oldPolyCount As Long

    Dim i As Long
    Dim codeNum As Long
    Dim valText As String

    currentEntity = ""
    inOldPolyline = False
    oldPolylineClosed = False
    polyCount = 0
    oldPolyCount = 0

    For i = entStartIndex To entEndIndex Step 2
        codeNum = DxfGroupCodeToLong(lines(i))
        valText = Trim$(lines(i + 1))

        If codeNum = 0 Then
            AddPendingDxfEntitySegments currentEntity, _
                                        lineHaveStart, lineHaveEnd, lineX0, lineY0, lineX1, lineY1, _
                                        polyX, polyY, polyCount, polyClosed, _
                                        sx0, sy0, sx1, sy1, slen, segmentCount

            currentEntity = UCase$(valText)

            lineHaveStart = False
            lineHaveEnd = False
            polyCount = 0
            polyClosed = False

            If currentEntity = "POLYLINE" Then
                inOldPolyline = True
                oldPolylineClosed = False
                oldPolyCount = 0
            ElseIf currentEntity = "SEQEND" Then
                If inOldPolyline Then
                    AddDxfPolylineSegmentsToArrays oldPolyX, oldPolyY, oldPolyCount, oldPolylineClosed, _
                                                   sx0, sy0, sx1, sy1, slen, segmentCount
                    inOldPolyline = False
                    oldPolylineClosed = False
                    oldPolyCount = 0
                End If
            End If

        Else
            Select Case currentEntity
                Case "LINE"
                    If codeNum = 10 Then
                        If TryReadDxfXYAt(lines, lineCount, i, 10, lineX0, lineY0) Then lineHaveStart = True
                    ElseIf codeNum = 11 Then
                        If TryReadDxfXYAt(lines, lineCount, i, 11, lineX1, lineY1) Then lineHaveEnd = True
                    End If

                Case "LWPOLYLINE"
                    If codeNum = 10 Then
                        Dim px As Double, py As Double
                        If TryReadDxfXYAt(lines, lineCount, i, 10, px, py) Then
                            AddDxf2DPoint polyX, polyY, polyCount, px, py
                        End If
                    ElseIf codeNum = 70 Then
                        polyClosed = ((CLng(Val(valText)) And 1) <> 0)
                    End If

                Case "POLYLINE"
                    If codeNum = 70 Then
                        oldPolylineClosed = ((CLng(Val(valText)) And 1) <> 0)
                    End If

                Case "VERTEX"
                    If inOldPolyline Then
                        If codeNum = 10 Then
                            Dim vx As Double, vy As Double
                            If TryReadDxfXYAt(lines, lineCount, i, 10, vx, vy) Then
                                AddDxf2DPoint oldPolyX, oldPolyY, oldPolyCount, vx, vy
                            End If
                        End If
                    End If
            End Select
        End If
    Next i

    AddPendingDxfEntitySegments currentEntity, _
                                lineHaveStart, lineHaveEnd, lineX0, lineY0, lineX1, lineY1, _
                                polyX, polyY, polyCount, polyClosed, _
                                sx0, sy0, sx1, sy1, slen, segmentCount

    If inOldPolyline Then
        AddDxfPolylineSegmentsToArrays oldPolyX, oldPolyY, oldPolyCount, oldPolylineClosed, _
                                       sx0, sy0, sx1, sy1, slen, segmentCount
    End If

    CollectDxfLinearSegments = (segmentCount > 0)
    Exit Function

EH:
    LogEvent " | WARN  | CollectDxfLinearSegments: " & Err.Number & " - " & Err.Description
End Function

Private Sub AddPendingDxfEntitySegments(ByVal entityName As String, _
                                        ByVal lineHaveStart As Boolean, _
                                        ByVal lineHaveEnd As Boolean, _
                                        ByVal lineX0 As Double, _
                                        ByVal lineY0 As Double, _
                                        ByVal lineX1 As Double, _
                                        ByVal lineY1 As Double, _
                                        ByRef polyX() As Double, _
                                        ByRef polyY() As Double, _
                                        ByVal polyCount As Long, _
                                        ByVal polyClosed As Boolean, _
                                        ByRef sx0() As Double, _
                                        ByRef sy0() As Double, _
                                        ByRef sx1() As Double, _
                                        ByRef sy1() As Double, _
                                        ByRef slen() As Double, _
                                        ByRef segmentCount As Long)
    On Error GoTo EH

    Select Case UCase$(entityName)
        Case "LINE"
            If lineHaveStart And lineHaveEnd Then
                AddDxfLinearSegmentToArrays lineX0, lineY0, lineX1, lineY1, sx0, sy0, sx1, sy1, slen, segmentCount
            End If

        Case "LWPOLYLINE"
            AddDxfPolylineSegmentsToArrays polyX, polyY, polyCount, polyClosed, sx0, sy0, sx1, sy1, slen, segmentCount
    End Select

    Exit Sub

EH:
    LogEvent " | WARN  | AddPendingDxfEntitySegments(" & entityName & "): " & Err.Number & " - " & Err.Description
End Sub

Private Sub AddDxfPolylineSegmentsToArrays(ByRef px() As Double, _
                                           ByRef py() As Double, _
                                           ByVal ptCount As Long, _
                                           ByVal isClosed As Boolean, _
                                           ByRef sx0() As Double, _
                                           ByRef sy0() As Double, _
                                           ByRef sx1() As Double, _
                                           ByRef sy1() As Double, _
                                           ByRef slen() As Double, _
                                           ByRef segmentCount As Long)
    On Error GoTo EH

    If ptCount < 2 Then Exit Sub

    Dim i As Long
    For i = 0 To ptCount - 2
        AddDxfLinearSegmentToArrays px(i), py(i), px(i + 1), py(i + 1), sx0, sy0, sx1, sy1, slen, segmentCount
    Next i

    If isClosed And ptCount > 2 Then
        AddDxfLinearSegmentToArrays px(ptCount - 1), py(ptCount - 1), px(0), py(0), sx0, sy0, sx1, sy1, slen, segmentCount
    End If

    Exit Sub

EH:
    LogEvent " | WARN  | AddDxfPolylineSegmentsToArrays: " & Err.Number & " - " & Err.Description
End Sub

Private Sub AddDxfLinearSegmentToArrays(ByVal x0 As Double, _
                                        ByVal y0 As Double, _
                                        ByVal x1 As Double, _
                                        ByVal y1 As Double, _
                                        ByRef sx0() As Double, _
                                        ByRef sy0() As Double, _
                                        ByRef sx1() As Double, _
                                        ByRef sy1() As Double, _
                                        ByRef slen() As Double, _
                                        ByRef segmentCount As Long)
    On Error GoTo EH

    Dim dx As Double
    Dim dy As Double
    Dim L As Double

    dx = x1 - x0
    dy = y1 - y0
    L = Sqr(dx * dx + dy * dy)

    If L < DXF_POSTPROCESS_MIN_SEGMENT_LENGTH Then Exit Sub

    If segmentCount = 0 Then
        ReDim sx0(0 To 0)
        ReDim sy0(0 To 0)
        ReDim sx1(0 To 0)
        ReDim sy1(0 To 0)
        ReDim slen(0 To 0)
    Else
        ReDim Preserve sx0(0 To segmentCount)
        ReDim Preserve sy0(0 To segmentCount)
        ReDim Preserve sx1(0 To segmentCount)
        ReDim Preserve sy1(0 To segmentCount)
        ReDim Preserve slen(0 To segmentCount)
    End If

    sx0(segmentCount) = x0
    sy0(segmentCount) = y0
    sx1(segmentCount) = x1
    sy1(segmentCount) = y1
    slen(segmentCount) = L

    segmentCount = segmentCount + 1
    Exit Sub

EH:
    LogEvent " | WARN  | AddDxfLinearSegmentToArrays: " & Err.Number & " - " & Err.Description
End Sub

Private Function SelectDxfRightAngleBottomLegRotation(ByRef sx0() As Double, _
                                                      ByRef sy0() As Double, _
                                                      ByRef sx1() As Double, _
                                                      ByRef sy1() As Double, _
                                                      ByRef slen() As Double, _
                                                      ByVal segmentCount As Long, _
                                                      ByRef bestRotationRad As Double, _
                                                      ByRef bestPrimaryLen As Double, _
                                                      ByRef bestSecondaryLen As Double) As Boolean
    On Error GoTo EH

    SelectDxfRightAngleBottomLegRotation = False

    Dim bestBottomPenalty As Double
    Dim bestArea As Double
    bestBottomPenalty = 1E+30
    bestPrimaryLen = -1#
    bestSecondaryLen = -1#
    bestArea = -1#

    Dim i As Long
    Dim j As Long

    For i = 0 To segmentCount - 2
        For j = i + 1 To segmentCount - 1
            Dim cornerX As Double, cornerY As Double
            Dim iFarX As Double, iFarY As Double
            Dim jFarX As Double, jFarY As Double

            If TryGetSharedDxfSegmentCorner(sx0(i), sy0(i), sx1(i), sy1(i), _
                                            sx0(j), sy0(j), sx1(j), sy1(j), _
                                            cornerX, cornerY, iFarX, iFarY, jFarX, jFarY) Then

                Dim ix As Double, iy As Double
                Dim jx As Double, jy As Double
                Dim iLen As Double, jLen As Double

                ix = iFarX - cornerX
                iy = iFarY - cornerY
                jx = jFarX - cornerX
                jy = jFarY - cornerY

                iLen = Sqr(ix * ix + iy * iy)
                jLen = Sqr(jx * jx + jy * jy)

                If iLen >= DXF_POSTPROCESS_MIN_SEGMENT_LENGTH And jLen >= DXF_POSTPROCESS_MIN_SEGMENT_LENGTH Then
                    ix = ix / iLen
                    iy = iy / iLen
                    jx = jx / jLen
                    jy = jy / jLen

                    Dim dotAbs As Double
                    dotAbs = Abs((ix * jx) + (iy * jy))

                    If dotAbs <= DXF_POSTPROCESS_PERP_DOT_TOL Then
                        Dim xVecX As Double, xVecY As Double
                        Dim yVecX As Double, yVecY As Double
                        Dim primaryLen As Double
                        Dim secondaryLen As Double

                        If DXF_POSTPROCESS_PREFER_LONGER_RIGHT_ANGLE_LEG_HORIZONTAL Then
                            If iLen >= jLen Then
                                xVecX = ix: xVecY = iy
                                yVecX = jx: yVecY = jy
                                primaryLen = iLen
                                secondaryLen = jLen
                            Else
                                xVecX = jx: xVecY = jy
                                yVecX = ix: yVecY = iy
                                primaryLen = jLen
                                secondaryLen = iLen
                            End If
                        Else
                            xVecX = ix: xVecY = iy
                            yVecX = jx: yVecY = jy
                            primaryLen = iLen
                            secondaryLen = jLen
                        End If

                        Dim rotationRad As Double
                        rotationRad = -Atn2(xVecY, xVecX)

                        Dim c As Double, s As Double
                        Dim yRotX As Double, yRotY As Double
                        c = Cos(rotationRad)
                        s = Sin(rotationRad)
                        RotatePoint2D yVecX, yVecY, c, s, yRotX, yRotY

                        'If the adjacent/opposite leg points downward after rotation,
                        'rotate 180 degrees. The selected edge remains horizontal,
                        'but the right-angle corner becomes the lower corner.
                        If yRotY < -EPS Then
                            rotationRad = rotationRad + PI_VAL
                        End If

                        Dim minX As Double, minY As Double, maxX As Double, maxY As Double
                        Dim pointCount As Long
                        If GetDxfSegmentEndpointBoundsAfterRotation(sx0, sy0, sx1, sy1, segmentCount, rotationRad, minX, minY, maxX, maxY, pointCount) Then
                            Dim edgeRX As Double, edgeRY As Double
                            c = Cos(rotationRad)
                            s = Sin(rotationRad)
                            RotatePoint2D cornerX, cornerY, c, s, edgeRX, edgeRY

                            Dim bottomPenalty As Double
                            bottomPenalty = Abs(edgeRY - minY)

                            Dim area As Double
                            area = primaryLen * secondaryLen

                            If IsDxfRightAngleCandidateBetter(bottomPenalty, primaryLen, secondaryLen, area, _
                                                              bestBottomPenalty, bestPrimaryLen, bestSecondaryLen, bestArea) Then
                                bestBottomPenalty = bottomPenalty
                                bestPrimaryLen = primaryLen
                                bestSecondaryLen = secondaryLen
                                bestArea = area
                                bestRotationRad = rotationRad
                                SelectDxfRightAngleBottomLegRotation = True

                                LogEvent " | INFO  | DXF right-angle candidate accepted | pair=" & CStr(i) & "/" & CStr(j) & _
                                         " | primary=" & FormatDxfLogNumber(primaryLen) & _
                                         " | secondary=" & FormatDxfLogNumber(secondaryLen) & _
                                         " | bottomPenalty=" & FormatDxfLogNumber(bottomPenalty) & _
                                         " | rotationDeg=" & FormatDxfLogNumber(RadToDeg(rotationRad))
                            End If
                        End If
                    End If
                End If
            End If
        Next j
    Next i

    If SelectDxfRightAngleBottomLegRotation Then
        LogEvent " | INFO  | DXF right-angle bottom-leg orientation selected | primary=" & FormatDxfLogNumber(bestPrimaryLen) & _
                 " | secondary=" & FormatDxfLogNumber(bestSecondaryLen) & _
                 " | bottomPenalty=" & FormatDxfLogNumber(bestBottomPenalty)
    End If

    Exit Function

EH:
    LogEvent " | WARN  | SelectDxfRightAngleBottomLegRotation: " & Err.Number & " - " & Err.Description
End Function

Private Function IsDxfRightAngleCandidateBetter(ByVal candBottomPenalty As Double, _
                                                ByVal candPrimaryLen As Double, _
                                                ByVal candSecondaryLen As Double, _
                                                ByVal candArea As Double, _
                                                ByVal bestBottomPenalty As Double, _
                                                ByVal bestPrimaryLen As Double, _
                                                ByVal bestSecondaryLen As Double, _
                                                ByVal bestArea As Double) As Boolean
    IsDxfRightAngleCandidateBetter = False

    'First priority: selected leg should be on the bottom, not on the top.
    If candBottomPenalty < bestBottomPenalty - DXF_POSTPROCESS_BOTTOM_EDGE_TOL Then
        IsDxfRightAngleCandidateBetter = True
        Exit Function
    End If

    If Abs(candBottomPenalty - bestBottomPenalty) <= DXF_POSTPROCESS_BOTTOM_EDGE_TOL Then
        'Then prefer a stronger real corner: larger shorter leg first, then area, then primary length.
        If candSecondaryLen > bestSecondaryLen + EPS Then
            IsDxfRightAngleCandidateBetter = True
            Exit Function
        End If

        If Abs(candSecondaryLen - bestSecondaryLen) <= EPS Then
            If candArea > bestArea + EPS Then
                IsDxfRightAngleCandidateBetter = True
                Exit Function
            End If

            If Abs(candArea - bestArea) <= EPS Then
                If candPrimaryLen > bestPrimaryLen + EPS Then
                    IsDxfRightAngleCandidateBetter = True
                    Exit Function
                End If
            End If
        End If
    End If
End Function

Private Function SelectDxfDominantBottomEdgeRotation(ByRef sx0() As Double, _
                                                     ByRef sy0() As Double, _
                                                     ByRef sx1() As Double, _
                                                     ByRef sy1() As Double, _
                                                     ByRef slen() As Double, _
                                                     ByVal segmentCount As Long, _
                                                     ByRef bestRotationRad As Double, _
                                                     ByRef bestLen As Double, _
                                                     ByRef secondaryLen As Double) As Boolean
    On Error GoTo EH

    SelectDxfDominantBottomEdgeRotation = False
    bestLen = -1#
    secondaryLen = 0#

    Dim i As Long
    Dim bestIndex As Long
    bestIndex = -1

    For i = 0 To segmentCount - 1
        If slen(i) > bestLen + EPS Then
            bestLen = slen(i)
            bestIndex = i
        ElseIf Abs(slen(i) - bestLen) <= EPS Then
            Dim candAngle As Double
            Dim bestAngle As Double
            candAngle = NormalizeAngleToHalfPi(Atn2(sy1(i) - sy0(i), sx1(i) - sx0(i)))
            bestAngle = NormalizeAngleToHalfPi(Atn2(sy1(bestIndex) - sy0(bestIndex), sx1(bestIndex) - sx0(bestIndex)))
            If Abs(candAngle) < Abs(bestAngle) - EPS Then bestIndex = i
        End If
    Next i

    If bestIndex < 0 Then Exit Function

    Dim angleRad As Double
    angleRad = Atn2(sy1(bestIndex) - sy0(bestIndex), sx1(bestIndex) - sx0(bestIndex))
    bestRotationRad = -NormalizeAngleToHalfPi(angleRad)

    Dim minX As Double, minY As Double, maxX As Double, maxY As Double
    Dim pointCount As Long

    If GetDxfSegmentEndpointBoundsAfterRotation(sx0, sy0, sx1, sy1, segmentCount, bestRotationRad, minX, minY, maxX, maxY, pointCount) Then
        Dim c As Double, s As Double
        Dim r0x As Double, r0y As Double
        Dim r1x As Double, r1y As Double
        c = Cos(bestRotationRad)
        s = Sin(bestRotationRad)

        RotatePoint2D sx0(bestIndex), sy0(bestIndex), c, s, r0x, r0y
        RotatePoint2D sx1(bestIndex), sy1(bestIndex), c, s, r1x, r1y

        Dim edgeY As Double
        edgeY = (r0y + r1y) / 2#

        'If the selected dominant edge is closer to the top than the bottom,
        'rotate 180 degrees so the same edge becomes the bottom nesting edge.
        If Abs(edgeY - maxY) < Abs(edgeY - minY) Then
            bestRotationRad = bestRotationRad + PI_VAL
            LogEvent " | INFO  | DXF dominant fallback rotated 180 degrees to place longest edge on bottom"
        End If
    End If

    SelectDxfDominantBottomEdgeRotation = True
    Exit Function

EH:
    LogEvent " | WARN  | SelectDxfDominantBottomEdgeRotation: " & Err.Number & " - " & Err.Description
End Function

Private Function TryGetSharedDxfSegmentCorner(ByVal a0x As Double, _
                                              ByVal a0y As Double, _
                                              ByVal a1x As Double, _
                                              ByVal a1y As Double, _
                                              ByVal b0x As Double, _
                                              ByVal b0y As Double, _
                                              ByVal b1x As Double, _
                                              ByVal b1y As Double, _
                                              ByRef cornerX As Double, _
                                              ByRef cornerY As Double, _
                                              ByRef aFarX As Double, _
                                              ByRef aFarY As Double, _
                                              ByRef bFarX As Double, _
                                              ByRef bFarY As Double) As Boolean
    TryGetSharedDxfSegmentCorner = False

    If DxfPointsCoincident2(a0x, a0y, b0x, b0y) Then
        cornerX = a0x: cornerY = a0y
        aFarX = a1x: aFarY = a1y
        bFarX = b1x: bFarY = b1y
        TryGetSharedDxfSegmentCorner = True
        Exit Function
    End If

    If DxfPointsCoincident2(a0x, a0y, b1x, b1y) Then
        cornerX = a0x: cornerY = a0y
        aFarX = a1x: aFarY = a1y
        bFarX = b0x: bFarY = b0y
        TryGetSharedDxfSegmentCorner = True
        Exit Function
    End If

    If DxfPointsCoincident2(a1x, a1y, b0x, b0y) Then
        cornerX = a1x: cornerY = a1y
        aFarX = a0x: aFarY = a0y
        bFarX = b1x: bFarY = b1y
        TryGetSharedDxfSegmentCorner = True
        Exit Function
    End If

    If DxfPointsCoincident2(a1x, a1y, b1x, b1y) Then
        cornerX = a1x: cornerY = a1y
        aFarX = a0x: aFarY = a0y
        bFarX = b0x: bFarY = b0y
        TryGetSharedDxfSegmentCorner = True
        Exit Function
    End If
End Function

Private Function DxfPointsCoincident2(ByVal x1 As Double, _
                                      ByVal y1 As Double, _
                                      ByVal x2 As Double, _
                                      ByVal y2 As Double) As Boolean
    DxfPointsCoincident2 = (Sqr((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) <= DXF_POSTPROCESS_POINT_TOL)
End Function

Private Function GetDxfSegmentEndpointBoundsAfterRotation(ByRef sx0() As Double, _
                                                          ByRef sy0() As Double, _
                                                          ByRef sx1() As Double, _
                                                          ByRef sy1() As Double, _
                                                          ByVal segmentCount As Long, _
                                                          ByVal rotationRad As Double, _
                                                          ByRef minX As Double, _
                                                          ByRef minY As Double, _
                                                          ByRef maxX As Double, _
                                                          ByRef maxY As Double, _
                                                          ByRef pointCount As Long) As Boolean
    On Error GoTo EH

    GetDxfSegmentEndpointBoundsAfterRotation = False
    pointCount = 0

    Dim c As Double, s As Double
    c = Cos(rotationRad)
    s = Sin(rotationRad)

    Dim i As Long
    Dim rx As Double, ry As Double

    For i = 0 To segmentCount - 1
        RotatePoint2D sx0(i), sy0(i), c, s, rx, ry
        ExpandDxfBounds rx, ry, minX, minY, maxX, maxY, pointCount

        RotatePoint2D sx1(i), sy1(i), c, s, rx, ry
        ExpandDxfBounds rx, ry, minX, minY, maxX, maxY, pointCount
    Next i

    GetDxfSegmentEndpointBoundsAfterRotation = (pointCount > 0)
    Exit Function

EH:
    LogEvent " | WARN  | GetDxfSegmentEndpointBoundsAfterRotation: " & Err.Number & " - " & Err.Description
End Function

Private Sub ExpandDxfBounds(ByVal x As Double, _
                            ByVal y As Double, _
                            ByRef minX As Double, _
                            ByRef minY As Double, _
                            ByRef maxX As Double, _
                            ByRef maxY As Double, _
                            ByRef pointCount As Long)
    If pointCount = 0 Then
        minX = x: maxX = x
        minY = y: maxY = y
    Else
        If x < minX Then minX = x
        If x > maxX Then maxX = x
        If y < minY Then minY = y
        If y > maxY Then maxY = y
    End If

    pointCount = pointCount + 1
End Sub

Private Function FindDxfEntitiesRange(ByRef lines() As String, _
                                      ByVal lineCount As Long, _
                                      ByRef entStartIndex As Long, _
                                      ByRef entEndIndex As Long) As Boolean
    On Error GoTo EH

    FindDxfEntitiesRange = False
    entStartIndex = 0
    entEndIndex = 0

    If lineCount < 6 Then Exit Function

    Dim i As Long
    Dim codeNum As Long
    Dim valueText As String
    Dim pendingSection As Boolean
    Dim insideEntities As Boolean

    pendingSection = False
    insideEntities = False

    For i = 0 To lineCount - 2 Step 2
        codeNum = DxfGroupCodeToLong(lines(i))
        valueText = UCase$(Trim$(lines(i + 1)))

        If pendingSection And codeNum = 2 Then
            If valueText = "ENTITIES" Then
                insideEntities = True
                entStartIndex = i + 2
            End If
            pendingSection = False

        ElseIf codeNum = 0 And valueText = "SECTION" Then
            pendingSection = True

        ElseIf insideEntities And codeNum = 0 And valueText = "ENDSEC" Then
            entEndIndex = i - 2
            If entEndIndex >= entStartIndex Then
                FindDxfEntitiesRange = True
            End If
            Exit Function
        End If
    Next i

    If insideEntities Then
        entEndIndex = lineCount - 2
        FindDxfEntitiesRange = (entEndIndex >= entStartIndex)
    End If

    Exit Function

EH:
    LogEvent " | WARN  | FindDxfEntitiesRange: " & Err.Number & " - " & Err.Description
End Function

Private Function FindDominantDxfLinearAngle(ByRef lines() As String, _
                                            ByVal lineCount As Long, _
                                            ByVal entStartIndex As Long, _
                                            ByVal entEndIndex As Long, _
                                            ByRef bestAngleRad As Double, _
                                            ByRef bestLen As Double, _
                                            ByRef segmentCount As Long) As Boolean
    On Error GoTo EH

    FindDominantDxfLinearAngle = False
    bestAngleRad = 0#
    bestLen = -1#
    segmentCount = 0

    Dim currentEntity As String
    Dim inOldPolyline As Boolean
    Dim oldPolylineClosed As Boolean

    Dim lineHaveStart As Boolean
    Dim lineHaveEnd As Boolean
    Dim lineX0 As Double, lineY0 As Double
    Dim lineX1 As Double, lineY1 As Double

    Dim polyX() As Double
    Dim polyY() As Double
    Dim polyCount As Long
    Dim polyClosed As Boolean

    Dim oldPolyX() As Double
    Dim oldPolyY() As Double
    Dim oldPolyCount As Long

    Dim i As Long
    Dim codeNum As Long
    Dim valText As String

    currentEntity = ""
    inOldPolyline = False
    oldPolylineClosed = False
    polyCount = 0
    oldPolyCount = 0

    For i = entStartIndex To entEndIndex Step 2
        codeNum = DxfGroupCodeToLong(lines(i))
        valText = Trim$(lines(i + 1))

        If codeNum = 0 Then
            FinalizeDxfSegmentEntity currentEntity, _
                                     lineHaveStart, lineHaveEnd, lineX0, lineY0, lineX1, lineY1, _
                                     polyX, polyY, polyCount, polyClosed, _
                                     bestAngleRad, bestLen, segmentCount

            currentEntity = UCase$(valText)

            lineHaveStart = False
            lineHaveEnd = False
            polyCount = 0
            polyClosed = False

            If currentEntity = "POLYLINE" Then
                inOldPolyline = True
                oldPolylineClosed = False
                oldPolyCount = 0
            ElseIf currentEntity = "SEQEND" Then
                If inOldPolyline Then
                    AddDxfPolylineSegments oldPolyX, oldPolyY, oldPolyCount, oldPolylineClosed, bestAngleRad, bestLen, segmentCount
                    inOldPolyline = False
                    oldPolylineClosed = False
                    oldPolyCount = 0
                End If
            End If

        Else
            Select Case currentEntity
                Case "LINE"
                    If codeNum = 10 Then
                        If TryReadDxfXYAt(lines, lineCount, i, 10, lineX0, lineY0) Then lineHaveStart = True
                    ElseIf codeNum = 11 Then
                        If TryReadDxfXYAt(lines, lineCount, i, 11, lineX1, lineY1) Then lineHaveEnd = True
                    End If

                Case "LWPOLYLINE"
                    If codeNum = 10 Then
                        Dim px As Double, py As Double
                        If TryReadDxfXYAt(lines, lineCount, i, 10, px, py) Then
                            AddDxf2DPoint polyX, polyY, polyCount, px, py
                        End If
                    ElseIf codeNum = 70 Then
                        polyClosed = ((CLng(Val(valText)) And 1) <> 0)
                    End If

                Case "POLYLINE"
                    If codeNum = 70 Then
                        oldPolylineClosed = ((CLng(Val(valText)) And 1) <> 0)
                    End If

                Case "VERTEX"
                    If inOldPolyline Then
                        If codeNum = 10 Then
                            Dim vx As Double, vy As Double
                            If TryReadDxfXYAt(lines, lineCount, i, 10, vx, vy) Then
                                AddDxf2DPoint oldPolyX, oldPolyY, oldPolyCount, vx, vy
                            End If
                        End If
                    End If
            End Select
        End If
    Next i

    FinalizeDxfSegmentEntity currentEntity, _
                             lineHaveStart, lineHaveEnd, lineX0, lineY0, lineX1, lineY1, _
                             polyX, polyY, polyCount, polyClosed, _
                             bestAngleRad, bestLen, segmentCount

    If inOldPolyline Then
        AddDxfPolylineSegments oldPolyX, oldPolyY, oldPolyCount, oldPolylineClosed, bestAngleRad, bestLen, segmentCount
    End If

    FindDominantDxfLinearAngle = (segmentCount > 0 And bestLen > 0#)
    Exit Function

EH:
    LogEvent " | WARN  | FindDominantDxfLinearAngle: " & Err.Number & " - " & Err.Description
End Function

Private Sub FinalizeDxfSegmentEntity(ByVal entityName As String, _
                                     ByVal lineHaveStart As Boolean, _
                                     ByVal lineHaveEnd As Boolean, _
                                     ByVal lineX0 As Double, _
                                     ByVal lineY0 As Double, _
                                     ByVal lineX1 As Double, _
                                     ByVal lineY1 As Double, _
                                     ByRef polyX() As Double, _
                                     ByRef polyY() As Double, _
                                     ByVal polyCount As Long, _
                                     ByVal polyClosed As Boolean, _
                                     ByRef bestAngleRad As Double, _
                                     ByRef bestLen As Double, _
                                     ByRef segmentCount As Long)
    On Error GoTo EH

    Select Case UCase$(entityName)
        Case "LINE"
            If lineHaveStart And lineHaveEnd Then
                ConsiderDxfLinearSegment lineX0, lineY0, lineX1, lineY1, bestAngleRad, bestLen, segmentCount
            End If

        Case "LWPOLYLINE"
            AddDxfPolylineSegments polyX, polyY, polyCount, polyClosed, bestAngleRad, bestLen, segmentCount
    End Select

    Exit Sub

EH:
    LogEvent " | WARN  | FinalizeDxfSegmentEntity(" & entityName & "): " & Err.Number & " - " & Err.Description
End Sub

Private Sub AddDxfPolylineSegments(ByRef px() As Double, _
                                   ByRef py() As Double, _
                                   ByVal ptCount As Long, _
                                   ByVal isClosed As Boolean, _
                                   ByRef bestAngleRad As Double, _
                                   ByRef bestLen As Double, _
                                   ByRef segmentCount As Long)
    On Error GoTo EH

    If ptCount < 2 Then Exit Sub

    Dim i As Long
    For i = 0 To ptCount - 2
        ConsiderDxfLinearSegment px(i), py(i), px(i + 1), py(i + 1), bestAngleRad, bestLen, segmentCount
    Next i

    If isClosed And ptCount > 2 Then
        ConsiderDxfLinearSegment px(ptCount - 1), py(ptCount - 1), px(0), py(0), bestAngleRad, bestLen, segmentCount
    End If

    Exit Sub

EH:
    LogEvent " | WARN  | AddDxfPolylineSegments: " & Err.Number & " - " & Err.Description
End Sub

Private Sub ConsiderDxfLinearSegment(ByVal x0 As Double, _
                                     ByVal y0 As Double, _
                                     ByVal x1 As Double, _
                                     ByVal y1 As Double, _
                                     ByRef bestAngleRad As Double, _
                                     ByRef bestLen As Double, _
                                     ByRef segmentCount As Long)
    On Error GoTo EH

    Dim dx As Double
    Dim dy As Double
    Dim L As Double
    Dim a As Double

    dx = x1 - x0
    dy = y1 - y0
    L = Sqr(dx * dx + dy * dy)

    If L < DXF_POSTPROCESS_MIN_SEGMENT_LENGTH Then Exit Sub

    a = NormalizeAngleToHalfPi(Atn2(dy, dx))

    segmentCount = segmentCount + 1

    If L > bestLen + EPS Then
        bestLen = L
        bestAngleRad = a
    ElseIf Abs(L - bestLen) <= EPS Then
        'Tie-breaker: prefer the segment requiring less rotation, then stable positive angle.
        If Abs(a) < Abs(bestAngleRad) - EPS Then
            bestAngleRad = a
        ElseIf Abs(Abs(a) - Abs(bestAngleRad)) <= EPS Then
            If a > bestAngleRad Then bestAngleRad = a
        End If
    End If

    Exit Sub

EH:
    LogEvent " | WARN  | ConsiderDxfLinearSegment: " & Err.Number & " - " & Err.Description
End Sub

Private Function NormalizeAngleToHalfPi(ByVal angleRad As Double) As Double
    Do While angleRad <= -PI_VAL / 2#
        angleRad = angleRad + PI_VAL
    Loop

    Do While angleRad > PI_VAL / 2#
        angleRad = angleRad - PI_VAL
    Loop

    NormalizeAngleToHalfPi = angleRad
End Function

Private Function GetRotatedDxfPointBounds(ByRef lines() As String, _
                                          ByVal lineCount As Long, _
                                          ByVal entStartIndex As Long, _
                                          ByVal entEndIndex As Long, _
                                          ByVal rotationRad As Double, _
                                          ByRef minX As Double, _
                                          ByRef minY As Double, _
                                          ByRef maxX As Double, _
                                          ByRef maxY As Double, _
                                          ByRef pointCount As Long) As Boolean
    On Error GoTo EH

    GetRotatedDxfPointBounds = False
    pointCount = 0

    Dim c As Double
    Dim s As Double
    c = Cos(rotationRad)
    s = Sin(rotationRad)

    Dim i As Long
    Dim codeNum As Long
    Dim x As Double, y As Double
    Dim rx As Double, ry As Double
    Dim currentEntity As String

    currentEntity = ""

    For i = entStartIndex To entEndIndex Step 2
        codeNum = DxfGroupCodeToLong(lines(i))

        If codeNum = 0 Then
            currentEntity = UCase$(Trim$(lines(i + 1)))
        ElseIf IsDxfPointXCode(codeNum) Then
            If IsDxfCoordinatePairAllowedForEntity(currentEntity, codeNum) Then
                If TryReadDxfXYAt(lines, lineCount, i, codeNum, x, y) Then
                    RotatePoint2D x, y, c, s, rx, ry

                    If pointCount = 0 Then
                        minX = rx: maxX = rx
                        minY = ry: maxY = ry
                    Else
                        If rx < minX Then minX = rx
                        If rx > maxX Then maxX = rx
                        If ry < minY Then minY = ry
                        If ry > maxY Then maxY = ry
                    End If

                    pointCount = pointCount + 1
                End If
            End If
        End If
    Next i

    GetRotatedDxfPointBounds = (pointCount > 0)
    Exit Function

EH:
    LogEvent " | WARN  | GetRotatedDxfPointBounds: " & Err.Number & " - " & Err.Description
End Function

Private Function ApplyDxf2DRotationToLines(ByRef lines() As String, _
                                           ByVal lineCount As Long, _
                                           ByVal entStartIndex As Long, _
                                           ByVal entEndIndex As Long, _
                                           ByVal rotationRad As Double, _
                                           ByVal offsetX As Double, _
                                           ByVal offsetY As Double) As Boolean
    On Error GoTo EH

    ApplyDxf2DRotationToLines = False

    Dim c As Double
    Dim s As Double
    Dim rotDeg As Double

    c = Cos(rotationRad)
    s = Sin(rotationRad)
    rotDeg = RadToDeg(rotationRad)

    Dim i As Long
    Dim codeNum As Long
    Dim x As Double, y As Double
    Dim rx As Double, ry As Double
    Dim currentEntity As String
    Dim useTranslation As Boolean

    currentEntity = ""

    For i = entStartIndex To entEndIndex Step 2
        codeNum = DxfGroupCodeToLong(lines(i))

        If codeNum = 0 Then
            currentEntity = UCase$(Trim$(lines(i + 1)))

        ElseIf IsDxfPointXCode(codeNum) Then
            If IsDxfCoordinatePairAllowedForEntity(currentEntity, codeNum) Then
                If TryReadDxfXYAt(lines, lineCount, i, codeNum, x, y) Then
                    RotatePoint2D x, y, c, s, rx, ry

                    useTranslation = True
                    If currentEntity = "ELLIPSE" And codeNum = 11 Then
                        'Ellipse 11/21 is the major-axis vector, not a point.
                        useTranslation = False
                    End If

                    If useTranslation Then
                        rx = rx + offsetX
                        ry = ry + offsetY
                    End If

                    lines(i + 1) = FormatDxfDouble(rx)
                    lines(i + 3) = FormatDxfDouble(ry)
                End If
            End If

        ElseIf currentEntity = "ARC" Then
            If codeNum = 50 Or codeNum = 51 Then
                lines(i + 1) = FormatDxfDouble(NormalizeDegrees360(DxfTextToDouble(lines(i + 1)) + rotDeg))
            End If

        ElseIf currentEntity = "TEXT" Or currentEntity = "MTEXT" Or currentEntity = "INSERT" Then
            If codeNum = 50 Then
                lines(i + 1) = FormatDxfDouble(NormalizeDegrees360(DxfTextToDouble(lines(i + 1)) + rotDeg))
            End If
        End If
    Next i

    ApplyDxf2DRotationToLines = True
    Exit Function

EH:
    LogEvent " | WARN  | ApplyDxf2DRotationToLines: " & Err.Number & " - " & Err.Description
End Function

Private Function IsDxfPointXCode(ByVal codeNum As Long) As Boolean
    'Waterjet exports mostly use 10/20, 11/21, etc.
    'Do not include 210/220 extrusion vectors here; changing extrusion vectors can corrupt DXF import.
    IsDxfPointXCode = (codeNum >= 10 And codeNum <= 18)
End Function

Private Function IsDxfCoordinatePairAllowedForEntity(ByVal entityName As String, ByVal xCode As Long) As Boolean
    'Default to allowing common 2D geometry point codes.
    'A small deny-list protects known vector-only pairs.
    IsDxfCoordinatePairAllowedForEntity = True

    Select Case UCase$(entityName)
        Case "ELLIPSE"
            '10/20 center is a point; 11/21 major-axis is a vector.
            If xCode = 11 Then
                IsDxfCoordinatePairAllowedForEntity = True
            End If
    End Select
End Function

Private Function TryReadDxfXYAt(ByRef lines() As String, _
                                ByVal lineCount As Long, _
                                ByVal codeIndex As Long, _
                                ByVal xCode As Long, _
                                ByRef xOut As Double, _
                                ByRef yOut As Double) As Boolean
    On Error GoTo EH

    TryReadDxfXYAt = False

    If codeIndex < 0 Then Exit Function
    If codeIndex + 3 >= lineCount Then Exit Function

    If DxfGroupCodeToLong(lines(codeIndex)) <> xCode Then Exit Function
    If DxfGroupCodeToLong(lines(codeIndex + 2)) <> xCode + 10 Then Exit Function

    xOut = DxfTextToDouble(lines(codeIndex + 1))
    yOut = DxfTextToDouble(lines(codeIndex + 3))

    TryReadDxfXYAt = True
    Exit Function

EH:
    TryReadDxfXYAt = False
End Function

Private Sub AddDxf2DPoint(ByRef px() As Double, _
                          ByRef py() As Double, _
                          ByRef ptCount As Long, _
                          ByVal x As Double, _
                          ByVal y As Double)
    On Error GoTo EH

    If ptCount = 0 Then
        ReDim px(0 To 0)
        ReDim py(0 To 0)
    Else
        ReDim Preserve px(0 To ptCount)
        ReDim Preserve py(0 To ptCount)
    End If

    px(ptCount) = x
    py(ptCount) = y
    ptCount = ptCount + 1
    Exit Sub

EH:
    LogEvent " | WARN  | AddDxf2DPoint: " & Err.Number & " - " & Err.Description
End Sub

Private Function DxfGroupCodeToLong(ByVal codeText As String) As Long
    On Error GoTo EH

    codeText = Trim$(codeText)
    If Len(codeText) = 0 Then
        DxfGroupCodeToLong = -999999
    Else
        DxfGroupCodeToLong = CLng(Val(codeText))
    End If
    Exit Function

EH:
    DxfGroupCodeToLong = -999999
End Function

Private Function DxfTextToDouble(ByVal valueText As String) As Double
    On Error GoTo EH

    valueText = Trim$(valueText)
    valueText = Replace$(valueText, ",", ".")

    If Len(valueText) = 0 Then
        DxfTextToDouble = 0#
    Else
        DxfTextToDouble = Val(valueText)
    End If
    Exit Function

EH:
    DxfTextToDouble = 0#
End Function

Private Function FormatDxfDouble(ByVal value As Double) As String
    On Error GoTo EH

    Dim fmt As String
    Dim s As String

    If DXF_POSTPROCESS_OUTPUT_DECIMALS <= 0 Then
        FormatDxfDouble = Trim$(Str$(value))
        Exit Function
    End If

    fmt = "0." & String$(DXF_POSTPROCESS_OUTPUT_DECIMALS, "0")
    s = Format$(value, fmt)
    s = Replace$(s, ",", ".")
    FormatDxfDouble = s
    Exit Function

EH:
    FormatDxfDouble = Trim$(Str$(value))
End Function

Private Function FormatDxfLogNumber(ByVal value As Double) As String
    On Error Resume Next
    FormatDxfLogNumber = Replace$(Format$(value, "0.000000"), ",", ".")
End Function

Private Function NormalizeDegrees360(ByVal degVal As Double) As Double
    Do While degVal < 0#
        degVal = degVal + 360#
    Loop

    Do While degVal >= 360#
        degVal = degVal - 360#
    Loop

    NormalizeDegrees360 = degVal
End Function

Private Function ReadTextFileLinesANSI(ByVal filePath As String, _
                                       ByRef lines() As String, _
                                       ByRef lineCount As Long) As Boolean
    On Error GoTo EH

    ReadTextFileLinesANSI = False
    lineCount = 0

    If Len(Trim$(filePath)) = 0 Then Exit Function
    If Not FileExists(filePath) Then Exit Function

    Dim ff As Integer
    Dim s As String

    ff = FreeFile
    Open filePath For Input As #ff

    Do Until EOF(ff)
        Line Input #ff, s

        If lineCount = 0 Then
            ReDim lines(0 To 0)
        Else
            ReDim Preserve lines(0 To lineCount)
        End If

        lines(lineCount) = s
        lineCount = lineCount + 1
    Loop

    Close #ff

    ReadTextFileLinesANSI = (lineCount > 0)
    Exit Function

EH:
    On Error Resume Next
    If ff <> 0 Then Close #ff
    LogEvent " | WARN  | ReadTextFileLinesANSI(" & filePath & "): " & Err.Number & " - " & Err.Description
End Function

Private Function WriteTextFileLinesANSI(ByVal filePath As String, _
                                        ByRef lines() As String, _
                                        ByVal lineCount As Long) As Boolean
    On Error GoTo EH

    WriteTextFileLinesANSI = False
    If Len(Trim$(filePath)) = 0 Then Exit Function
    If lineCount <= 0 Then Exit Function

    Dim ff As Integer
    Dim i As Long

    ff = FreeFile
    Open filePath For Output As #ff

    For i = 0 To lineCount - 1
        Print #ff, lines(i)
    Next i

    Close #ff

    WriteTextFileLinesANSI = True
    Exit Function

EH:
    On Error Resume Next
    If ff <> 0 Then Close #ff
    LogEvent " | WARN  | WriteTextFileLinesANSI(" & filePath & "): " & Err.Number & " - " & Err.Description
End Function

Private Sub RotatePoint2D(ByVal x As Double, _
                          ByVal y As Double, _
                          ByVal c As Double, _
                          ByVal s As Double, _
                          ByRef xOut As Double, _
                          ByRef yOut As Double)
    xOut = (x * c) - (y * s)
    yOut = (x * s) + (y * c)
End Sub

Private Sub CopyFileIfExists(ByVal sourcePath As String, ByVal destPath As String)
    On Error GoTo EH

    If Len(Trim$(sourcePath)) = 0 Then Exit Sub
    If Len(Trim$(destPath)) = 0 Then Exit Sub
    If Not FileExists(sourcePath) Then Exit Sub

    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")

    If fso.FileExists(destPath) Then fso.DeleteFile destPath, True
    fso.CopyFile sourcePath, destPath, True

    LogEvent " | INFO  | DXF post-process backup written => " & destPath
    Exit Sub

EH:
    LogEvent " | WARN  | CopyFileIfExists failed: " & Err.Number & " - " & Err.Description
End Sub

Private Function CreateTempPartFromBody(ByVal body As SldWorks.Body2, ByVal tempPartPath As String, Optional ByVal saveImmediately As Boolean = True) As SldWorks.ModelDoc2
    On Error GoTo EH

    Dim partTemplate As String
    partTemplate = GetPartTemplatePath()
    If Len(partTemplate) = 0 Then
        Debug.Print TimeStamp() & " | FAIL  | No default part template available"
        Exit Function
    End If

    Debug.Print TimeStamp() & " | INFO  | Temp part template = " & partTemplate
    Debug.Print TimeStamp() & " | INFO  | Temp part target   = " & tempPartPath

    Dim tempDoc As SldWorks.ModelDoc2
    Set tempDoc = swApp.NewDocument(partTemplate, 0, 0#, 0#)

    If tempDoc Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | New temp part document creation failed"
        Exit Function
    End If

    Dim tempPart As SldWorks.PartDoc
    Set tempPart = tempDoc

    tempDoc.ClearSelection2 True

    Dim newFeat As SldWorks.Feature
    Set newFeat = tempPart.CreateFeatureFromBody3(body, False, swCreateFeatureBodySimplify)

    If newFeat Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | CreateFeatureFromBody3 returned Nothing"
        swApp.CloseDoc tempDoc.GetTitle
        Exit Function
    End If

    tempDoc.ForceRebuild3 True

    If Not HideAllSketchesInModel(tempDoc) Then
        Debug.Print TimeStamp() & " | WARN  | HideAllSketchesInModel returned False during temp part creation"
    End If

    If DIRECT_TEMP_PART_FORCE_INCH_UNITS Then
        If ForceModelLinearUnitsToInches(tempDoc) Then
            Debug.Print TimeStamp() & " | INFO  | Temp part units forced to inches for direct DXF export"
        Else
            Debug.Print TimeStamp() & " | WARN  | Temp part units could not be forced to inches"
        End If
    End If

    If Not FAST_MODE_MINIMIZE_EXTRA_REDRAWS Then
        tempDoc.ViewZoomtofit2
    End If

    If saveImmediately Then
        If Not TrySaveModelToPath(tempDoc, tempPartPath) Then
            Debug.Print TimeStamp() & " | FAIL  | All temp part save attempts failed"
            swApp.CloseDoc tempDoc.GetTitle
            Exit Function
        End If

        Debug.Print TimeStamp() & " | INFO  | Temp part saved = " & tempPartPath
    Else
        Debug.Print TimeStamp() & " | INFO  | Temp part created in memory; initial disk save deferred"
    End If

    Set CreateTempPartFromBody = tempDoc
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | CreateTempPartFromBody: " & Err.Number & " - " & Err.Description
End Function

Private Function TrySaveModelToPath(ByVal mdl As SldWorks.ModelDoc2, ByVal filePath As String) As Boolean
    On Error GoTo EH

    TrySaveModelToPath = False

    If mdl Is Nothing Then Exit Function
    If Len(filePath) = 0 Then Exit Function

    DeleteFileIfExists filePath

    Dim actErr As Long
    actErr = 0
    On Error Resume Next
    swApp.ActivateDoc3 mdl.GetTitle, False, swDontRebuildActiveDoc, actErr
    Err.Clear
    On Error GoTo EH

    mdl.ForceRebuild3 True
    mdl.ViewZoomtofit2
    DoEvents

    Dim errs As Long, warns As Long
    errs = 0: warns = 0

    Debug.Print TimeStamp() & " | INFO  | Save attempt 1: Extension.SaveAs"
    If mdl.Extension.SaveAs(filePath, swSaveAsCurrentVersion, swSaveAsOptions_Silent, Nothing, errs, warns) Then
        Debug.Print TimeStamp() & " | INFO  | Save attempt 1 returned True. errs=" & errs & " warns=" & warns
        If FileExists(filePath) Then
            TrySaveModelToPath = True
            Exit Function
        End If
        Debug.Print TimeStamp() & " | WARN  | Save attempt 1 returned True but file not found"
    Else
        Debug.Print TimeStamp() & " | WARN  | Save attempt 1 returned False. errs=" & errs & " warns=" & warns
    End If

    errs = 0: warns = 0
    Debug.Print TimeStamp() & " | INFO  | Save attempt 2: Extension.SaveAs with COPY option"
    If mdl.Extension.SaveAs(filePath, swSaveAsCurrentVersion, swSaveAsOptions_Silent Or swSaveAsOptions_Copy, Nothing, errs, warns) Then
        Debug.Print TimeStamp() & " | INFO  | Save attempt 2 returned True. errs=" & errs & " warns=" & warns
        If FileExists(filePath) Then
            TrySaveModelToPath = True
            Exit Function
        End If
        Debug.Print TimeStamp() & " | WARN  | Save attempt 2 returned True but file not found"
    Else
        Debug.Print TimeStamp() & " | WARN  | Save attempt 2 returned False. errs=" & errs & " warns=" & warns
    End If

    errs = 0: warns = 0
    Debug.Print TimeStamp() & " | INFO  | Save attempt 3: Extension.SaveAs after re-activate"
    actErr = 0
    On Error Resume Next
    swApp.ActivateDoc3 mdl.GetTitle, True, swDontRebuildActiveDoc, actErr
    Err.Clear
    On Error GoTo EH

    mdl.GraphicsRedraw2
    mdl.ViewZoomtofit2
    DoEvents

    If mdl.Extension.SaveAs(filePath, swSaveAsCurrentVersion, swSaveAsOptions_Silent, Nothing, errs, warns) Then
        Debug.Print TimeStamp() & " | INFO  | Save attempt 3 returned True. errs=" & errs & " warns=" & warns
        If FileExists(filePath) Then
            TrySaveModelToPath = True
            Exit Function
        End If
        Debug.Print TimeStamp() & " | WARN  | Save attempt 3 returned True but file not found"
    Else
        Debug.Print TimeStamp() & " | WARN  | Save attempt 3 returned False. errs=" & errs & " warns=" & warns
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | TrySaveModelToPath: " & Err.Number & " - " & Err.Description
End Function

Private Function OrientAndNameTempPartView(ByVal tempDoc As SldWorks.ModelDoc2, _
                                           ByRef xDir() As Double, _
                                           ByRef faceNormal() As Double, _
                                           ByVal viewName As String) As Boolean
    On Error GoTo EH

    OrientAndNameTempPartView = False

    If tempDoc Is Nothing Then Exit Function

    Dim viewXf As SldWorks.MathTransform
    Set viewXf = BuildViewOrientationTransform(xDir, faceNormal)

    If viewXf Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | BuildViewOrientationTransform returned Nothing"
        Exit Function
    End If

    Dim mvObj As Object
    Set mvObj = tempDoc.ActiveView

    If mvObj Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | tempDoc.ActiveView returned Nothing"
        Exit Function
    End If

    Debug.Print TimeStamp() & " | INFO  | Setting current model view orientation"
    On Error Resume Next
    CallByName mvObj, "Orientation3", VbSet, viewXf
    If Err.Number <> 0 Then
        Debug.Print TimeStamp() & " | FAIL  | Setting Orientation3 failed: " & Err.Number & " - " & Err.Description
        Err.Clear
        On Error GoTo EH
        Exit Function
    End If
    On Error GoTo EH

    tempDoc.GraphicsRedraw2
    tempDoc.ViewZoomtofit2

    On Error Resume Next
    tempDoc.DeleteNamedView viewName
    Err.Clear
    On Error GoTo EH

    Debug.Print TimeStamp() & " | INFO  | Naming current view as [" & viewName & "]"
    tempDoc.NameView viewName
    tempDoc.GraphicsRedraw2
    tempDoc.ViewZoomtofit2

    OrientAndNameTempPartView = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | OrientAndNameTempPartView: " & Err.Number & " - " & Err.Description
End Function

Private Function ReopenTempPartForDirectExport(ByRef currentDoc As SldWorks.ModelDoc2, ByVal tempPartPath As String) As SldWorks.ModelDoc2
    On Error GoTo EH

    Set ReopenTempPartForDirectExport = Nothing

    If Len(Trim$(tempPartPath)) = 0 Then Exit Function
    If Not FileExists(tempPartPath) Then
        Debug.Print TimeStamp() & " | FAIL  | ReopenTempPartForDirectExport: temp part file does not exist: " & tempPartPath
        Exit Function
    End If

    Debug.Print TimeStamp() & " | INFO  | Closing in-memory temp part before direct reopen"
    CloseModelDocSafe currentDoc

    Dim errs As Long
    Dim warns As Long
    errs = 0
    warns = 0

    Debug.Print TimeStamp() & " | INFO  | Reopening persisted temp part for direct export: " & tempPartPath
    Set ReopenTempPartForDirectExport = swApp.OpenDoc6(tempPartPath, swDocPART, swOpenDocOptions_Silent Or swOpenDocOptions_ReadOnly, "", errs, warns)

    Debug.Print TimeStamp() & " | INFO  | Reopen temp part result errs=" & errs & " warns=" & warns

    If ReopenTempPartForDirectExport Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | ReopenTempPartForDirectExport returned Nothing"
    End If
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ReopenTempPartForDirectExport: " & Err.Number & " - " & Err.Description
End Function

Private Function ExportTempPartToDxf_DirectByAnnotationView(ByVal tempPartDoc As SldWorks.ModelDoc2, _
                                                            ByVal tempPartPath As String, _
                                                            ByVal finalDxfPath As String, _
                                                            ByVal modelViewName As String, _
                                                            ByVal preserveCornerOrientation As Boolean) As Boolean
    On Error GoTo EH

    ExportTempPartToDxf_DirectByAnnotationView = False

    If tempPartDoc Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | Direct export: tempPartDoc is Nothing"
        Exit Function
    End If

    If tempPartDoc.GetType <> swDocPART Then
        Debug.Print TimeStamp() & " | FAIL  | Direct export requires PART doc, got " & DocTypeName(tempPartDoc.GetType)
        Exit Function
    End If

    Dim swTempPart As SldWorks.PartDoc
    Set swTempPart = tempPartDoc

    Dim alignmentData(0 To 11) As Double
    Dim varAlignment As Variant
    BuildIdentityDwgAlignment alignmentData
    varAlignment = alignmentData

    If Not ActivateDocumentByTitle(tempPartDoc.GetTitle) Then
        Debug.Print TimeStamp() & " | WARN  | Direct export could not explicitly activate temp part"
    End If

    tempPartDoc.ForceRebuild3 True

    If Not HideAllSketchesInModel(tempPartDoc) Then
        Debug.Print TimeStamp() & " | WARN  | HideAllSketchesInModel returned False immediately before direct DXF export"
    End If

    If DIRECT_TEMP_PART_FORCE_INCH_UNITS Then
        If ForceModelLinearUnitsToInches(tempPartDoc) Then
            Debug.Print TimeStamp() & " | INFO  | Direct export temp part linear units = INCHES"
        Else
            Debug.Print TimeStamp() & " | WARN  | Direct export could not confirm INCH units on temp part"
        End If
    End If

    tempPartDoc.GraphicsRedraw2
    tempPartDoc.ViewZoomtofit2

    Debug.Print TimeStamp() & " | INFO  | Direct export preserveCornerOrientation = " & CStr(preserveCornerOrientation)
    Debug.Print TimeStamp() & " | INFO  | Direct export requested view name = [" & modelViewName & "]"

    If TryDirectExportToDxfByViewName(swTempPart, tempPartPath, finalDxfPath, modelViewName, varAlignment) Then
        ExportTempPartToDxf_DirectByAnnotationView = True
        Exit Function
    End If

    If EXPERIMENTAL_DIRECT_ALLOW_CURRENT_VIEW_FALLBACK Then
        Debug.Print TimeStamp() & " | WARN  | Experimental direct export by named view failed; trying *Current fallback"
        If TryDirectExportToDxfByViewName(swTempPart, tempPartPath, finalDxfPath, "*Current", varAlignment) Then
            ExportTempPartToDxf_DirectByAnnotationView = True
            Exit Function
        End If
    Else
        Debug.Print TimeStamp() & " | INFO  | *Current fallback disabled to avoid losing deterministic orientation"
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ExportTempPartToDxf_DirectByAnnotationView: " & Err.Number & " - " & Err.Description
End Function

Private Function TryDirectExportToDxfByViewName(ByVal swTempPart As SldWorks.PartDoc, _
                                                ByVal modelPath As String, _
                                                ByVal finalDxfPath As String, _
                                                ByVal viewName As String, _
                                                ByVal varAlignment As Variant) As Boolean
    On Error GoTo EH

    Dim dataViews(0 To 0) As String
    Dim varViews As Variant
    Dim resultVar As Variant
    Dim ok As Boolean

    TryDirectExportToDxfByViewName = False

    dataViews(0) = viewName
    varViews = dataViews

    DeleteFileIfExists finalDxfPath

    Debug.Print TimeStamp() & " | INFO  | Direct ExportToDWG2 start"
    Debug.Print TimeStamp() & " | INFO  |   modelPath    = " & modelPath
    Debug.Print TimeStamp() & " | INFO  |   finalDxfPath = " & finalDxfPath
    Debug.Print TimeStamp() & " | INFO  |   viewName     = " & viewName

    On Error Resume Next
    resultVar = CallByName(swTempPart, "ExportToDWG2", VbMethod, _
                           finalDxfPath, _
                           modelPath, _
                           SW_EXPORT_TO_DWG_ANNOTATION_VIEWS, _
                           True, _
                           varAlignment, _
                           False, _
                           False, _
                           0, _
                           varViews)
    If Err.Number <> 0 Then
        Debug.Print TimeStamp() & " | WARN  | CallByName ExportToDWG2 failed for [" & viewName & "]: " & Err.Number & " - " & Err.Description
        Err.Clear
        On Error GoTo EH
        Exit Function
    End If
    On Error GoTo EH

    ok = False
    On Error Resume Next
    ok = CBool(resultVar)
    On Error GoTo EH

    Debug.Print TimeStamp() & " | INFO  | ExportToDWG2 result = " & CStr(ok)

    If Not ok Then Exit Function

    If Not FileExists(finalDxfPath) Then
        Debug.Print TimeStamp() & " | WARN  | ExportToDWG2 returned True but output file not found"
        Exit Function
    End If

    If GetFileSizeSafe(finalDxfPath) <= 0 Then
        Debug.Print TimeStamp() & " | WARN  | ExportToDWG2 created zero-byte DXF"
        Exit Function
    End If

    Debug.Print TimeStamp() & " | INFO  | Direct ExportToDWG2 succeeded. File size = " & CStr(GetFileSizeSafe(finalDxfPath))
    TryDirectExportToDxfByViewName = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | TryDirectExportToDxfByViewName(" & viewName & "): " & Err.Number & " - " & Err.Description
End Function

Private Sub BuildIdentityDwgAlignment(ByRef alignmentData() As Double)
    alignmentData(0) = 0#
    alignmentData(1) = 0#
    alignmentData(2) = 0#
    alignmentData(3) = 1#
    alignmentData(4) = 0#
    alignmentData(5) = 0#
    alignmentData(6) = 0#
    alignmentData(7) = 1#
    alignmentData(8) = 0#
    alignmentData(9) = 0#
    alignmentData(10) = 0#
    alignmentData(11) = 1#
End Sub

Private Function ActivateDocumentByTitle(ByVal docTitle As String) As Boolean
    On Error GoTo EH

    ActivateDocumentByTitle = False

    If Len(Trim$(docTitle)) = 0 Then Exit Function

    Dim actErr As Long
    Dim mdl As SldWorks.ModelDoc2

    Set mdl = swApp.ActivateDoc3(docTitle, False, 0, actErr)
    Debug.Print TimeStamp() & " | INFO  | ActivateDoc3 [" & docTitle & "] err=" & actErr

    If Not mdl Is Nothing Then
        ActivateDocumentByTitle = True
        Exit Function
    End If

    If Not swApp.ActiveDoc Is Nothing Then
        If StrComp(swApp.ActiveDoc.GetTitle, docTitle, vbTextCompare) = 0 Then
            ActivateDocumentByTitle = True
        End If
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ActivateDocumentByTitle(" & docTitle & "): " & Err.Number & " - " & Err.Description
End Function

Private Function ForceModelLinearUnitsToInches(ByVal mdl As SldWorks.ModelDoc2) As Boolean
    On Error GoTo EH

    ForceModelLinearUnitsToInches = False

    If mdl Is Nothing Then Exit Function

    Dim beforeUnits As Long
    Dim afterUnits As Long

    On Error Resume Next
    beforeUnits = mdl.GetUserPreferenceIntegerValue(swUnitsLinear)
    Err.Clear
    On Error GoTo EH

    Debug.Print TimeStamp() & " | INFO  | ForceModelLinearUnitsToInches before = " & CStr(beforeUnits)

    mdl.SetUserPreferenceIntegerValue swUnitsLinear, swINCHES

    On Error Resume Next
    afterUnits = mdl.GetUserPreferenceIntegerValue(swUnitsLinear)
    Err.Clear
    On Error GoTo EH

    Debug.Print TimeStamp() & " | INFO  | ForceModelLinearUnitsToInches after  = " & CStr(afterUnits)

    ForceModelLinearUnitsToInches = (afterUnits = swINCHES)
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ForceModelLinearUnitsToInches: " & Err.Number & " - " & Err.Description
End Function

Private Sub CloseModelDocSafe(ByRef mdl As SldWorks.ModelDoc2)
    On Error Resume Next

    If mdl Is Nothing Then Exit Sub

    Dim ttl As String
    ttl = mdl.GetTitle

    If Len(ttl) > 0 Then
        swApp.CloseDoc ttl
    End If

    Set mdl = Nothing
End Sub

Private Function GetFileSizeSafe(ByVal filePath As String) As Double
    On Error GoTo EH
    GetFileSizeSafe = 0#
    If Not FileExists(filePath) Then Exit Function
    GetFileSizeSafe = CDbl(FileLen(filePath))
    Exit Function
EH:
    GetFileSizeSafe = 0#
End Function

Private Function GetDxfExportModeName() As String
    If USE_FAST_MODE Then
        If USE_EXPERIMENTAL_FAST_DIRECT_DXF Then
            If EXPERIMENTAL_DIRECT_FALLBACK_TO_DRAWING Then
                GetDxfExportModeName = "FAST_MODE_DIRECT_PART_EXPORT_WITH_MANUAL_DRAWING_FALLBACK"
            Else
                GetDxfExportModeName = "FAST_MODE_DIRECT_PART_EXPORT_ONLY"
            End If
        Else
            GetDxfExportModeName = "FAST_MODE_DIRECT_PART_EXPORT_DISABLED"
        End If
    Else
        GetDxfExportModeName = "LEGACY_SAFE_MODE"
    End If
End Function

Private Function ShouldAttemptFastDirectDxfExport(ByVal preserveCornerOrientation As Boolean) As Boolean
    ShouldAttemptFastDirectDxfExport = False

    If Not USE_FAST_MODE Then Exit Function
    If Not USE_EXPERIMENTAL_FAST_DIRECT_DXF Then Exit Function

    Debug.Print TimeStamp() & " | INFO  | Direct part-export path enabled. preserveCornerOrientation=" & CStr(preserveCornerOrientation)
    ShouldAttemptFastDirectDxfExport = True
End Function

Private Function ExportTempPartToDxf_ByNamedViewDrawing(ByVal tempPartDoc As SldWorks.ModelDoc2, _
                                                        ByVal tempPartPath As String, _
                                                        ByVal tempDrwPath As String, _
                                                        ByVal finalDxfPath As String, _
                                                        ByVal modelViewName As String, _
                                                        ByRef xDir() As Double, _
                                                        ByRef faceNormal() As Double, _
                                                        ByVal preserveCornerOrientation As Boolean) As Boolean
    On Error GoTo EH

    ExportTempPartToDxf_ByNamedViewDrawing = False

    Dim drwTemplate As String
    drwTemplate = GetDrawingTemplatePath()
    If Len(drwTemplate) = 0 Then
        Debug.Print TimeStamp() & " | FAIL  | No drawing template available for export"
        Exit Function
    End If

    Dim bbox As Variant
    bbox = GetFirstBodyBoxFromPart(tempPartDoc)

    Dim w As Double, h As Double
    If Not IsEmpty(bbox) Then
        w = Abs(CDbl(bbox(3)) - CDbl(bbox(0))) + 2# * SHEET_MARGIN_M
        h = Abs(CDbl(bbox(4)) - CDbl(bbox(1))) + 2# * SHEET_MARGIN_M
    Else
        w = MIN_SHEET_W_M
        h = MIN_SHEET_H_M
    End If

    If w < MIN_SHEET_W_M Then w = MIN_SHEET_W_M
    If h < MIN_SHEET_H_M Then h = MIN_SHEET_H_M

    Debug.Print TimeStamp() & " | INFO  | Drawing export sheet size (m) = " & FormatNumber(w, 4) & " x " & FormatNumber(h, 4)
    Debug.Print TimeStamp() & " | INFO  | Creating drawing view from model view [" & modelViewName & "]"

    Dim drwDoc As SldWorks.ModelDoc2
    Set drwDoc = swApp.NewDocument(drwTemplate, swDwgPapersUserDefined, w, h)

    If drwDoc Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | New drawing creation failed"
        Exit Function
    End If

    Dim drw As SldWorks.DrawingDoc
    Set drw = drwDoc

    Dim viewX As Double, viewY As Double
    viewX = w / 2#
    viewY = h / 2#

    Dim v As SldWorks.View
    Set v = drw.CreateDrawViewFromModelView3(tempPartPath, modelViewName, viewX, viewY, 0#)

    If v Is Nothing Then
        Debug.Print TimeStamp() & " | FAIL  | CreateDrawViewFromModelView3 returned Nothing for view [" & modelViewName & "]"
        swApp.CloseDoc drwDoc.GetTitle
        Exit Function
    End If

    On Error Resume Next
    v.UseSheetScale = False
    v.ScaleDecimal = 1#
    On Error GoTo EH

    drwDoc.ForceRebuild3 True
    drwDoc.ViewZoomtofit2

    If CorrectDrawingViewRoll(v, xDir, faceNormal, preserveCornerOrientation) Then
        drwDoc.ForceRebuild3 True
        drwDoc.ViewZoomtofit2
    Else
        Debug.Print TimeStamp() & " | WARN  | CorrectDrawingViewRoll did not make a change"
    End If

    If Not TrySaveModelToPath(drwDoc, tempDrwPath) Then
        Debug.Print TimeStamp() & " | WARN  | Temp drawing save failed; continuing DXF save"
    End If

    Dim errs As Long, warns As Long
    errs = 0: warns = 0
    If drwDoc.Extension.SaveAs(finalDxfPath, swSaveAsCurrentVersion, swSaveAsOptions_Silent, Nothing, errs, warns) Then
        Debug.Print TimeStamp() & " | INFO  | Drawing SaveAs DXF succeeded. errs=" & errs & " warns=" & warns
        If FileExists(finalDxfPath) Then
            ExportTempPartToDxf_ByNamedViewDrawing = True
        End If
    Else
        Debug.Print TimeStamp() & " | FAIL  | Drawing SaveAs DXF failed. errs=" & errs & " warns=" & warns
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | ExportTempPartToDxf_ByNamedViewDrawing: " & Err.Number & " - " & Err.Description
End Function

Private Function CorrectDrawingViewRoll(ByVal v As SldWorks.View, _
                                        ByRef xDir() As Double, _
                                        ByRef faceNormal() As Double, _
                                        ByVal preserveCornerOrientation As Boolean) As Boolean
    On Error GoTo EH

    CorrectDrawingViewRoll = False

    If v Is Nothing Then Exit Function

    Dim ang As Double
    If GetModelVectorAngleInView(v, xDir, ang) Then
        Debug.Print TimeStamp() & " | INFO  | View roll correction angle = " & FormatNumber(RadToDeg(ang), 4) & " deg"

        Dim curAngle As Double
        curAngle = 0#
        On Error Resume Next
        curAngle = CDbl(CallByName(v, "Angle", VbGet))
        If Err.Number <> 0 Then
            Debug.Print TimeStamp() & " | WARN  | Could not read View.Angle: " & Err.Number & " - " & Err.Description
            Err.Clear
            On Error GoTo EH
        Else
            CallByName v, "Angle", VbLet, (curAngle - ang)
            If Err.Number <> 0 Then
                Debug.Print TimeStamp() & " | WARN  | Could not write View.Angle: " & Err.Number & " - " & Err.Description
                Err.Clear
                On Error GoTo EH
            Else
                CorrectDrawingViewRoll = True
            End If
        End If
        On Error GoTo EH
    Else
        Debug.Print TimeStamp() & " | WARN  | Could not determine in-view angle for xDir"
    End If

    Dim outline As Variant
    outline = v.GetOutline

    If VariantHasAtLeast4Numbers(outline) Then
        Dim width As Double, height As Double
        width = Abs(CDbl(outline(2)) - CDbl(outline(0)))
        height = Abs(CDbl(outline(3)) - CDbl(outline(1)))

        Debug.Print TimeStamp() & " | INFO  | Post-roll outline W x H = " & FormatNumber(width, 6) & " x " & FormatNumber(height, 6)

        If preserveCornerOrientation Then
            Debug.Print TimeStamp() & " | INFO  | Corner-driven orientation active -> skipping legacy 90-degree width/height auto-rotate"
        ElseIf height > width + EPS Then
            Debug.Print TimeStamp() & " | INFO  | Applying additional +90 deg correction because view is taller than wide"

            Dim curAngle2 As Double
            curAngle2 = 0#
            On Error Resume Next
            curAngle2 = CDbl(CallByName(v, "Angle", VbGet))
            If Err.Number = 0 Then
                CallByName v, "Angle", VbLet, (curAngle2 + PI_VAL / 2#)
                If Err.Number = 0 Then
                    CorrectDrawingViewRoll = True
                Else
                    Debug.Print TimeStamp() & " | WARN  | Secondary 90-degree correction failed: " & Err.Number & " - " & Err.Description
                    Err.Clear
                End If
            Else
                Debug.Print TimeStamp() & " | WARN  | Could not read View.Angle for 90-degree correction: " & Err.Number & " - " & Err.Description
                Err.Clear
            End If
            On Error GoTo EH
        End If
    End If

    Dim vx As Double, vy As Double, vz As Double
    If TransformModelVectorToView(v, faceNormal, vx, vy, vz) Then
        Debug.Print TimeStamp() & " | INFO  | Face normal in view coords = (" & _
                    FormatNumber(vx, 6) & ", " & FormatNumber(vy, 6) & ", " & FormatNumber(vz, 6) & ")"
    End If

    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | CorrectDrawingViewRoll: " & Err.Number & " - " & Err.Description
End Function

Private Function GetModelVectorAngleInView(ByVal v As SldWorks.View, _
                                           ByRef modelVec() As Double, _
                                           ByRef angRad As Double) As Boolean
    On Error GoTo EH

    GetModelVectorAngleInView = False
    angRad = 0#

    Dim vx As Double, vy As Double, vz As Double
    If Not TransformModelVectorToView(v, modelVec, vx, vy, vz) Then Exit Function

    If Abs(vx) <= EPS And Abs(vy) <= EPS Then Exit Function

    angRad = Atn2(vy, vx)
    GetModelVectorAngleInView = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetModelVectorAngleInView: " & Err.Number & " - " & Err.Description
End Function

Private Function TransformModelVectorToView(ByVal v As SldWorks.View, _
                                            ByRef modelVec() As Double, _
                                            ByRef outX As Double, _
                                            ByRef outY As Double, _
                                            ByRef outZ As Double) As Boolean
    On Error GoTo EH

    TransformModelVectorToView = False

    If v Is Nothing Then Exit Function

    Dim mtv As SldWorks.MathTransform
    Set mtv = v.ModelToViewTransform
    If mtv Is Nothing Then Exit Function

    Dim data(2) As Double
    data(0) = modelVec(0)
    data(1) = modelVec(1)
    data(2) = modelVec(2)

    Dim mv As SldWorks.MathVector
    Set mv = swMathUtil.CreateVector(data)
    If mv Is Nothing Then Exit Function

    Dim tv As SldWorks.MathVector
    Set tv = mv.MultiplyTransform(mtv)
    If tv Is Nothing Then Exit Function

    Dim arr As Variant
    arr = tv.ArrayData
    If Not VariantHas3Numbers(arr) Then Exit Function

    outX = CDbl(arr(0))
    outY = CDbl(arr(1))
    outZ = CDbl(arr(2))

    TransformModelVectorToView = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | TransformModelVectorToView: " & Err.Number & " - " & Err.Description
End Function

Private Function VariantHasAtLeast9Numbers(ByVal v As Variant) As Boolean
    On Error GoTo EH

    VariantHasAtLeast9Numbers = False
    If IsEmpty(v) Then Exit Function
    If Not IsArray(v) Then Exit Function

    Dim lb As Long, ub As Long
    lb = LBound(v)
    ub = UBound(v)

    If (ub - lb + 1) < 9 Then Exit Function

    Dim i As Long, tmp As Double
    For i = 0 To 8
        tmp = CDbl(v(lb + i))
    Next i

    VariantHasAtLeast9Numbers = True
    Exit Function

EH:
    VariantHasAtLeast9Numbers = False
End Function

Private Function VariantHasAtLeast4Numbers(ByVal v As Variant) As Boolean
    On Error GoTo EH

    VariantHasAtLeast4Numbers = False
    If IsEmpty(v) Then Exit Function
    If Not IsArray(v) Then Exit Function

    Dim lb As Long, ub As Long
    lb = LBound(v)
    ub = UBound(v)

    If (ub - lb + 1) < 4 Then Exit Function

    Dim i As Long, tmp As Double
    For i = 0 To 3
        tmp = CDbl(v(lb + i))
    Next i

    VariantHasAtLeast4Numbers = True
    Exit Function

EH:
    VariantHasAtLeast4Numbers = False
End Function

Private Function GetFirstBodyBoxFromPart(ByVal mdl As SldWorks.ModelDoc2) As Variant
    On Error GoTo EH

    Dim p As SldWorks.PartDoc
    Set p = mdl

    Dim vBodies As Variant
    vBodies = p.GetBodies2(swSolidBody, True)

    If IsEmpty(vBodies) Then
        vBodies = p.GetBodies2(swAllBodies, True)
    End If

    If IsEmpty(vBodies) Then Exit Function
    If Not IsArray(vBodies) Then Exit Function

    Dim b As SldWorks.Body2
    Set b = vBodies(LBound(vBodies))

    If b Is Nothing Then Exit Function

    GetFirstBodyBoxFromPart = b.GetBodyBox
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetFirstBodyBoxFromPart: " & Err.Number & " - " & Err.Description
End Function

'=========================================================================================
' TEMPLATE HELPERS
'=========================================================================================
Private Function GetPartTemplatePath() As String
    On Error GoTo EH

    GetPartTemplatePath = Trim$(swApp.GetUserPreferenceStringValue(swDefaultTemplatePart))
    If Len(GetPartTemplatePath) = 0 Then
        GetPartTemplatePath = Trim$(swApp.GetDocumentTemplate(swDocPART, "", 0#, 0#, 0#))
    End If
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetPartTemplatePath: " & Err.Number & " - " & Err.Description
End Function

Private Function GetDrawingTemplatePath() As String
    On Error GoTo EH

    If FileExists(CUSTOM_DRAWING_TEMPLATE) Then
        GetDrawingTemplatePath = CUSTOM_DRAWING_TEMPLATE
        Debug.Print TimeStamp() & " | INFO  | Using custom drawing template = " & GetDrawingTemplatePath
        Exit Function
    End If

    Debug.Print TimeStamp() & " | WARN  | Custom drawing template not found, falling back"

    GetDrawingTemplatePath = Trim$(swApp.GetUserPreferenceStringValue(swDefaultTemplateDrawing))
    If Len(GetDrawingTemplatePath) = 0 Then
        GetDrawingTemplatePath = Trim$(swApp.GetDocumentTemplate(swDocDRAWING, "", 0#, 0#, 0#))
    End If
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetDrawingTemplatePath: " & Err.Number & " - " & Err.Description
End Function

'=========================================================================================
' TEMP PATH HELPERS
'=========================================================================================
Private Function HideAllSketchesInModel(ByVal mdl As SldWorks.ModelDoc2) As Boolean
    On Error GoTo EH

    HideAllSketchesInModel = False

    If mdl Is Nothing Then Exit Function

    If Not ActivateDocumentByTitle(mdl.GetTitle) Then
        Debug.Print TimeStamp() & " | WARN  | HideAllSketchesInModel could not explicitly activate [" & mdl.GetTitle & "]"
    End If

    Dim feat As SldWorks.Feature
    Dim hiddenCount As Long
    Dim visitCount As Long

    Set feat = mdl.FirstFeature

    Do While Not feat Is Nothing
        visitCount = visitCount + 1
        HideSketchFeatureRecursive feat, hiddenCount
        Set feat = feat.GetNextFeature
    Loop

    mdl.ClearSelection2 True
    mdl.GraphicsRedraw2

    Debug.Print TimeStamp() & " | INFO  | HideAllSketchesInModel visited top-level features = " & CStr(visitCount) & " | sketches hidden = " & CStr(hiddenCount)
    HideAllSketchesInModel = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | HideAllSketchesInModel: " & Err.Number & " - " & Err.Description
End Function

Private Sub HideSketchFeatureRecursive(ByVal feat As SldWorks.Feature, ByRef hiddenCount As Long)
    On Error GoTo EH

    If feat Is Nothing Then Exit Sub

    Dim typeName As String
    typeName = feat.GetTypeName2

    If IsSketchFeatureType(typeName) Then
        Debug.Print TimeStamp() & " | INFO  | Hiding sketch feature [" & feat.Name & "] type=[" & typeName & "]"
        If BlankSketchFeatureBySelection(feat) Then
            hiddenCount = hiddenCount + 1
        Else
            Debug.Print TimeStamp() & " | WARN  | Could not blank sketch feature [" & feat.Name & "]"
        End If
    End If

    Dim subFeat As SldWorks.Feature
    Set subFeat = feat.GetFirstSubFeature

    Do While Not subFeat Is Nothing
        HideSketchFeatureRecursive subFeat, hiddenCount
        Set subFeat = subFeat.GetNextSubFeature
    Loop

    Exit Sub

EH:
    Debug.Print TimeStamp() & " | ERROR | HideSketchFeatureRecursive(" & feat.Name & "): " & Err.Number & " - " & Err.Description
End Sub

Private Function IsSketchFeatureType(ByVal typeName As String) As Boolean
    Dim t As String
    t = UCase$(Trim$(typeName))

    Select Case t
        Case "PROFILEFEATURE", "SKETCH", "3DSKETCH", "3DSKETCHPROFILE", "DERIVEDSKETCH"
            IsSketchFeatureType = True
        Case Else
            IsSketchFeatureType = False
    End Select
End Function

Private Function BlankSketchFeatureBySelection(ByVal feat As SldWorks.Feature) As Boolean
    On Error GoTo EH

    BlankSketchFeatureBySelection = False

    If feat Is Nothing Then Exit Function
    If swApp.ActiveDoc Is Nothing Then Exit Function

    swApp.ActiveDoc.ClearSelection2 True

    If Not feat.Select2(False, -1) Then
        Debug.Print TimeStamp() & " | WARN  | Select2 failed while trying to blank sketch [" & feat.Name & "]"
        Exit Function
    End If

    swApp.ActiveDoc.BlankSketch
    swApp.ActiveDoc.ClearSelection2 True
    BlankSketchFeatureBySelection = True
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | BlankSketchFeatureBySelection(" & feat.Name & "): " & Err.Number & " - " & Err.Description
End Function

Private Function GetLocalTempRoot() As String
    On Error GoTo EH

    Dim baseTemp As String
    baseTemp = Trim$(Environ$("TEMP"))
    If Len(baseTemp) = 0 Then baseTemp = Trim$(Environ$("TMP"))
    If Len(baseTemp) = 0 Then baseTemp = "C:\Temp"

    Dim root As String
    root = baseTemp & "\" & TEMP_PREFIX & SafeNowStamp()

    GetLocalTempRoot = EnsureFolderExists(root)
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetLocalTempRoot: " & Err.Number & " - " & Err.Description
    GetLocalTempRoot = ""
End Function

'=========================================================================================
' FILE / PATH HELPERS
'=========================================================================================
Private Function EnsureFolderExists(ByVal folderPath As String) As String
    On Error GoTo EH

    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")

    If Not fso.FolderExists(folderPath) Then
        fso.CreateFolder folderPath
    End If

    If fso.FolderExists(folderPath) Then
        EnsureFolderExists = folderPath
    Else
        EnsureFolderExists = ""
    End If
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | EnsureFolderExists(" & folderPath & "): " & Err.Number & " - " & Err.Description
    EnsureFolderExists = ""
End Function

Private Function GetFolderFromPath(ByVal fullPath As String) As String
    Dim p As Long
    p = InStrRev(fullPath, "\")
    If p > 0 Then
        GetFolderFromPath = Left$(fullPath, p - 1)
    Else
        GetFolderFromPath = ""
    End If
End Function

Private Function GetUniqueOutputPath(ByVal folderPath As String, ByVal baseFileNameNoExt As String, ByVal extNoDot As String) As String
    On Error GoTo EH

    Dim candidate As String
    Dim i As Long

    candidate = folderPath & "\" & baseFileNameNoExt & "." & extNoDot
    If Not FileExists(candidate) Then
        GetUniqueOutputPath = candidate
        Exit Function
    End If

    For i = 1 To 9999
        candidate = folderPath & "\" & baseFileNameNoExt & "_" & Format$(i, "00") & "." & extNoDot
        If Not FileExists(candidate) Then
            GetUniqueOutputPath = candidate
            Exit Function
        End If
    Next i

    GetUniqueOutputPath = folderPath & "\" & baseFileNameNoExt & "_" & SafeNowStamp() & "." & extNoDot
    Exit Function

EH:
    Debug.Print TimeStamp() & " | ERROR | GetUniqueOutputPath: " & Err.Number & " - " & Err.Description
End Function


' Lightweight compatibility wrapper for SAVE_ALL orientation routines.
' AUTO DXF SAVE keeps its existing Immediate-window logging behavior.
Private Sub LogEvent(ByVal messageText As String)
    On Error Resume Next
    Debug.Print TimeStamp() & messageText
End Sub

Private Function FileExists(ByVal filePath As String) As Boolean
    On Error Resume Next
    FileExists = (Len(Dir$(filePath, vbNormal)) > 0)
End Function

Private Sub DeleteFileIfExists(ByVal filePath As String)
    On Error Resume Next
    If Len(filePath) > 0 Then
        If FileExists(filePath) Then Kill filePath
    End If
End Sub

Private Sub DeleteFolderIfEmpty(ByVal folderPath As String)
    On Error Resume Next
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    If fso.FolderExists(folderPath) Then
        If fso.GetFolder(folderPath).Files.Count = 0 And fso.GetFolder(folderPath).SubFolders.Count = 0 Then
            fso.DeleteFolder folderPath, True
        End If
    End If
End Sub

Private Sub CloseDocIfOpen(ByVal filePath As String)
    On Error Resume Next
    If Len(filePath) = 0 Then Exit Sub

    Dim openDoc As SldWorks.ModelDoc2
    Set openDoc = swApp.GetOpenDocumentByName(filePath)
    If Not openDoc Is Nothing Then
        swApp.CloseDoc openDoc.GetTitle
        Exit Sub
    End If

    swApp.CloseDoc GetFileNameFromPath(filePath)
End Sub

Private Function GetFileNameFromPath(ByVal filePath As String) As String
    Dim p As Long
    p = InStrRev(filePath, "\")
    If p > 0 Then
        GetFileNameFromPath = Mid$(filePath, p + 1)
    Else
        GetFileNameFromPath = filePath
    End If
End Function

Private Function GetFileStemFromPath(ByVal filePath As String) As String
    Dim fileNameOnly As String
    Dim p As Long

    fileNameOnly = GetFileNameFromPath(filePath)
    p = InStrRev(fileNameOnly, ".")

    If p > 1 Then
        GetFileStemFromPath = Left$(fileNameOnly, p - 1)
    Else
        GetFileStemFromPath = fileNameOnly
    End If
End Function


Private Function SanitizeFileName(ByVal s As String) As String
    Dim badChars As Variant
    Dim i As Long

    s = Trim$(s)
    badChars = Array("\", "/", ":", "*", "?", """", "<", ">", "|")

    For i = LBound(badChars) To UBound(badChars)
        s = Replace$(s, badChars(i), "_")
    Next i

    Do While InStr(s, "__") > 0
        s = Replace$(s, "__", "_")
    Loop

    s = Trim$(s)
    s = TrimDotsAndSpaces(s)

    SanitizeFileName = s
End Function

Private Function TrimDotsAndSpaces(ByVal s As String) As String
    Do While Len(s) > 0 And (Right$(s, 1) = "." Or Right$(s, 1) = " ")
        s = Left$(s, Len(s) - 1)
    Loop
    Do While Len(s) > 0 And (Left$(s, 1) = "." Or Left$(s, 1) = " ")
        s = Mid$(s, 2)
    Loop
    TrimDotsAndSpaces = s
End Function

'=========================================================================================
' VECTOR MATH
'=========================================================================================
Private Function VecLength(ByRef v() As Double) As Double
    VecLength = Sqr(v(0) * v(0) + v(1) * v(1) + v(2) * v(2))
End Function

Private Sub NormalizeVec(ByRef v() As Double)
    Dim L As Double
    L = VecLength(v)
    If L > EPS Then
        v(0) = v(0) / L
        v(1) = v(1) / L
        v(2) = v(2) / L
    End If
End Sub

Private Function DotProduct(ByRef a() As Double, ByRef b() As Double) As Double
    DotProduct = a(0) * b(0) + a(1) * b(1) + a(2) * b(2)
End Function

Private Sub CrossProduct(ByRef a() As Double, ByRef b() As Double, ByRef outV() As Double)
    outV(0) = a(1) * b(2) - a(2) * b(1)
    outV(1) = a(2) * b(0) - a(0) * b(2)
    outV(2) = a(0) * b(1) - a(1) * b(0)
End Sub

Private Sub ProjectVectorOntoPlane(ByRef v() As Double, ByRef n() As Double, ByRef outV() As Double)
    Dim d As Double
    d = DotProduct(v, n)
    outV(0) = v(0) - d * n(0)
    outV(1) = v(1) - d * n(1)
    outV(2) = v(2) - d * n(2)
End Sub

Private Sub StabilizeVectorSign(ByRef v() As Double)
    If Abs(v(0)) > EPS Then
        If v(0) < 0# Then FlipVec v
    ElseIf Abs(v(1)) > EPS Then
        If v(1) < 0# Then FlipVec v
    ElseIf Abs(v(2)) > EPS Then
        If v(2) < 0# Then FlipVec v
    End If
End Sub

Private Sub FlipVec(ByRef v() As Double)
    v(0) = -v(0)
    v(1) = -v(1)
    v(2) = -v(2)
End Sub

Private Function CompareVectorLex(ByRef a() As Double, ByRef b() As Double) As Long
    If Abs(a(0) - b(0)) > EPS Then
        CompareVectorLex = Sgn(a(0) - b(0))
        Exit Function
    End If
    If Abs(a(1) - b(1)) > EPS Then
        CompareVectorLex = Sgn(a(1) - b(1))
        Exit Function
    End If
    If Abs(a(2) - b(2)) > EPS Then
        CompareVectorLex = Sgn(a(2) - b(2))
        Exit Function
    End If
    CompareVectorLex = 0
End Function

Private Function Distance3(ByRef p0() As Double, ByRef p1() As Double) As Double
    Distance3 = Sqr((p1(0) - p0(0)) ^ 2 + (p1(1) - p0(1)) ^ 2 + (p1(2) - p0(2)) ^ 2)
End Function

Private Function Dbl3ToStr(ByRef v() As Double) As String
    Dbl3ToStr = FormatNumber(v(0), 8) & ", " & FormatNumber(v(1), 8) & ", " & FormatNumber(v(2), 8)
End Function

Private Function Atn2(ByVal y As Double, ByVal x As Double) As Double
    If Abs(x) < EPS Then
        If y > 0# Then
            Atn2 = PI_VAL / 2#
        ElseIf y < 0# Then
            Atn2 = -PI_VAL / 2#
        Else
            Atn2 = 0#
        End If
    ElseIf x > 0# Then
        Atn2 = Atn(y / x)
    ElseIf x < 0# Then
        If y >= 0# Then
            Atn2 = Atn(y / x) + PI_VAL
        Else
            Atn2 = Atn(y / x) - PI_VAL
        End If
    End If
End Function

Private Function RadToDeg(ByVal rad As Double) As Double
    RadToDeg = rad * 180# / PI_VAL
End Function

'=========================================================================================
' STRING / LOG HELPERS
'=========================================================================================
Private Function NzStr(ByVal s As String) As String
    NzStr = Trim$(s & "")
End Function

Private Function TimeStamp() As String
    TimeStamp = Format$(Now, "yyyy-mm-dd hh:nn:ss")
End Function

Private Function SafeNowStamp() As String
    SafeNowStamp = Format$(Now, "yyyymmdd_hhnnss")
End Function
Procedure index · 166 declarations
File checksum

SHA-256: 73188fcc4679705f67f83da25f44b4ab33da2095d87e84b386d31550bcba731f