Best Linear Cut Optimizers

Best Linear Cut Optimizers

petestrycharske
Advisor Advisor
7,521 Views
9 Replies
Message 1 of 10

Best Linear Cut Optimizers

petestrycharske
Advisor
Advisor

All,

 

Good morning!  I was recently asked by a client what the best linear cut optimizers are out there for Inventor.  I didn't see anything in the Inventor App Store, so I some digging and found a couple of online calculators and a couple of Excel based options.  However, it dawned on me that I should reach out to the community to see what everyone else has / is using.  If you could please provide links to the optimizers below, I'd love to evaluate them.  If you have any questions, please do not hesitate to contact me.  Below is a list that I've at least taken a cursory look at:

 

https://smartcut.pro/

 

https://www.cutoptimizeronline.com/

 

https://www.optimalon.com/length_cutting_excel.htm

 

https://metalopt.com/free_optimizer.html

 

Thanks in advance for any thoughts!  Hope all is well and have a most blessed day!

 

Peace,

Pete

Just a guy on a couch...

Please give a kudos if helpful and mark as a solution if somehow I got it right.
7,522 Views
9 Replies
Replies (9)
Message 2 of 10

petestrycharske
Advisor
Advisor

Oops, I meant to ask for others to provide links.  I merely wanted to list the ones that I'd already looked at to see if others had any feedback on them.  Sorry for any confusion.

Just a guy on a couch...

Please give a kudos if helpful and mark as a solution if somehow I got it right.
0 Likes
Message 3 of 10

johnsonshiue
Community Manager
Community Manager

Hi Pete,

 

I am sorry that I don't have much to offer here since I am ignorant of "Linear Cut Optimizer." I am not aware of an Autodesk solution. I think what you have found is much more information than I can offer.

There is a trick I use for inquiries like this. I usually search for a solution provided for our competitors. Sometimes, the same solution might be available to Inventor also. For example, there are some online viewers and robotic analysis tools. Please share what you find.

Merry Christmas and Happy New Year!

Many thanks!



Johnson Shiue ([email protected])
Software Test Engineer
0 Likes
Message 4 of 10

Anonymous
Not applicable

For a single set of lengths to optimize the solutions are relatively narrow and limited to

the best combination that can be fit within a stock length to cut from.

However if the need is for multiple sets not all known at one time, now that's where there

is no absolute best as strategies come in to play. As with poker, odds and choice strategies.

I have extensive experience in this area, over 30 years and many thousands of optimizations.

Anyone with questions may feel free to contact me about some of these techniques

 

 

 

0 Likes
Message 5 of 10

Anonymous
Not applicable

Hey Pete,

Another thought, would you be able to create a nesting template for bar stock(or whatever you/client is using) and use that?

Message 6 of 10

paulZKN98
Advocate
Advocate

@petestrycharske Did you have any success with this search?  This would be HUGE for us, and I'm surprised that there aren't any options in the app store.  We are always generating cut lists from our BOM and manually determining how many sticks of metal would be required for ordering / cutting processes in the shop.  

 

@Anonymous Could you elaborate on what tools you could use for this?  

 

Thanks!

Paul

0 Likes
Message 7 of 10

swalton
Mentor
Mentor

I recently used Inventor Nesting to solve this problem for rubber strips.  It is part of the PDMC subscription, but a separate install.

 

I followed the AU class here: https://www.autodesk.com/autodesk-university/class/Inventor-Nesting-Isnt-Just-Sheet-Metal-2020

 

Worked fine for my needs.

 

Steve Walton
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Inventor 2025
Vault Professional 2025
Message 8 of 10

paulZKN98
Advocate
Advocate
Wow, I've played around with Inventor Nesting but thought it was only for Sheetmetal. This is big! Thankyou!
0 Likes
Message 9 of 10

mik_korepanov
Explorer
Explorer

Hello! I’ve been using smartcut.pro for a while — it provides decent results.

 

Recently, I started working on my own solution. It’s still in beta, but in my tests it already delivers very competitive (and sometimes better) results compared to other tools.

I would really appreciate it if you could try it out and share your feedback:

 

https://cut1d.xyz/

 

Benchmark setup

  • Stock length: 1250 (unlimited quantity)

Test Case 1 – Details

Length Quantity
25035
46053
620

Results (Test Case 1)

Tool                   Bars  Max Waste     Time
smartcut.pro3210005s
metalopt327503s
cut1d3210001s

Test Case 2 – Details

Length Quantity
25035
6206
46053
120020
5020

Results (Test Case 2)

Tool                   Bars   Max Waste    Time
smartcut.pro577905s
metalopt527503s
cut1d5210001s

These are simple test cases, but they already show promising performance.

Thanks in advance for your time — any feedback is highly appreciated!

0 Likes
Message 10 of 10

mgrenier2
Collaborator
Collaborator

It's still very much a work in progress but I'm trying to build one with iLogic

 

Option Explicit

Sub Main()
    Dim app As Inventor.Application = ThisApplication
    Dim tg As TransientGeometry = app.TransientGeometry
    Dim srcAsm As AssemblyDocument = app.ActiveDocument
	Dim basePath As String
	basePath = Left(srcAsm.FullFileName, InStrRev(srcAsm.FullFileName, "\"))

    ' ---------------- Paramètres ----------------
    Dim kerfMM As Double: kerfMM = 3.175          ' 1/8"
    Dim stockLenMM As Double: stockLenMM = 7315.2 ' 288"
    Dim gabaritPath As String
    gabaritPath = "C:\Vault WS\Designs\DIVERS\Mathieu G\Tests iLogic\OptiCutter\OptiCutter-Template.iam"

    ' ---------------- Préparer dictionnaire familles ----------------
    Dim families As New Dictionary(Of String, List(Of Object()))
    Dim keywords() As String: keywords = Split("POUTRE|CORNIÈRE|TUBE|TUYAU|ACIER PLAT|ACIER ROND|HSS", "|")

    ' Collecter récursivement
    Dim occ As ComponentOccurrence
    For Each occ In srcAsm.ComponentDefinition.Occurrences
        CollectParts(occ, families, keywords)
    Next

    If families.Count = 0 Then
        MessageBox.Show("Aucun profilé détecté.", "OptiCutter")
        Exit Sub
    End If

    ' ---------------- FFD + génération ----------------
    Dim fKey As String
    For Each fKey In families.Keys
        Dim parts As List(Of Object())
        parts = families(fKey)
        SortByLengthDesc(parts)

        ' Optimisation: First-Fit Decreasing
        Dim bars As New List(Of List(Of Object()))
        Dim p As Object()
        For Each p In parts
            Dim L As Double: L = CDbl(p(1))
            Dim placed As Boolean: placed = False

            Dim b As List(Of Object())
            For Each b In bars
                Dim used As Double: used = SumLengths(b) + KerfTotal(b.Count, kerfMM)
                Dim extraKerf As Double: extraKerf = IIf(b.Count > 0, kerfMM, 0)
                If used + extraKerf + L <= stockLenMM Then
                    b.Add(p)
                    placed = True
                    Exit For
                End If
            Next
            If Not placed Then
                Dim nb As New List(Of Object())
                nb.Add(p)
                bars.Add(nb)
            End If
        Next

        ' Générer un assemblage par barre
        Dim barIdx As Integer: barIdx = 1
        Dim b2 As List(Of Object())
        For Each b2 In bars
            If Not System.IO.File.Exists(gabaritPath) Then
                MessageBox.Show("Gabarit introuvable: " & gabaritPath, "OptiCutter")
                Exit Sub
            End If

            Dim newAsm As AssemblyDocument
            newAsm = app.Documents.Open(gabaritPath, True)
            newAsm.DisplayName = "PlanCoupe_" & CleanName(fKey) & "_Barre" & barIdx
            Dim compDef As AssemblyComponentDefinition = newAsm.ComponentDefinition

            ' Plans assemblage (mapping)
            Dim asmXY As WorkPlane, asmYZ As WorkPlane, asmXZ As WorkPlane
            asmXY = compDef.WorkPlanes.Item(3)
            asmYZ = compDef.WorkPlanes.Item(1)
            asmXZ = compDef.WorkPlanes.Item(2)

            Dim offsetMM As Double: offsetMM = 0
            Dim first As Boolean: first = True

            Dim q As Object()
            For Each q In b2
                Dim path As String: path = CStr(q(0))
                Dim Lmm As Double: Lmm = CDbl(q(1))
                If Not System.IO.File.Exists(path) Then Continue For

                Dim occNew As ComponentOccurrence
                occNew = compDef.Occurrences.Add(path, tg.CreateMatrix())
                Dim pDef As PartComponentDefinition = TryCast(occNew.Definition, PartComponentDefinition)
                If pDef Is Nothing Then Continue For

                ' Plans pièce (mapping)
                Dim wpXY As WorkPlane, wpYZ As WorkPlane, wpXZ As WorkPlane
                wpXY = pDef.WorkPlanes.Item(3)
                wpYZ = pDef.WorkPlanes.Item(1)
                wpXZ = pDef.WorkPlanes.Item(2)

                ' Proxies
                Dim xyProxy As WorkPlaneProxy, yzProxy As WorkPlaneProxy, xzProxy As WorkPlaneProxy
                occNew.CreateGeometryProxy(wpXY, xyProxy)
                occNew.CreateGeometryProxy(wpYZ, yzProxy)
                occNew.CreateGeometryProxy(wpXZ, xzProxy)

                ' Contraintes
                compDef.Constraints.AddFlushConstraint(asmXZ, xzProxy, 0)
                compDef.Constraints.AddFlushConstraint(asmYZ, yzProxy, 0)
                Dim offCM As Double: offCM = IIf(first, 0, offsetMM / 10.0)
                compDef.Constraints.AddFlushConstraint(asmXY, xyProxy, offCM)
                first = False

                ' Avancer offset
                offsetMM += Lmm
                If Not IsLastInBar(b2, q) Then offsetMM += kerfMM
            Next

            ' Sauvegarder et fermer
            Dim savePath As String
			savePath = basePath & newAsm.DisplayName & ".iam"
            newAsm.SaveAs(savePath, False)
            'newAsm.Close(False)
            barIdx += 1
        Next
    Next

    MessageBox.Show("Optimisation terminée: barres générées par famille.", "OptiCutter")
End Sub

' ===== Helpers =====

Private Sub CollectParts(occ As ComponentOccurrence, ByRef families As Dictionary(Of String, List(Of Object())), ByVal keywords() As String)
    If TypeOf occ.Definition Is PartComponentDefinition Then
        Dim partDoc As Document = occ.Definition.Document
        Dim desc As String, dest As String
        desc = "" : dest = ""
        On Error Resume Next
        desc = CStr(iProperties.Value(occ.Name, "Project", "Description"))
        dest = CStr(iProperties.Value(occ.Name, "Custom", "Destination"))
        On Error GoTo 0

        Dim keep As Boolean: keep = False
        If desc <> "" Then
            Dim up As String: up = UCase(desc)
            Dim k As Integer
            For k = LBound(keywords) To UBound(keywords)
                If InStr(up, keywords(k)) > 0 Then keep = True : Exit For
            Next
        End If
        If LCase(dest) = "scie" Then keep = True

        If keep And desc <> "" Then
            Dim Lmm As Double: Lmm = 0
            On Error Resume Next
            Lmm = CDbl(partDoc.ComponentDefinition.Parameters.UserParameters.Item("Longueur").Value) * 10
            If Err.Number <> 0 Then
                Err.Clear()
                Lmm = CDbl(partDoc.ComponentDefinition.Parameters.UserParameters.Item("G_L").Value) * 10
            End If
            On Error GoTo 0

            If Lmm > 0 Then
                Dim famKey As String: famKey = Trim(UCase(desc))
                If Not families.ContainsKey(famKey) Then families.Add(famKey, New List(Of Object()))
                families(famKey).Add(New Object(){partDoc.FullFileName, Lmm})
            End If
        End If
    ElseIf TypeOf occ.Definition Is AssemblyComponentDefinition Then
        Dim subOcc As ComponentOccurrence
        For Each subOcc In occ.SubOccurrences
            CollectParts(subOcc, families, keywords)
        Next
    End If
End Sub

Private Sub SortByLengthDesc(ByRef lst As List(Of Object()))
    Dim n As Integer: n = lst.Count
    Dim i As Integer, j As Integer
    For i = 0 To n - 2
        For j = i + 1 To n - 1
            If CDbl(lst(i)(1)) < CDbl(lst(j)(1)) Then
                Dim tmp As Object(): tmp = lst(i)
                lst(i) = lst(j)
                lst(j) = tmp
            End If
        Next
    Next
End Sub

Private Function SumLengths(lst As List(Of Object())) As Double
    Dim s As Double: s = 0
    Dim it As Object()
    For Each it In lst
        s = s + CDbl(it(1))
    Next
    SumLengths = s
End Function

Private Function KerfTotal(count As Integer, kerfMM As Double) As Double
    If count <= 1 Then
        KerfTotal = 0
    Else
        KerfTotal = (count - 1) * kerfMM
    End If
End Function

Private Function IsLastInBar(lst As List(Of Object()), item As Object()) As Boolean
    IsLastInBar = (Object.ReferenceEquals(lst(lst.Count - 1), item))
End Function

Private Function CleanName(s As String) As String
    ' Supprime caractères illégaux pour noms de fichiers
    Dim badChars As String: badChars = "\/:*?""<>|"
    Dim c As String
    For Each c In badChars
        s = Replace(s, c, "_")
    Next
    CleanName = s
End Function
0 Likes