Can iLogic calculate the individual volumes of each solid in a multibody part file?
Also, I know I can use iLogic to give the extents of a sheet metal part, but can it do the same for a regular part file? (Length, Width, and height)
Solved! Go to Solution.
Solved by J-Camper. Go to Solution.
Solved by Michael.Navara. Go to Solution.
@chris,
Here is an example of what you are asking for:
Sub Main
Dim pDoc As PartDocument = TryCast(ThisApplication.ActiveDocument, PartDocument)
If IsNothing(pDoc) Then Logger.Debug("Not Run In Part Document") : Exit Sub
For Each sb As SurfaceBody In pDoc.ComponentDefinition.SurfaceBodies
If Not sb.IsSolid Then Continue For
Dim sbVolume As Double = sb.Volume(.0001)
Logger.Trace(String.Format("{0} = {1} cm^3",sb.Name, sbVolume))
Next
Call AlignedBoxSize(pDoc.ComponentDefinition.PreciseRangeBox)'Box aligned with origin
Call OrientedBoxSize(pDoc.ComponentDefinition.OrientedMinimumRangeBox)'Box allowed to rotate for tightest fit
End Sub
Sub AlignedBoxSize(aRangeBox As Box)
Dim xLength, yLength, zLength As Double
xLength = aRangeBox.MaxPoint.X - aRangeBox.MinPoint.X
yLength = aRangeBox.MaxPoint.Y - aRangeBox.MinPoint.Y
zLength = aRangeBox.MaxPoint.Z - aRangeBox.MinPoint.Z
Logger.Trace(String.Format("X: {0} cm, Y: {1} cm, Z: {2} cm",xLength, yLength, zLength))
End Sub
Sub OrientedBoxSize(anOrientedBox As OrientedBox)
Dim SizeOfBox As New List(Of Double)
SizeOfBox.Add(anOrientedBox.DirectionOne.Length)
SizeOfBox.Add(anOrientedBox.DirectionTwo.Length)
SizeOfBox.Add(anOrientedBox.DirectionThree.Length)
SizeOfBox.Sort()
Logger.Trace(String.Format("Min Length: {0} cm, Mid Length: {1} cm, Max Length: {2} cm",SizeOfBox.Item(0), SizeOfBox.Item(1), SizeOfBox.Item(2)))
End Sub
I don't think there is a simple extents property for normal parts, but you can get a range box or oriented range box, which are both shown in above iLogic.
When you have a value of volume, you can do whatever you want. You can write it to the parameter for example. Parameter with the name 'parVolume' must exists. If you set the parameter property Value, the value must be in database units. Then you can set the units of the parameter to inches and its value is converted automatically.
Dim pDoc As PartDocument = ThisDoc.Document
'...
Dim sbVolume As Double = 1 'sb.Volume(.0001)
'...
pDoc.ComponentDefinition.Parameters("parVolume").Value = sbVolume
Logger.Trace is one of several methods which write message to iLogic log window. Trace is the lowest level.
@Michael.Navara apologies for not understanding... firstly, in your above example, am I adding the code you wrote below the code that @J-Camper wrote? Second, how are you getting the in^3 as a unit type, I can't find that?
I know I'm missing something, I just don't entirely understand what @J-Camper wrote or what you added.
Units: If you want to use parameter, you must specify the units. If the parameter is calculated by expression (for example Area = Length * Width) you must specify appropriate units otherwise Inventor show an error. For example you can write in * in to the units field in parameter definition and this is automatically converted to in^2. The same works for volume.
Volume in parameter: You can use this modification for the code mentioned above. Only the part for volume remains.
Sub Main()
Dim pDoc As PartDocument = TryCast(ThisApplication.ActiveDocument, PartDocument)
If IsNothing(pDoc) Then Logger.Debug("Not Run In Part Document") : Exit Sub
For Each sb As SurfaceBody In pDoc.ComponentDefinition.SurfaceBodies
If Not sb.IsSolid Then Continue For
Dim sbVolume As Double = sb.Volume(0.0001)
Logger.Trace(String.Format("{0} = {1} cm^3", sb.Name, sbVolume))
Dim paramName As String = sb.Name & "_Volume"
Try
pDoc.ComponentDefinition.Parameters.UserParameters(paramName).Value = sbVolume
Catch ex As Exception
pDoc.ComponentDefinition.Parameters.UserParameters.AddByValue(paramName, sbVolume, "in^3")
End Try
Next
'Call AlignedBoxSize(pDoc.ComponentDefinition.PreciseRangeBox)'Box aligned with origin
'Call OrientedBoxSize(pDoc.ComponentDefinition.OrientedMinimumRangeBox)'Box allowed to rotate for tightest fit
End Sub
@chris,
The "Logger.Trace" is a way to write a message in the iLogic Logger. I prefer this over messageboxes for testing as you do not have to clear each messagebox, but it will still give you a look at each step. In order to use it, you need to set log level to trace and have the iLogic Log window open:
Then For changing units you will need to do your own unit conversion for volume as the conversions from UnitsOfMeasure will not work for compound units. I added the conversions to the rule I posted before:
Sub Main
Dim pDoc As PartDocument = TryCast(ThisApplication.ActiveDocument, PartDocument)
If IsNothing(pDoc) Then Logger.Debug("Not Run In Part Document") : Exit Sub
For Each sb As SurfaceBody In pDoc.ComponentDefinition.SurfaceBodies
If Not sb.IsSolid Then Continue For
Dim sbVolume As Double = sb.Volume(.0001)
' Logger.Trace(String.Format("{0} = {1} cm^3", sb.Name, sbVolume))
sbVolume/=2.54^3 'cm are the database units, so cm^3 to in^3 conversion
Logger.Trace(String.Format("{0} = {1} in^3", sb.Name, sbVolume))
Next
Call AlignedBoxSize(pDoc.ComponentDefinition.PreciseRangeBox)'Box aligned with origin
Call OrientedBoxSize(pDoc.ComponentDefinition.OrientedMinimumRangeBox)'Box allowed to rotate for tightest fit
End Sub
Sub AlignedBoxSize(aRangeBox As Box)
Dim xLength, yLength, zLength As Double
xLength = aRangeBox.MaxPoint.X - aRangeBox.MinPoint.X
yLength = aRangeBox.MaxPoint.Y - aRangeBox.MinPoint.Y
zLength = aRangeBox.MaxPoint.Z - aRangeBox.MinPoint.Z
' Logger.Trace(String.Format("X: {0} cm, Y: {1} cm, Z: {2} cm", xLength, yLength, zLength))
xLength /= 2.54 'cm are the database units, so cm to in conversion
yLength /= 2.54 'cm are the database units, so cm to in conversion
zLength /= 2.54 'cm are the database units, so cm to in conversion
Logger.Trace(String.Format("X: {0} in, Y: {1} in, Z: {2} in", xLength, yLength, zLength))
End Sub
Sub OrientedBoxSize(anOrientedBox As OrientedBox)
Dim SizeOfBox As New List(Of Double)
SizeOfBox.Add(anOrientedBox.DirectionOne.Length)
SizeOfBox.Add(anOrientedBox.DirectionTwo.Length)
SizeOfBox.Add(anOrientedBox.DirectionThree.Length)
SizeOfBox.Sort()
' Logger.Trace(String.Format("Min Length: {0} cm, Mid Length: {1} cm, Max Length: {2} cm",SizeOfBox.Item(0), SizeOfBox.Item(1), SizeOfBox.Item(2)))
SizeOfBox.Item(0) /= 2.54 'cm are the database units, so cm to in conversion
SizeOfBox.Item(1) /= 2.54 'cm are the database units, so cm to in conversion
SizeOfBox.Item(2) /= 2.54 'cm are the database units, so cm to in conversion
Logger.Trace(String.Format("Min Length: {0} in, Mid Length: {1} in, Max Length: {2} in",SizeOfBox.Item(0), SizeOfBox.Item(1), SizeOfBox.Item(2)))
End Sub
Note that you could perform the conversion at the same time as you are setting initial values, but I left both the original and new traces available by separating the operations.
For conversion square or cubic units you can use internal conversion using UnitsOfMeasure.ConvertUnits
Dim l1 As Double = 2.54 '1 in => cm
Dim l2 As Double = 2.54 '1 in => cm
Dim l3 As Double = 2.54 '1 in => cm
Dim v1 = l1 * l2 * l3
Logger.Debug(v1 & " cm3")
Dim v2 = ThisApplication.UnitsOfMeasure.ConvertUnits(v1, "cm^3", "in^3")
Logger.Debug(v2 & " in3") 'Expected 1 in^3
@J-Camper @Michael.Navara Thank you both for your help. I don't fully understand "how/why" you wrote what you did, but it's working for what I need!
@Michael.Navara,
Thanks for the correction. I usually try to stick with UnitsTypeEnum values instead of strings of units, but I do see that it works with strings.
what is the correct code to add to the volumes that will format the numbers to only be (one) decimal place?
Update: I figured out how to control the decimal places, but it only works in the "Logger" the Parameters and Form still show 5 or 6 decimal places...?
You should be able to put the Double into "Math.Round(Double Variable, 1)" The second item is how many decimal places:
Dim test As Double = 1.123456789
test = Math.Round(test, 1)
Logger.Trace(test)
Edit: If you are still getting weird results when setting the Parameter value, you can feed the Double in as a String:
Dim test As Double = 1.123456789
test = Math.Round(test, 1)
Logger.Trace(test)
Parameter("feedtest") = test.ToString
Can't find what you're looking for? Ask the community or share your knowledge.