iLogic: Setting Extra Layers In DXF Exports

iLogic: Setting Extra Layers In DXF Exports

Andrea_Garo_
Contributor Contributor
244 Views
2 Replies
Message 1 of 3

iLogic: Setting Extra Layers In DXF Exports

Andrea_Garo_
Contributor
Contributor

Hi everyone

 

Based on the iLogic rule described in @JelteDeJong  article

https://clintbrown.co.uk/2020/09/19/ilogic-setting-extra-layers-in-dxf-exports/
I would like to understand whether it is possible to extend its functionality to automatically assign an additional layer during DXF export.

More specifically, the goal would be to assign a dedicated layer to all concentric circles associated with Ø14 mm holes, where these circles represent the countersink.

The idea is to avoid manual edge selection and instead rely on automatic geometry recognition (Ø14 hole + countersink), so that all countersink circles are exported to the DXF on a specific layer.

Has anyone already implemented a similar solution using iLogic or the Inventor API?
Any suggestions or references would be greatly appreciated.

0 Likes
245 Views
2 Replies
Replies (2)
Message 2 of 3

aurel_e
Collaborator
Collaborator

Try this:

Option Explicit On
Option Infer Off
Imports System.Collections.Generic
Imports System.Text

Public Class ThisRule

    Private setName As String = "FlatPatternAttributes"
    Private attName As String = "LayerName"
    Private defaultLayerName As String = "CSK"

    Private tolerance As Double = 0.05 ' cm tolerance

    Public Sub Main()

        Dim doc As PartDocument = ThisDoc.Document

        If Not TypeOf doc.ComponentDefinition Is SheetMetalComponentDefinition Then
            MsgBox("This rule only works with sheet metal parts.", vbExclamation, "Error")
            Return
        End If

        Dim comDef As SheetMetalComponentDefinition = doc.ComponentDefinition

        '---------------------------------------------------------
        ' 1️⃣ Prompt for hole diameter (default 14 mm)
        '---------------------------------------------------------
        Dim inputDia As String = InputBox("Enter diameter of the small hole (mm):", "Hole Diameter", "14")
        Dim targetHoleDiameter As Double
        If Not Double.TryParse(inputDia, targetHoleDiameter) Then
            MsgBox("Invalid input. Using default 14mm.", vbExclamation)
            targetHoleDiameter = 14
        End If
        targetHoleDiameter = targetHoleDiameter / 10 ' convert mm to cm

        '---------------------------------------------------------
        ' 2️⃣ Flat pattern check / silent creation
        '---------------------------------------------------------
        If Not comDef.HasFlatPattern Then
            Try
                comDef.Unfold()
            Catch ex As Exception
                MsgBox("Failed to create flat pattern.", vbExclamation, "Error")
                Return
            End Try
        End If

        Try
            comDef.FlatPattern.Edit()
        Catch
        End Try

        '---------------------------------------------------------
        ' 3️⃣ Collect circular edges
        '---------------------------------------------------------
        Dim allCircularEdges As List(Of Edge) = GetAllCircularEdges(doc)
        If allCircularEdges.Count = 0 Then
            MsgBox("No circular edges found in the flat pattern.", vbExclamation, "No Geometry Found")
            comDef.FlatPattern.ExitEdit()
            Return
        End If

        '---------------------------------------------------------
        ' 4️⃣ Detect countersinks
        '---------------------------------------------------------
        Dim smallEdges As List(Of Edge) = FindSmallEdgesByConcentricGroups(allCircularEdges, targetHoleDiameter)

        If smallEdges.Count = 0 Then
            MsgBox("No small holes found with diameter ~" & targetHoleDiameter * 10 & " mm.", vbExclamation)
            comDef.FlatPattern.ExitEdit()
            Return
        End If

        '---------------------------------------------------------
        ' 5️⃣ Assign CSK layer only to the small edges
        '---------------------------------------------------------
        AssignLayerAttributes(smallEdges, defaultLayerName)

        '---------------------------------------------------------
        ' 6️⃣ Export DXF with CSK green
        '---------------------------------------------------------
        ExportFlatPatternDXF(comDef, defaultLayerName)

        '---------------------------------------------------------
        ' 7️⃣ Highlight for verification
        '---------------------------------------------------------
        HighlightEdges(smallEdges)
        ShowSummary(smallEdges.Count, defaultLayerName)

        comDef.FlatPattern.ExitEdit()

    End Sub

    '=========================================================
    ' Find only the smallest edge at each concentric group
    '=========================================================
    Private Function FindSmallEdgesByConcentricGroups(allEdges As List(Of Edge), targetHoleDiameter As Double) As List(Of Edge)
        Dim smallEdges As New List(Of Edge)
        Dim edgesByCenter As Dictionary(Of String, List(Of Edge)) = GroupEdgesByCenter(allEdges)

        For Each groupEdges As List(Of Edge) In edgesByCenter.Values
            If groupEdges.Count < 1 Then Continue For

            Dim sortedEdges As List(Of Edge) = SortEdgesByDiameter(groupEdges)
            Dim smallestCirc As Circle = TryCast(sortedEdges(0).Geometry, Circle)
            If smallestCirc Is Nothing Then Continue For

            Dim diameter As Double = smallestCirc.Radius * 2
            If Math.Abs(diameter - targetHoleDiameter) <= tolerance Then
                smallEdges.Add(sortedEdges(0)) ' only the smallest edge
            End If
        Next

        Return smallEdges
    End Function

    '=========================================================
    ' Helpers: Group / Sort / Geometry
    '=========================================================
    Private Function GroupEdgesByCenter(edges As List(Of Edge)) As Dictionary(Of String, List(Of Edge))
        Dim dict As New Dictionary(Of String, List(Of Edge))
        For Each e As Edge In edges
            Dim c As Circle = TryCast(E.Geometry, Circle)
            If c Is Nothing Then Continue For
            Dim key As String = Math.Round(c.Center.X, 4) & "," & Math.Round(c.Center.Y, 4) & "," & Math.Round(c.Center.Z, 4)
            If Not dict.ContainsKey(key) Then dict.Add(key, New List(Of Edge))
            dict(key).Add(E)
        Next
        Return dict
    End Function

    Private Function SortEdgesByDiameter(edges As List(Of Edge)) As List(Of Edge)
        Dim tmp As New List(Of Tuple(Of Edge, Double))
        For Each e As Edge In edges
            Dim c As Circle = TryCast(E.Geometry, Circle)
            If c IsNot Nothing Then tmp.Add(Tuple.Create(E, c.Radius * 2))
        Next
        tmp.Sort(Function(a, b) a.Item2.CompareTo(b.Item2))
        Dim result As New List(Of Edge)
        For Each t As Tuple(Of Edge, Double) In tmp
            result.Add(t.Item1)
        Next
        Return result
    End Function

    Private Function GetAllCircularEdges(doc As PartDocument) As List(Of Edge)
        Dim result As New List(Of Edge)
        Dim fp As FlatPattern = doc.ComponentDefinition.FlatPattern
        If fp.Body Is Nothing Then Return result
        For Each f As Face In fp.Body.Faces
            For Each e As Edge In f.Edges
                If TypeOf E.Geometry Is Circle Then result.Add(E)
            Next
        Next
        Return result
    End Function

    '=========================================================
    ' Assign layer
    '=========================================================
    Private Sub AssignLayerAttributes(edges As List(Of Edge), layerName As String)
        For Each e As Edge In edges
            Dim aSet As AttributeSet
            If E.AttributeSets.NameIsUsed(setName) Then
                aSet = E.AttributeSets.Item(setName)
            Else
                aSet = E.AttributeSets.Add(setName)
            End If
            If aSet.NameIsUsed(attName) Then
                aSet.Item(attName).Value = layerName
            Else
                aSet.Add(attName, ValueTypeEnum.kStringType, layerName)
            End If
        Next
    End Sub

    '=========================================================
    ' Export DXF
    '=========================================================
    Private Sub ExportFlatPatternDXF(comDef As SheetMetalComponentDefinition, layerName As String)
        Dim sOut As String = "FLAT PATTERN DXF?AcadVersion=2004"
        sOut &= "&InvisibleLayers=IV_TANGENT;IV_FEATURE_PROFILES;IV_ARC_CENTERS;IV_TOOL_CENTER;IV_TOOL_CENTER_DOWN;IV_FEATURE_PROFILES_DOWN"
        sOut &= "&UnconsumedSketchesLayer=" & layerName
        sOut &= "&UnconsumedSketchesLayerColor=0;255;0" ' green RGB
        sOut &= "?OFILE"
        Dim path As String = ThisDoc.Path
        Dim name As String = ThisDoc.Document.DisplayName.Replace(".ipt", "")
        Dim filename As String = path & "\" & name & ".dxf"
        Try
            comDef.DataIO.WriteDataToFile(sOut, filename)
        Catch ex As Exception
            MsgBox("DXF export failed: " & ex.Message, vbExclamation, "Error")
        End Try
    End Sub

    '=========================================================
    ' Highlight edges
    '=========================================================
    Private Sub HighlightEdges(edges As List(Of Edge))
        Dim doc As PartDocument = ThisDoc.Document
        For i As Integer = doc.HighlightSets.Count To 1 Step -1
            doc.HighlightSets.Item(i).Delete()
        Next
        If edges.Count = 0 Then Return
        Dim hs As HighlightSet = doc.HighlightSets.Add()
        hs.Color = ThisApplication.TransientObjects.CreateColor(0, 255, 0)
        Dim col As ObjectCollection = ThisApplication.TransientObjects.CreateObjectCollection()
        For Each e As Edge In edges
            col.Add(E)
        Next
        hs.AddMultipleItems(col)
    End Sub

    '=========================================================
    ' Show summary
    '=========================================================
    Private Sub ShowSummary(count As Integer, layerName As String)
        MsgBox(count & " holes assigned to layer '" & layerName &
               "' and exported to DXF.", vbInformation, "Complete")
    End Sub

End Class
0 Likes
Message 3 of 3

Andrea_Garo_
Contributor
Contributor

The iLogic code correctly identifies groups of concentric circular edges in the flat pattern of a sheet metal part.

At the moment, however, the custom layer is assigned to the inner (smallest) circle of each group.

What I am trying to achieve is the following: for each group of concentric circles, the smallest circle should be used only as a reference to identify the hole, while the custom layer must be applied exclusively to the outermost circle (outer profile / countersink).

In other words, the detection logic is correct, but the layer should be applied to the outer circle rather than the inner one, so that the result is correctly reflected in the DXF exported from the flat pattern.

0 Likes