Part Smarter, not harder.

One way to simplify the process of using parts in inventor is to make a master part file that's driven by parameters and then create a rule in ilogic to save all of your info for each configured variant of that part into the .ipt file, swapping them out when the params change. I've been doing this with Json into a custom AttributeSet, and it seems to work pretty awesome. I've got these .ipt's I call smartparts, and what I do is I make a class that holds a bunch of data to drive the parameters of the model file. i just serialize and deserialize from there. So, for instance, for a pipe you could write this in a rule:
Sub main
  Dim PipeList As List(Of Pipe) = New List(Of Pipe)
  Dim SchList As List(Of ScheduleTableValues) = New List(Of ScheduleTableValues)
  Dim JSeri As JavaScriptSerializer = New JavaScriptSerializer
  AttName = "JSON"
  Dim ThisPartDocument As PartDocument = ThisApplication.Documents.ItemByName(ThisDoc.Document.FullDocumentName)
  Dim Attset As AttributeSet

  Try'[

    SchList = initScheduleList(SchList)
  Catch
    Logger.Error("{0} couldn't be made for some reason.. ", "SchList")
  End Try']

  Try'[
    Logger.Info("creating the PipeList")
    initializePipes(PipeList, SchList)
    Logger.Info("The number of objects in the PipeList after creating it is: {0}.", PipeList.Count)
  Catch Ex As Exception
    Logger.Info("The number of objects in the PipeList after creating it is: {0}.", PipeList.Count)
    '   Logger.Info("something went wrong, the Code is in it's Cach block after trying to Populate the Teelist {0}.", TeeList.Count)
    Logger.Info("Error {0}::{1}.", Ex.Message, Ex.HResult)
  End Try']

  SerializeToJSON(PipeList, AttName)

End Sub

<Serializable() >
Class Pipe


  Public _nps As String = ""
  Public _ptype As String = "PIPE"
  Public _mat As String = ""
  Public _sch As String = ""
  Public _pol As String = "MILL"
  Public _lcOrPed As String = ""
  Public _ptNum As String = ""
  Public _thickness As Double
  Public _schTableValue As ScheduleTableValues


  Public Sub New

  End Sub

  Public Sub New(Nps As String, Mat As String, Sch As String, Pol As String, LcOrPed As String, PtNum As String, Schlist As List(Of ScheduleTableValues))
    Me._nps = Nps
    Me._mat = Mat
    Me._sch = Sch
    Me._pol = Pol
    Me._lcOrPed = LcOrPed
    Me._ptNum = PtNum
    Me._schTableValue = (From Entry In Schlist Where entry._nominalPipeSize = CDblAny(Me._nps)).FirstOrDefault

    Select Case Me._sch
      Case "SCH05"
        Me._thickness = Me._schTableValue._sch05
      Case "SCH10"
        Me._thickness = Me._schTableValue._sch10
      Case "SCH20"
        Me._thickness = Me._schTableValue._sch20
      Case "SCH40"
        Me._thickness = Me._schTableValue._sch40
      Case "SCH80"
        Me._thickness = Me._schTableValue._sch80
      Case "SCH160"
        Me._thickness = Me._schTableValue._sch160
    End Select

  End Sub

End Class

<Serializable()>
Class ScheduleTableValues
  Public _nominalPipeSize As Double
  Public _od As Double
  Public _sch05 As Double
  Public _sch10 As Double
  Public _sch20 As Double
  Public _sch30 As Double
  Public _sch40 As Double
  Public _sch80 As Double
  Public _sch120 As Double
  Public _sch160 As Double

  Public Sub New(NominalPipeSize As Double, Od As Double, SCH05 As Double, SCH10 As Double, SCH20 As Double, SCH30 As Double, SCH40 As Double, SCH80 As Double, SCH120 As Double, SCH160 As Double)
    Me._nominalPipeSize = NominalPipeSize
    Me._od = Od
    Me._sch05 = SCH05
    Me._sch10 = SCH10
    Me._sch20 = SCH20
    Me._sch30 = SCH30
    Me._sch40 = SCH40
    Me._sch80 = SCH80
    Me._sch120 = SCH120
    Me._sch160 = SCH160
  End Sub
  Public Overrides Function ToString() As String
    Return String.Format("[NPS:{0}, OD:{1}]", Me._nominalPipeSize, Me._od)
  End Function
  Public Sub New
  End Sub
End Class

Function initScheduleList(ByRef SchList As List(Of ScheduleTableValues))

  SchList.Add(New ScheduleTableValues(0.125, 0.405, 0.035, 0.049, 0.049, 0.057, 0.068, 0.095, 0, 0))
  SchList.Add(New ScheduleTableValues(0.25, 0.54, 0.049, 0.065, 0.065, 0.073, 0.088, 0.119, 0, 0))
  SchList.Add(New ScheduleTableValues(0.375, 0.675, 0.049, 0.065, 0.065, 0.073, 0.091, 0.126, 0, 0))
  SchList.Add(New ScheduleTableValues(0.5, 0.84, 0.065, 0.083, 0.083, 0.095, 0.109, 0.147, 0, 0.188))
  SchList.Add(New ScheduleTableValues(0.75, 1.05, 0.065, 0.083, 0.083, 0.095, 0.113, 0.154, 0, 0.219))
  SchList.Add(New ScheduleTableValues(1, 1.315, 0.065, 0.109, 0.109, 0.114, 0.133, 0.179, 0, 0.25))
  SchList.Add(New ScheduleTableValues(1.25, 1.66, 0.065, 0.109, 0.109, 0.117, 0.14, 0.191, 0, 0.25))
  SchList.Add(New ScheduleTableValues(1.5, 1.9, 0.065, 0.109, 0.109, 0.125, 0.145, 0.2, 0, 0.281))
  SchList.Add(New ScheduleTableValues(2, 2.375, 0.065, 0.109, 0.109, 0.125, 0.154, 0.218, 0.25, 0.344))
  SchList.Add(New ScheduleTableValues(2.5, 2.875, 0.083, 0.12, 0.12, 0.188, 0.203, 0.276, 0.3, 0.375))
  SchList.Add(New ScheduleTableValues(3, 3.5, 0.083, 0.12, 0.12, 0.188, 0.216, 0.3, 0.35, 0.438))
  SchList.Add(New ScheduleTableValues(3.5, 4, 0.083, 0.12, 0.12, 0.188, 0.226, 0.318, 0, 0))
  SchList.Add(New ScheduleTableValues(4, 4.5, 0.083, 0.12, 0, 0.188, 0.237, 0.337, 0.437, 0.531))
  SchList.Add(New ScheduleTableValues(4.5, 5, 0, 0, 0, 0, 0.247, 0.355, 0, 0))
  SchList.Add(New ScheduleTableValues(5, 5.563, 0.109, 0.134, 0, 0, 0.258, 0.375, 0.5, 0.625))
  SchList.Add(New ScheduleTableValues(6, 6.625, 0.109, 0.134, 0, 0, 0.28, 0.432, 0.562, 0.719))
  SchList.Add(New ScheduleTableValues(7, 7.625, 0, 0, 0, 0, 0.301, 0.5, 0, 0))
  SchList.Add(New ScheduleTableValues(8, 8.625, 0.109, 0.148, 0, 0.277, 0.322, 0.5, 0.719, 0.906))
  SchList.Add(New ScheduleTableValues(9, 9.625, 0, 0, 0, 0, 0.342, 0.5, 0, 0))
  SchList.Add(New ScheduleTableValues(10, 10.75, 0.134, 0.165, 0.25, 0.307, 0.365, 0, 0, 0))
  SchList.Add(New ScheduleTableValues(12, 12.75, 0.156, 0.18, 0.25, 0.33, 0.375, 0, 0, 0))
  SchList.Add(New ScheduleTableValues(14, 14, 0.156, 0.25, 0.312, 0.375, 0.375, 0, 0, 0))
  SchList.Add(New ScheduleTableValues(16, 16, 0.165, 0.25, 0.312, 0.375, 0.375, 0, 0, 0))
  SchList.Add(New ScheduleTableValues(18, 18, 0.165, 0.25, 0.312, 0.437, 0.375, 0, 0, 0))
  SchList.Add(New ScheduleTableValues(20, 20, 0.188, 0.25, 0.375, 0.5, 0.375, 0, 0, 0))
  SchList.Add(New ScheduleTableValues(22, 22, 0.188, 0.25, 0.375, 0.5, 0.375, 0, 0, 0))
  SchList.Add(New ScheduleTableValues(24, 24, 0.218, 0.25, 0.375, 0.562, 0.375, 0, 0, 0))

  Return SchList

End Function

''' <summary>
''' This Serializes a variable passed in of basically anything that is serializable, then deposits it into
''' this part's attributes under the set called JSONSet, with the Attribute named by the passed in AttName
'''
''' provides minimal error checking to make sure the set exists and the AttName exists, and it creates them if not.
'''
''' this Depends upon "Imports System.Web.Script.Serialization" and "AddReference "System.Web.Extensions"" being in the header for JavaSciptSerializer
''' </summary>
''' <param name="X"></param>
''' <param name="AttName"></param>
Friend Sub SerializeToJSON(ByRef X, AttName)
  Dim JSeri As New JavaScriptSerializer
  Dim AttSet As AttributeSet
  Dim SerialString = JSeri.Serialize(X)
  Dim ThisPartDocument As PartDocument = ThisApplication.Documents.ItemByName(ThisDoc.Document.FullDocumentName)
  Try

    If ThisPartDocument.AttributeSets.NameIsUsed("JSONSet") Then
      AttSet = ThisDoc.Document.AttributeSets.Item("JSONSet")
    Else
      AttSet = ThisDoc.Document.AttributeSets.Add("JSONSet")

    End If
    'EXTREMELY important to add Inventor to Atribute, otherwise it's thinking its a general system object attribute that we don't want.
    Dim JSONATT As Inventor.Attribute
    If AttSet.NameIsUsed(AttName) Then
      JSONATT = AttSet.Item(AttName)
    Else
      JSONATT = AttSet.Add(AttName, ValueTypeEnum.kStringType, "ThisIsAPlaceHolder")
    End If

    JSONATT.Value = SerialString
  Catch

  End Try


End Sub

Sub initializePipes(ByRef PipeList As List(Of Pipe), ByRef SchList As List(Of ScheduleTableValues))

  PipeList.Add(New Pipe("0.25", "304LSS", "SCH40", "MILL", "", "PipePartNumberFromErpSoftware", SchList))
'add all of your part information here.

End Sub




after this I have another rule that is aware of the properties changing, and as they do, load in the deserialized info that best fits from the json


 

Sub Main
  Dim PipeList As List(Of Pipe) = New List(Of Pipe)
  Dim PipesToUse As List(Of Pipe) = New List(Of Pipe)
  PipeList = DeserializeJSON(PipeList)
  Logger.Info(String.Format(" {0} Has {1} Objects after the Deserialization", "PipeList", PipeList.Count))
  Dim NormalPipeList As List(Of Pipe) = (From This As Pipe In PipeList Where This._lcOrPed = "" Select this).ToList
  Logger.Info(String.Format(" {0} Has {1} Objects after the Deserialization", "NormalPipeList", NormalPipeList.Count))
  Dim LCPipeList As List(Of Pipe) = (From This As Pipe In PipeList Where This._lcOrPed = "LC" Select this).ToList
  Logger.Info(String.Format(" {0} Has {1} Objects after the Deserialization", "LCPipeList", LCPipeList.Count))
  Dim PEDPipeList As List(Of Pipe) = (From This As Pipe In PipeList Where This._lcOrPed = "PED" Select this).ToList
  Logger.Info(String.Format(" {0} Has {1} Objects after the Deserialization", "PEDPipeList", PEDPipeList.Count))

  If LotControl
    pipesToUse = LCPipeList
  End If

  If PEDMaterial
    PipesToUse = PEDPipeList
  End If

  If Not LotControl And Not PEDMaterial Then
    PipesToUse = NormalPipeList
  End If


  SetLists(PipesToUse)

End Sub

Sub SetLists(ByRef PipesToUse As List(Of Pipe))
  MultiValue.SetValueOptions(True)
  MultiValue.UpdateAfterChange = True
  Parameter.UpdateAfterChange = True

  Dim NpsList = (From This As Pipe In PipesToUse Where This._ptype = "PIPE" Select this._nps Distinct ).ToList
  MultiValue.List("NominalDia") = NpsList.ToArray
  Select Case NominalDia
    Case Else
      Logger.Info(String.Format(" {0} Has {1} choices", "NominalDia", NpsList.Count))
      RuleParametersOutput()
      InventorVb.DocumentUpdate()
  End Select

  Dim MatList As List(Of String) = (From This As Pipe In PipesToUse Where This._nps = Parameter("NominalDia") Select This._mat Distinct ).ToList
  MultiValue.List("MaterialChoice") = MatList.ToArray
  Select Case MaterialChoice
    Case Else
      Logger.Info(String.Format(" {0} Has {1} choices", "MaterialChoice", MatList.Count))
      RuleParametersOutput()
      InventorVb.DocumentUpdate
  End Select
Try
  Dim SchChoiceList As List(Of String) = (From This As Pipe In PipesToUse Where This._nps = Parameter("NominalDia") And This._mat = Parameter("MaterialChoice") And This._pol = Parameter("PolishChoice")Select This._sch Distinct ).ToList
MultiValue.List("Schedule") = SchChoiceList.ToArray
Logger.Info(String.Format(" {0} Has {1} choices", "SchChoiceList", SchChoiceList.Count))
Catch
  Dim SchChoiceList As List(Of String) = (From This As Pipe In PipesToUse Where This._nps = Parameter("NominalDia") Select This._sch Distinct ).ToList
  Logger.Info(String.Format(" {0} Has {1} choices", "SchChoiceList", SchChoiceList.Count))
MultiValue.List("Schedule") = SchChoiceList.ToArray
End Try


 
  Select Case Schedule
    Case Else
 
      RuleParametersOutput()
      InventorVb.DocumentUpdate
  End Select
 
    Dim PolishList As List(Of String) = (From This As Pipe In PipesToUse Where This._nps = Parameter("NominalDia") Select This._pol Distinct ).ToList
  MultiValue.List("PolishChoice") = PolishList.ToArray
  Select Case PolishChoice
    Case Else
      Logger.Info(String.Format(" {0} Has {1} choices", "PolishList", PolishList.Count))
      RuleParametersOutput()
      InventorVb.DocumentUpdate
  End Select
  Try
    Dim PartNumList As List(Of String) = (From This As Pipe In PipesToUse Where This._nps = Parameter("NominalDia") And This._mat = Parameter("MaterialChoice") And This._pol = Parameter("PolishChoice") And This._sch = Parameter("Schedule") Select This._ptNum  ).ToList
  MultiValue.List("PartNumber") = PartNumList.ToArray
        Logger.Info(String.Format(" {0} Has {1} choices", "PartNumList", PartNumList.Count))
  Catch
    Dim PartNumList As List(Of String) = (From This As Pipe In PipesToUse Where This._nps = Parameter("NominalDia") And This._mat = Parameter("MaterialChoice") And This._sch = Parameter("Schedule") Select This._ptNum  ).ToList
  MultiValue.List("PartNumber") = PartNumList.ToArray
        Logger.Info(String.Format(" {0} Has {1} choices", "PartNumList", PartNumList.Count))
End Try
  Select Case PartNumber
    Case Else
   
      RuleParametersOutput()
      InventorVb.DocumentUpdate
  End Select
  Dim DescriptionString As String = String.Format("{0} {1} {2} {3} {4}", "PIPE", Parameter("NominalDia"), Parameter("MaterialChoice"), Parameter("Schedule"), Parameter("PolishChoice"))
  Description = DescriptionString
  Try
  Thickness = (From This As Pipe In PipesToUse Where This._ptNum = Parameter("PartNumber") Select This._thickness ).FirstOrDefault
  Catch
  End Try
  Try
  OD = (From This As Pipe In PipesToUse Where This._ptNum = Parameter("PartNumber") Select This._schTableValue._od ).FirstOrDefault
  Catch
  End Try
End Sub

Function DeserializeJSON(ByRef PipeList As List(Of Pipe))
  Dim Doc As PartDocument = ThisDoc.Document
  Dim JSeri As JavaScriptSerializer = New JavaScriptSerializer
  Dim AttName As String = "JSON"
  Dim Attset As AttributeSet = Doc.AttributeSets.Item("JSONSet")
  'EXTREMELY Important, add Inventor to the Attribute here, so it knows its not a general system attribute.
  Dim JSONATT As Inventor.Attribute
  Dim deSerialString As String
  If Attset.NameIsUsed(AttName) Then
    JSONATT = Attset.Item(AttName)
  End If
  Try
    deSerialString = JSONATT.Value
    PipeList = JSeri.Deserialize(Of List(Of Pipe))(deSerialString)
  Catch ex As Exception
    Logger.Info("Ran into trouble when trying to deserialize.{0}{1}", vbCrLf, ex.Message)
  End Try
  Return PipeList
End Function

Class Pipe


  Public _nps As String = ""
  Public _ptype As String = "PIPE"
  Public _mat As String = ""
  Public _sch As String = ""
  Public _pol As String = "MILL"
  Public _lcOrPed As String = ""
  Public _ptNum As String = ""
  Public _thickness As Double
  Public _schTableValue As ScheduleTableValues


  Public Sub New

  End Sub

End Class

<Serializable() >
Class ScheduleTableValues
  Public _nominalPipeSize As Double
  Public _od As Double
  Public _sch05 As Double
  Public _sch10 As Double
  Public _sch20 As Double
  Public _sch30 As Double
  Public _sch40 As Double
  Public _sch80 As Double
  Public _sch120 As Double
  Public _sch160 As Double

 
  Public Overrides Function ToString() As String
    Return String.Format("[NPS:{0}, OD:{1}]", Me._nominalPipeSize, Me._od)
  End Function
  Public Sub New
  End Sub
End Class​


Mind you, this solution for things is a couple of years old, and Ive grown leaps and bounds past this since then, so there's a ton of things I'd do differently now, not the least of which is using an all purpose dll I write in a sane language like Fsharp as much as possible, and then calling out to it from ilogic where needed, if at all.
 
I'm doing a lot of redunant work, a lot of updating the document when I don't have to, and the ways I'm allocating and reallocating too much data with my lists is very noobish as well, I just didn't understand data as well as I do now.

Comments

Popular posts from this blog

Made2Manage Database writing using EFCore, or things I wish I knew before goring myself on the unicorn's horn.

Inventor Addins and Assembly Binding Redirect... Ew.

Hello World..