When you are tranversing through an assembly, how can you create a list with the part name and its GLOBAL minRange value? How would you use proxies to accompolish this?
Thank you,
-lemensk
Solved! Go to Solution.
Solved by lemensk. Go to Solution.
Hi,
If you access the range in the assembly context, you can use ComponentOccurrence.RangeBox without proxy because this has been transformed in the assembly context.
Mr. Liang,
Isn't your comment a 'half' truth? Before I posted the question, I had operating code that extracted Rangebox. However, my model had sub-assemblies and one particular sub-assembly was rotated 90degrees to the Global Assembly axis; so the 'x' minRange was the actually the Global 'z' value.
I beleive I can get around this by utilizing a proxy, but I was hoping for a simplified/error-proof technique.
Thank you,
-Kenny
Have you tried something like this? I've used this method for similar situations.
ComponentOccurrence myOccurance;
foreach(SurfaceBody body in myOccurance.SurfaceBodies)
{
if (body is SurfaceBodyProxy)
{
SurfaceBodyProxy bodyProxy = (SurfaceBodyProxy)body;
SurfaceBody NativeBody = bodyProxy.NativeObject;
Box bodyRange = NativeBody.RangeBox;
//whatever logic you need with the range box
}
}
Hi Kenny,
The RangeBox is a rectangular box that is guaranteed to enclose this object. I tested with the attached part, sub-**** and top-****, placing the occurrences with different rotations. The RangeBox looks well to me. Their locations are in the context of the top assembly The code is as below.
Or I misunderstood your question?
Sub getPartParam() Dim oAssDoc As AssemblyDocument Set oAssDoc = ThisApplication.ActiveDocument Dim localAsset As Asset Set localAsset = oAssDoc.Assets.Item("Clear") Dim oCompDef As ComponentDefinition Set oCompDef = oAssDoc.ComponentDefinition Dim oTransientBRep As TransientBRep Set oTransientBRep = ThisApplication.TransientBRep On Error Resume Next Dim oClientGraphics As ClientGraphics Set oClientGraphics = oCompDef.ClientGraphicsCollection.Item("Sample3DGraphicsID") If Err.Number = 0 Then On Error GoTo 0 oClientGraphics.Delete ThisApplication.ActiveView.Update Err.Clear Exit Sub End If Set oClientGraphics = oCompDef.ClientGraphicsCollection.Add("Sample3DGraphicsID") Dim oSurfacesNode As GraphicsNode Set oSurfacesNode = oClientGraphics.AddNode(1) oSurfacesNode.Appearance = localAsset Dim oOcc As ComponentOccurrence For Each oOcc In oAssDoc.ComponentDefinition.Occurrences Dim oRB As Box Set oRB = oOcc.RangeBox Dim oBody As SurfaceBody Set oBody = oTransientBRep.CreateSolidBlock(oRB.Copy()) ' Create client graphics based on the transient body Dim oSurfaceGraphics As SurfaceGraphics Set oSurfaceGraphics = oSurfacesNode.AddSurfaceGraphics(oBody) Next oSurfacesNode.Appearance = localAsset ThisApplication.ActiveView.Update End Sub
I am trying to extract part locations. Here is my model:
(IMAGE1)
You will notice that I have (6) posts, both comprised of Angle 1:1 and Angle 1:2. Here is the result I get when I print off the parts MinRange and MaxRange Properties:
(IMAGE2)
As you will notice, they are all identical. I understand your code in the context that the Min and MaxRange values provided by Occurrences of an Assembly all have the same datum, but when I try to access parts in a sub-assembly (i.e., a face of one of your cube) I only get the min/max values that pertain to it locally (i.e. x,y,z values pertaining to the cube origin, not the assembly origin). Granted, I have created a coorolation between locaiton of a subassembly to the main assembly and add the difference between the two to the min/max range values, but this all falls apart when the subassembly itself has a different axis orientation then the main assembly.
I was hoping to use proxies, but I'm having trouble at generating a vector between the global origin and a parts min/max range values.
-thanks, Ken
Hi Ken,
You should try to modify Xiao's code to make it work for your assembly and if it does not work as you need it then show us how you modified it.
I think you are retrieving the data in context of the subassembly you activated - i.e. "Support 2:1" -, but what you seem to want is the locaion in context of the topmost assembly.
Using proxies is not more complicated than getting the information in a different context and then doing transformations on them: http://adndevblog.typepad.com/manufacturing/2013/07/occurrences-contexts-definitions-proxies.html
I hope this helps.
Cheers,
Here is my code:
'------------------------start
'Option Explicit
Dim partOccur As Inventor.ComponentOccurrence
Dim tempA As Inventor.ComponentOccurrence
Dim assemblyDoc As Inventor.AssemblyDocument
Dim fileName As String
Dim inventDoc As Inventor.AssemblyDocument
Dim partProxy As Inventor.WorkPointProxy
Dim partProxy2 As Inventor.WorkPointProxy
Dim partParentProxy As Inventor.WorkPointProxy
Dim partParentFatherProxy As Inventor.WorkPointProxy
Dim partParentGrandFatherProxy As Inventor.WorkPointProxy
Dim proxyToUse As Inventor.WorkPointProxy
Sub printPart()
Dim inventDoc As Inventor.AssemblyDocument
Set inventDoc = ThisApplication.ActiveDocument
fileName = inventDoc.DisplayName
For Each partOccur In inventDoc.ComponentDefinition.Occurrences
printPartCoord partOccur, 0, 0, 0 'inventDoc.ComponentDefinition.RangeBox.MinPoint.Z
Next
End Sub
Sub printPartCoord(assemblyObj As Object, xCoord As Double, yCoord As Double, zCoord As Double)
Dim strg As String
'Dim xDelta, yDelta, zCoord2 As Double
Dim partVert1Proxy As Inventor.WorkPointProxy
Dim partVert1 As Inventor.WorkPoint
If TypeName(assemblyObj) = "AssemblyDocument" Then
Set assemblyDoc = assemblyObj
For Each partOccur In assemblyDoc.ComponentDefinition.Occurrences
printPartCoord partOccur, xCoord, _
yCoord, _
zCoord
Next
ElseIf TypeName(assemblyObj) = "ComponentOccurrence" Then
For Each partOccur In assemblyObj.Definition.Occurrences
If partOccur.Definition.SurfaceBodies.Count > 0 Then
Dim deltaX, deltaY, deltaZ, avgX, avgY, avgZ As Double
Dim minRangePoint, maxRangePoint, minRangePoint1, maxRangePoint1 As WorkPoint
Dim partVector As Vector
deltaX = partOccur.RangeBox.MaxPoint.X - _
partOccur.RangeBox.MinPoint.X
avgX = (deltaX / 2)
deltaY = partOccur.RangeBox.MaxPoint.Y - _
partOccur.RangeBox.MinPoint.Y
avgY = (deltaY / 2)
deltaZ = partOccur.RangeBox.MaxPoint.Z - _
partOccur.RangeBox.MinPoint.Z
avgZ = (deltaZ / 2)
If deltaX > deltaY And deltaX > deltaZ Then
Set minRangePoint1 = partOccur.Definition.WorkPoints.AddFixed(ThisApplication.TransientGeometry.CreatePoint(0, avgY, avgZ))
Set maxRangePoint1 = partOccur.Definition.WorkPoints.AddFixed(ThisApplication.TransientGeometry.CreatePoint(deltaX, avgY, avgZ))
ElseIf deltaY > deltaX And deltaY > deltaZ Then
Set minRangePoint1 = partOccur.Definition.WorkPoints.AddFixed(ThisApplication.TransientGeometry.CreatePoint(avgX, 0, avgZ))
Set maxRangePoint1 = partOccur.Definition.WorkPoints.AddFixed(ThisApplication.TransientGeometry.CreatePoint(avgX, deltaY, avgZ))
Else
Set minRangePoint1 = partOccur.Definition.WorkPoints.AddFixed(ThisApplication.TransientGeometry.CreatePoint(avgX, avgY, 0))
Set maxRangePoint1 = partOccur.Definition.WorkPoints.AddFixed(ThisApplication.TransientGeometry.CreatePoint(avgX, avgY, deltaZ))
End If
Set partVector = minRangePoint1.Point.VectorTo(maxRangePoint1.Point)
maxRangePoint1.Delete
minRangePoint1.Delete
'Set minRangePoint = partOccur.Definition.WorkPoints.AddFixed(partOccur.RangeBox.MinPoint)
'Set maxRangePoint = partOccur.Definition.WorkPoints.AddFixed(partOccur.RangeBox.MaxPoint)
Set minRangePoint = partOccur.Definition.WorkPoints(1)
'Set maxRangePoint = partOccur.Definition.WorkPoints(2)
Dim oMinWorkPointProxy As Inventor.WorkPointProxy
Dim oMaxWorkPointProxy As Inventor.WorkPointProxy
Dim oMinWorkPointProxy1 As Inventor.WorkPointProxy
Dim oMaxWorkPointProxy1 As Inventor.WorkPointProxy
Dim oMinWorkPointProxy2 As Inventor.WorkPointProxy
Dim oMaxWorkPointProxy2 As Inventor.WorkPointProxy
Dim oMinWorkPointUseProxy As Inventor.WorkPointProxy
Dim oMaxWorkPointUseProxy As Inventor.WorkPointProxy
Dim oMinWorkPointProxy3 As Inventor.WorkPointProxy
Dim oMaxWorkPointProxy3 As Inventor.WorkPointProxy
Dim oMinWorkPointProxy4 As Inventor.WorkPointProxy
Dim oMaxWorkPointProxy4 As Inventor.WorkPointProxy
Set tempA = assemblyObj
Call partOccur.CreateGeometryProxy(minRangePoint, oMinWorkPointProxy)
'Call partOccur.CreateGeometryProxy(maxRangePoint, oMaxWorkPointProxy)
Set oMinWorkPointUseProxy = oMinWorkPointProxy
'Set oMaxWorkPointUseProxy = oMaxWorkPointProxy
Call assemblyObj.CreateGeometryProxy(oMinWorkPointProxy, oMinWorkPointProxy1)
'Call assemblyObj.CreateGeometryProxy(oMaxWorkPointProxy, oMaxWorkPointProxy1)
Set oMinWorkPointUseProxy = oMinWorkPointProxy1
'Set oMaxWorkPointUseProxy = oMaxWorkPointProxy1
If Not (tempA.Parent.ActiveOccurrence Is Nothing) Then
Call tempA.Parent.ActiveOccurrence.CreateGeometryProxy(oMinWorkPointProxy1, oMinWorkPointProxy2)
'Call tempA.Parent.ActiveOccurrence.CreateGeometryProxy(oMaxWorkPointProxy1, oMaxWorkPointProxy2)
Set oMinWorkPointUseProxy = oMinWorkPointProxy2
'Set oMaxWorkPointUseProxy = oMaxWorkPointProxy2
If Not (tempA.Parent.Parent.ActiveOccurrence Is Nothing) Then
Call tempA.Parent.Parent.ActiveOccurrence.CreateGeometryProxy(oMinWorkPointProxy2, oMinWorkPointProxy3)
'Call tempA.Parent.Parent.ActiveOccurrence.CreateGeometryProxy(oMaxWorkPointProxy2, oMaxWorkPointProxy3)
Set oMinWorkPointUseProxy = oMinWorkPointProxy3
'Set oMaxWorkPointUseProxy = oMaxWorkPointProxy3
If Not (tempA.Parent.Parent.Parent.ActiveOccurrence Is Nothing) Then
Call tempA.Parent.Parent.Parent.ActiveOccurrence.CreateGeometryProxy(oMinWorkPointProxy3, oMinWorkPointProxy4)
'Call tempA.Parent.Parent.Parent.ActiveOccurrence.CreateGeometryProxy(oMaxWorkPointProxy3, oMaxWorkPointProxy4)
Set oMinWorkPointUseProxy = oMinWorkPointProxy4
'Set oMaxWorkPointUseProxy = oMaxWorkPointProxy4
End If
End If
End If
Dim xMin As Double
Dim yMin As Double
Dim zMin As Double
Dim xMax As Double
Dim yMax As Double
Dim zMax As Double
xMin = oMinWorkPointUseProxy.Point.X + xCoord
yMin = oMinWorkPointUseProxy.Point.Y + yCoord
zMin = oMinWorkPointUseProxy.Point.Z + zCoord
xMax = oMinWorkPointUseProxy.Point.X + partVector.X + xCoord
yMax = oMinWorkPointUseProxy.Point.Y + partVector.Y + yCoord
zMax = oMinWorkPointUseProxy.Point.Z + partVector.Z + zCoord
strg = partOccur.Name & ";" & xMin & ";" & yMin & ";" & zMin & ";" & partOccur.Name & ";" & xMax & ";" & yMax & ";" & zMax
Open "C:\Temp\" & fileName & ".txt" For Append As #1
Print #1, strg
Close #1
Else
printPartCoord partOccur, xCoord, _
yCoord, _
zCoord
End If
Next
End If
End Sub
'------------------------end
What it is supposed to do it print off (2) points for each part, the beginging of a member and the end of the member.
What would make this REALLY easy is if there is code out there to 'destory' and assembly and 'float' all the parts to the surface (i.e. one level). Heck, I wouldn't even mind if it created a 10 MG file and took 2 days for run time
Hi,
I think that Xiao's code is pretty close to what you want. I think you just want to go down to the leaf occuurrences, the actual parts.
You just need to modify the following part in the getPartParam function from this:
For Each oOcc In oAssDoc.ComponentDefinition.Occurrences
to this:
For Each oOcc In oAssDoc.ComponentDefinition.Occurrences.AllLeafOccurrences
Note: you also need to add the "Clear" appearance style to the document in the "Appearance Browser" palette before running the code.
Cheers,
Below is the answer to my question. Surprised how hard it was to get such simple code:
'CODE START ---------------------------------
Sub printParts()
Dim inventDoc As Inventor.AssemblyDocument
Dim deltaX, deltaY, deltaZ, avgX, avgY, avgZ, minX, minY, minZ, maxX, maxY, maxZ As Double
Dim fileName, strg As String
Dim partOccur As Inventor.ComponentOccurrence
Set inventDoc = ThisApplication.ActiveDocument
fileName = inventDoc.DisplayName
For Each partOccur In inventDoc.ComponentDefinition.Occurrences.AllLeafOccurrences 'For each part included in the assembly
strg = partOccur.Name & ";" & partOccur.RangeBox.minPoint.X & ";" & partOccur.RangeBox.minPoint.Y & _
";" & partOccur.RangeBox.minPoint.Z
Open "C:\Temp\" & fileName & ".txt" For Append As #1 'Open txt file and Append
Print #1, strg 'Print String
Close #1 'Close txt file
Next
End Sub
'CODE STOP ---------------------------------
Quote: "Note: you also need to add the "Clear" appearance style to the document in the "Appearance Browser" palette before running the code."
I don't access the Appearance Brower palette at all; would I NEED to do something with the Appearance Brower or fear unreliable/contaminated data from Leaf Occurrences?