Cannot get global(assembly) coordinates

Greg Papp

Cannot get global(assembly) coordinates

Hello.  I have tried to get assembly coordinates directly in CatVBA, and I cannot find a way. 

If you use the Measurement tool in a CATProduct assembly, it returns global or assembly coordinates.  

I have tried to use the SPAWorkbench to get them using a referenced Part but the measurements all come back in the local (Part Coordinate) system.

Any help will be appreciated.  Thanks, Greg

Gerardo Veredas

RE: Cannot get global(assembly) coordinates
(in response to Greg Papp)

If I understood, you are measuring objects (points or similar) which are inside a CATPart which is inside a CATProduct, right?

In that case, you are getting coordinates with respect to the CATPart's axis system. If you want these coordinates given with respect to the CATProduct's axis system you must apply an axis system transformation to the coordinates. You just have to multiply the coordinates vector times the transformation matrix, which is the one given by the Move object (or its inverse, I don't remember well)

It's a well-known problem which has been solved many times, don't waste your time writing down code. If this is the problem you're talking about, I'll post you a tested solution that works for CATParts at any level of depth inside a Product (I mean Part inside Product inside Product.... and so on, when multiple transformations are involved)


David Burke

RE: Cannot get global(assembly) coordinates
(in response to Greg Papp)

Not sure if you are addressing GPAPP's problem, but I would like to see this code. I'm working on something that applies global rotations to part(s). It works when the part is one level deep in the product, but not when there are several levels involved. I have not had the time to fix it, so you would be helping me out a lot!

Greg Papp

RE: Cannot get global(assembly) coordinates
(in response to Greg Papp)
For Nimdraug and Dave2784, attached is sample code.

Please forgive me if I am nieve about an AxisSystem, as far as I know, there is no global AxisSystem declared at the origin in a CATProduct assembly.

I want to return the values of a point location (the centerpoint of a hole on a CATPart) that is on a CATPart in a CATProduct assembly. To clarify my initial statement, the assemblies are built from CATparts without any geometry at global 0,0,0 (no axis, no planes, nothing). Yet when you use the Measure tool and select a hole's edge, it returns the values back to global 0,0,0.

Every time I try and use the SPAworkbench, I must refer to objects on a CATPart, and it apparently switches the measurement to local within the CATPart. So the latest hack is an attempt to measure between two different CATParts. I have created a CATPart with nothing in it except a single Point and then added this to the CATProduct assembly. When you view the assembly, the point appears at true global 0,0,0. If you do a measure distance by selecting on the CATPart and the (new) point at global 0,0,0 using the Measurement tool, you can see the values between them appear correctly.

But from the code below, all I am getting back is a local distance to the part's own internal origin.

Sub MakePointFromEdge(MySelect, mypart As Object, HoleOrig As Variant)

'Input = MySelect, selection object from LocatorSelect routine.

'A Point object is generated at the Hole's center, and
'the XYZ coordinates of the hole's origin are returned
'in Part Coordinate space.

'9-23-08 g.v.papp; copied from NEVJOHNSON's code at the COE Website and modified.

Dim myshapes
Dim myppnt
Dim oPuntoCentro As Point
Dim MyWkBnch As SPAWorkbench
Dim ThisPart
Dim MyMeasure
Dim GlobalOrig(5)
Dim temporig(2)
Dim myresult
Dim pnt1 As Point
Dim pnt2 As Point
Dim oRef1 As Reference
Dim oRef2 As Reference

IorigCnt = IorigCnt + 1
Dim InputObject(0)

Set oEdge = MySelect.Item(1)
Set oRef = oEdge.Reference
Set oAssemble = oEdge.Value.Parent
Set myshapes = oEdge.Value.Parent.Parent
Set mypart = myshapes.Parent.Parent.Parent 'this may be too specific, please forgive me

Set oHSF = mypart.HybridShapeFactory
Set oPuntoCentro = oHSF.AddNewPointCenter(oRef)
oPuntoCentro.Name = "LocatorOrigin" & "." & IorigCnt
Set oHB = mypart.HybridBodies.Add()
oHB.AppendHybridShape oPuntoCentro

Set myppnt = oPuntoCentro
myppnt.GetCoordinates HoleOrig
Set mypoint = oPuntoCentro


Set pnt1 = mypart.FindObjectByName("LocatorOrigin." & IorigCnt)
Set oRef1 = mypart.CreateReferenceFromObject(pnt1)

doccnt = CATIA.Documents.Count
For i = 1 To doccnt
mnam = CATIA.Documents.Item(i).Name
If (InStr(1, mnam, "Reference_Origin") > 0) Then
Set ThisPart = CATIA.Documents.Item(i).Part
Set pnt2 = ThisPart.FindObjectByName("Point.1")
pnt2.GetCoordinates temporig
Set oRef2 = ThisPart.CreateReferenceFromObject(pnt2)
Exit For
End If

Set MyWkBnch = CATIA.ActiveDocument.GetWorkbench("SPAWorkbench")
Set MyMeasure = MyWkBnch.GetMeasurable(oRef1)
myresult = MyMeasure.GetMinimumDistancePoints(oRef2, GlobalOrig)

'--------GlobalOrig is only returning distance to the part's local origin.

End Sub

Gerardo Veredas

RE: Cannot get global(assembly) coordinates
(in response to Greg Papp)


You don't need to add any "dummy" empty CATPart whatsoever to get a point's coordinates expressed in the CATProduct's global coordinates system. Try the code I post below. Pass the coordinates you get in HoleOrig to the sub and an empty array, and you will get back the array with the global coordinates. Continue reading my reply to DAVE2784 to see a brief explanation on how it works.

Also, my suggestion is that you don't use Measurables unless you really need to. Not the case of a point's coordinates or a point-point distance.



To DAVE2784:

Here is the code, sorry for the delay. I've simplified it to just make the coordinates transformation.

There are two functions and a sub. The two functions are just mathematical stuff, 3x3 matrix inverse and determinant calculation, you can replace them for your preferred ones if you want. Sub Coord_Transform will do the coordinates transformation. The arguments of the sub are:

aRel() As Double ,  Matrix with a set of coordinates relative to the CATPart's axis system. These are, typically, the ones you get with the GetCoordinates method on a Point. Coordinates are as usual; aRel(0) for X, aRel(1) for Y and aRel(2) for Z. Maybe you need to convert types from variant to double to avoid type mismatch.

aAbs() As Double, Matrix with coordinates with respect to the Axis System of the top-level CATProduct. This is the matrix where you will get the results of the coordinates transformation. Initially blank, pass it to the sub and it will return it to you properly filled; again aAbs(0) for X, aAbs(1) for Y and aAbs(2) for Z

oProduct As Product, This is the CATPart's Product. For example, if you are measuring the coordinates of a "Point.1" in a CATPart named "Part.1", which is the first instance in a CATproduct named "RootProduct", then oProduct=RootProduct.Products.Item(1), and the CATPart itself can be accessed via the reference product, like oProduct.ReferenceProduct.Parent. You need to know the Product object which references to the CATPart in order to get its coordinates with the Position property.

bRecursively As Boolean, True if you want to calculate the coordinates with respect to the top-level Product, no matter what level of depth your CATPart is. False to calculate only with respect to the CATPart's father Product. I guess what you want to try here is "True", with some levels of depth...

Just paste the code in yours and call Coord_Transform with the appropiate arguments. If you need it, a similar routine also calculates coordinates taking into account different Axis Systems in a CATPart, using the same matrix transformations...

Hope it helps!


'---CODE START------------------------------------------------------
Function Det3x3(dX11 As Double, dX12 As Double, dX13 As Double, _
dX21 As Double, dX22 As Double, dX23 As Double, _
dX31 As Double, dX32 As Double, dX33 As Double) As Double
'* 3x3 matrix determinant calculation (direct)

Det3x3 = dX11 * dX22 * dX33 + dX12 * dX23 * dX31 + dX21 * dX32 * dX13 - _
dX13 * dX22 * dX31 - dX12 * dX21 * dX33 - dX23 * dX32 * dX11
End Function
Function Inv3x3(dX11 As Double, dX12 As Double, dX13 As Double, _
dX21 As Double, dX22 As Double, dX23 As Double, _
dX31 As Double, dX32 As Double, dX33 As Double, aInv() As Double) As Boolean
'* 3x3 matrix inverse calculation (direct)
    Dim dDet As Double

ReDim aInv(8)

Inv3x3 = False

dDet = Det3x3(dX11, dX12, dX13, dX21, dX22, dX23, dX31, dX32, dX33)
If dDet = 0 Then Exit Function

aInv(0) = (dX22 * dX33 - dX23 * dX32) / Abs(dDet)
aInv(1) = (dX13 * dX32 - dX12 * dX33) / Abs(dDet)
aInv(2) = (dX12 * dX23 - dX13 * dX22) / Abs(dDet)
aInv(3) = (dX23 * dX31 - dX21 * dX33) / Abs(dDet)
aInv(4) = (dX11 * dX33 - dX13 * dX31) / Abs(dDet)
aInv(5) = (dX13 * dX21 - dX11 * dX23) / Abs(dDet)
aInv(6) = (dX21 * dX32 - dX22 * dX31) / Abs(dDet)
aInv(7) = (dX12 * dX31 - dX11 * dX32) / Abs(dDet)
aInv(8) = (dX11 * dX22 - dX12 * dX21) / Abs(dDet)

Inv3x3 = True

End Function
Sub Coord_Transform(aRel() As Double, aAbs() As Double, oProduct As Product, bRecursively As Boolean)

Dim vProduct As Object, vCoord(11)
Dim oFatherProduct As Product
Dim aInv() As Double

'Exit condition, empty object
If oProduct Is Nothing Then Exit Sub

'Redim absolute coords matrix
On Error Resume Next
ReDim aAbs(2)
On Error GoTo 0

'Calculate product coordinates
Set vProduct = oProduct
vProduct.Position.GetComponents vCoord

'Calculate inverse matrix
If Inv3x3(CDbl(vCoord(0)), CDbl(vCoord(1)), CDbl(vCoord(2)), _
CDbl(vCoord(3)), CDbl(vCoord(4)), CDbl(vCoord(5)), _
CDbl(vCoord(6)), CDbl(vCoord(7)), CDbl(vCoord(8)), aInv) Then
MsgBox "Error, degenerate transformation", vbOKOnly
Exit Sub
End If

'Calculate transformation
aAbs(0) = vCoord(9) + aInv(0) * aRel(0) + aInv(1) * aRel(1) + aInv(2) * aRel(2)
aAbs(1) = vCoord(10) + aInv(3) * aRel(0) + aInv(4) * aRel(1) + aInv(5) * aRel(2)
aAbs(2) = vCoord(11) + aInv(6) * aRel(0) + aInv(7) * aRel(1) + aInv(8) * aRel(2)

'If recursive option sepecified, search for parents and applies the transformation again
If bRecursively Then

'Try to assign parent
Set oFatherProduct = Nothing
On Error Resume Next
Set oFatherProduct = oProduct.Parent.Parent
On Error GoTo 0

'If OK, recalculate coords
If oFatherProduct Is Nothing Then
aRel(0) = aAbs(0)
aRel(1) = aAbs(1)
aRel(2) = aAbs(2)
Coord_Transform aRel, aAbs, oFatherProduct, True
End If

End If

End Sub

'---CODE END------------------------------------------------------

Greg Papp

RE: Cannot get global(assembly) coordinates
(in response to Greg Papp)
My compliments to nimdraug for the 29 September reply.

It took me a little while to plug it into my code, but it yields good accurate results.
The main thing is to make sure the correct CatProduct is being supplied.

I think it's much harder to document and explain code for third party users like myself
than it is to write it in the first place, but I benefited from the explanation.

The approach is excellent and (as far as I can tell) not documented in the Catia VBA help.

Edgar David Perez Muñoz

RE: Cannot get global(assembly) coordinates
(in response to Greg Papp)

I know its a very old Thread, but im trying to get absolute coordintaes of several points and i cant get it to work everytime.

Basically i have a main product with several products in it, in this case im working with Flexible curves, i extract the initial and end point coordinates and then use the code posted above to get the absolute coordinates.


For some reason on some models it does work and i get coordinates referenced to the same absolute Axis system, but on other models i get different coordintes even thought the CATIA tool to measure distances between objects gives me 0 Distance.

Any idea what could cause this?

Edited By:
Edgar David Perez Muñoz[Safran Engineering Services] @ Jul 22, 2016 - 11:26 AM (America/Mountain)

Little Cthulhu

RE: Cannot get global(assembly) coordinates
(in response to Edgar David Perez Muñoz)



Do you use local axis systems in your parts?


Also check similar thread:

Balla Zoltan

RE: Cannot get global(assembly) coordinates
(in response to Gerardo Veredas)

Hello, could I use this code to get the global/Absolute coordinates of a select direction inside a positioned Part using the Measurable2.GetPlane Coord sintax?

Or I have to multiply first the Part position matrix with the direction matrix and after that to apply the coord_Transform sub?


Cliff Johnson, Cliff

RE: Cannot get global(assembly) coordinates
(in response to Balla Zoltan)

As of R25 (or maybe R24) the SPAWorkbench / Measurable now always returns global point coordinates.  So all the heavy matrix math is no longer required. 

How to ask questions 

Little Cthulhu

RE: Cannot get global(assembly) coordinates
(in response to Cliff Johnson, Cliff)

Thanks for pointing that out, Cliff.

Balla Zoltan

RE: Cannot get global(assembly) coordinates
(in response to Cliff Johnson, Cliff)


I use a Catia V5-6 Release 2014, Service pack 4, Built Number 24, Hot fix 88.

When I select -in product context- a direction containd in a Positioned Part I get back the Local direction as the Part would be opened in a new window.

But when I activate the part manualy -also in Product context- before I start the selection command it gives me back the global coordinates of the direction vector. It is somehow strange for me.

How could I get back always the global coordinates of the direction vector?

Barcode Maker

RE: Cannot get global(assembly) coordinates
(in response to Greg Papp)

How many measurement tools there are in  CAT product assembly.