Measure from Axis System

COE Administrator

Measure from Axis System
Hello All,

I am trying to export point coordinates measured from a user defined axis system rather than from the part origin. Below is the current code I am using. It works great as far as exporting the points to Excel, but I can't get it to reference with respect to another axis.

I borrowed most of this code from another post.

Can anyone help me with this? Is it possible?

Thanks in advance!
Branden

Sub CATMain()

'Dim zPartDoc As Document
Set zPartDoc = CATIA.ActiveDocument

Set xl = GetObject(, "Excel.Application")

'Dim zCATPart As Part
Set zCatPart = zPartDoc.Part

'Dim zSelection As Selection
Set zSelection = zPartDoc.Selection

'Dim zSPAWorkbench As SPAWorkbench
Set zSPAWorkbench = zPartDoc.GetWorkbench("SPAWorkbench")

'Search only Visible points

'zSelection.Clear
'zSelection.Search "CATPrtSearch.Point.Visibility=Visible,all"


Set oAxisSystem = zCatPart.AxisSystems.Item(1)
Set oRefAxisSystem = zCatPart.CreateReferenceFromObject(oAxisSystem)


Dim zCoords(2)

For i = 1 To zSelection.Count
Set oRef = zCatPart.CreateReferenceFromObject(zSelection.Item(i).Reference)
oRef.RefAxisSystem = oRefAxisSystem
Set zMeasure = zSPAWorkbench.GetMeasurable(oRef)

zMeasure.GetPoint zCoords

'Writes out point X Y and Z

For j = 0 To 2
xl.ActiveCell.Offset(0, j).Value = zCoords(j) / 25.4
Next

xl.ActiveCell.Offset(1, 0).Select

Next


End Sub





COE Administrator

Measure from Axis System
(in response to COE Administrator)
Ok, my mistake. I copied the code as I was messing with it trying to get it to work. Here is the code that works right now, without measuring from a specified axis system. Basically I have taken out the line:

oRef.RefAxisSystem = oRefAxisSystem

Here is the code with the above line removed:

Sub CATMain()

'Dim zPartDoc As Document
Set zPartDoc = CATIA.ActiveDocument

Set xl = GetObject(, "Excel.Application")

'Dim zCATPart As Part
Set zCatPart = zPartDoc.Part

'Dim zSelection As Selection
Set zSelection = zPartDoc.Selection

'Dim zSPAWorkbench As SPAWorkbench
Set zSPAWorkbench = zPartDoc.GetWorkbench("SPAWorkbench")

'Search only Visible points

'zSelection.Clear
'zSelection.Search "CATPrtSearch.Point.Visibility=Visible,all"


Set oAxisSystem = zCatPart.AxisSystems.Item(1)
Set oRefAxisSystem = zCatPart.CreateReferenceFromObject(oAxisSystem)


Dim zCoords(2)

For i = 1 To zSelection.Count
Set oRef = zCatPart.CreateReferenceFromObject(zSelection.Item(i).Reference)
'oRef.RefAxisSystem = oRefAxisSystem
Set zMeasure = zSPAWorkbench.GetMeasurable(oRef)

zMeasure.GetPoint zCoords

'Writes out point X Y and Z

For j = 0 To 2
xl.ActiveCell.Offset(0, j).Value = zCoords(j) / 25.4
Next

xl.ActiveCell.Offset(1, 0).Select

Next


sorry 'bout that.

COE Administrator

Measure from Axis System
(in response to COE Administrator)
Have you tried using the GetMinimumDistancePoints(reference, array() ) method of the measurable object? I have never tried it, but I imagine you could get a reference to the axis you are interested in, and then read the coordinate data for the XYZ position.

Good luck.

COE Administrator

Measure from Axis System
(in response to COE Administrator)
Thanks for the prompt reply, Gary. I have looked at the CATIA help on the GetMinimumDistancePoints(reference, array() ) method and, like with most of the CATIA help documentation, I am stupefied. I have muddled through some of it and gotten a basic understanding, but this one looks like a doozie!!

I'll give it a try, but I'm not sure if this will get me where I want to be. . .

Thanks,
Branden

COE Administrator

Measure from Axis System
(in response to COE Administrator)
Sorry bjstep - I have just tried my suggestion and it didn't work. It still gave values with ref to the master origin.

I will maybe have a more concerted attempt tomorrow. My code snippet that I inserted into your original code is shown below - I created a second axis system called "GB axis" :




Status = zSelection.SelectElement2(Array("Point"), "Select a point", True)
If Status = "Cancel" Then Exit Sub

Set oAxisSystem = zCATPart.AxisSystems.Item("GB axis")
Set oRefAxisSystem = zCATPart.CreateReferenceFromObject(oAxisSystem)


Dim zCoords(2)

For i = 1 To zSelection.Count
Set oRef = zCATPart.CreateReferenceFromObject(zSelection.Item(i).Value)
'oRef.RefAxisSystem = oRefAxisSystem
Set zMeasure = zSPAWorkbench.GetMeasurable(oRefAxisSystem)
Dim coords(8)
zMeasure.GetMinimumDistancePoints oRef, coords

COE Administrator

Measure from Axis System
(in response to COE Administrator)
Geez. Gary. Thanks for all your concentrated work thus far. I think you are on the right track. I'll try to play with it a little tonight as I won't have time the rest of the working day.

Regards,
Branden

Cliff Johnson, Cliff

Measure from Axis System
(in response to COE Administrator)
I don't see that you need to use measurment at all to do this.

From the points you can get their absolute coordinates.

From the axis system you can get its origin and vector directions.

A little vector algebra gives you the points relative to the coordinate system:

(this is VBA code)

Sub CATMain()

'first search for and retrieve all the visible points. Stash them in a collection....
Dim sel 'As Selection
Set sel = CATIA.ActiveDocument.Selection

Dim visiblePoints As Collection
Set visiblePoints = New Collection

Dim query As String
query = "'Generative Shape Design'.Point.Visibility=Visible,all"
sel.Clear
sel.Search query

For i = 1 To sel.count
visiblePoints.Add sel.Item(i).Value
Next

'Now select the axis system to use...
Dim fil(0)
fil(0) = "AxisSystem"
sel.Clear
ans = sel.SelectElement2(fil, "Select an axis system", False)
If ans <> "Normal" Then Exit Sub

Dim axis As AxisSystem
Set axis = sel.Item(1).Value

Debug.Print "axis system is " & axis.Name

'Get the definition of the axis system
Dim axisOrigin(2)
Dim xVect(2), yVect(2), zVect(2)
Dim vAxis As Variant
Set vAxis = axis
vAxis.GetOrigin (axisOrigin)
vAxis.GetXAxis (xVect)
vAxis.GetYAxis (yVect)
vAxis.GetZAxis (zVect)

'these vectors need to be normalized
NormalizeVector xVect, xVect
NormalizeVector yVect, yVect
NormalizeVector zVect, zVect

'display the Coordinate system data in VBA immediate window
Debug.Print "ORIGIN: " & axisOrigin(0) & ", " & axisOrigin(1) & ", " & axisOrigin(2)
Debug.Print "Vect DX: " & xVect(0) & ", " & xVect(1) & ", " & xVect(2)
Debug.Print "Vect DY: " & yVect(0) & ", " & yVect(1) & ", " & yVect(2)
Debug.Print "Vect DZ: " & zVect(0) & ", " & zVect(1) & ", " & zVect(2)

'loop through all the points getting each coordinate, and transform it into the axis system coordinate
Dim globalCoords(2)
Dim delta(2)
Dim csCoords(2)
Dim vPx As Variant

For i = 1 To visiblePoints.count
Set vPx = visiblePoints.Item(i)
vPx.GetCoordinates (globalCoords)
Debug.Print "Point : " & vPx.Name & " GLOBAL: X = " & globalCoords(0) & " Y = " & globalCoords(1) & " Z = " & globalCoords(2) & " (Units = mm)"

'vector from cs origin to point
delta(0) = globalCoords(0) - axisOrigin(0)
delta(1) = globalCoords(1) - axisOrigin(1)
delta(2) = globalCoords(2) - axisOrigin(2)

'determine components along cs axis
csCoords(0) = DotProduct(delta, xVect)
csCoords(1) = DotProduct(delta, yVect)
csCoords(2) = DotProduct(delta, zVect)

'output the results to VBA
Debug.Print "Point : " & vPx.Name & " CS: X = " & csCoords(0) & " Y = " & csCoords(1) & " Z = " & csCoords(2) & " (Units = mm)"

Next


End Sub

'----------------------------------------------------------------------------

Public Function DotProduct(vect1(), vect2()) As Double
DotProduct = vect1(0) * vect2(0) + vect1(1) * vect2(1) + vect1(2) * vect2(2)
End Function

'----------------------------------------------------------------------------
Public Sub NormalizeVector(invect(), ByRef normvect())
Dim mag As Double
mag = Sqr(invect(0) * invect(0) + invect(1) * invect(1) + invect(2) * invect(2))
If mag < 0.0000001 Then Call Err.Raise(1001, , "Zero length vector cannot be normalized")
normvect(0) = invect(0) / mag
normvect(1) = invect(1) / mag
normvect(2) = invect(2) / mag
End Sub

COE Administrator

Measure from Axis System
(in response to COE Administrator)
Cliff, this is a pretty ingenius method and I think this will work. However, I need to squash a bug. . .

Runtime Error 438 at line:
vPx.GetCoordinates (globalCoords)

"Object does not support property or method"

Does this have to do with declaring vPx as Variant?

Thanks for your input on this.

Cliff Johnson, Cliff

Measure from Axis System
(in response to COE Administrator)
I am pretty sure it has to be that way. It's one of the cardinal rules of Catia VB programming:

Any method which uses an array argument must be called on a variant object.

What I would look at is what kind of object is vPx in your specific case? You should be able to use the VB function typename() on the object to see what it really is (Assuming you are using VBA, enter "print typename(vPx)" in the immediate window when you get this error message) .

Could be it's something that looks and smells like a point but is not - like an intersection between two curves or an extremum. I see that an intersection will be returned by my search query and that won't have a GetCoordinates method. You would have to create a datum point from it first.

Changing the search query to this:

query="'Generative Shape Design'.'Point object'.Visibility=Visible"

should return only true points.


Then again, there may be something else I have not considered.

COE Administrator

Measure from Axis System
(in response to COE Administrator)
Yes, Cliff, I think you are right. I went ahead and converted the points to datum before obtaining coordinates and it seems to be working. I have added Excel reference and output in inches. The code works as follows:

Sub CATMain()

'first search for and retrieve all the visible points. Stash them in a collection....
Dim sel 'As Selection
Set sel = CATIA.ActiveDocument.Selection

Set xl = GetObject(, "Excel.Application")

Set zCatPart = CATIA.ActiveDocument.Part
Set HSF = zCatPart.HybridShapeFactory

Dim visiblePoints As Collection
Set visiblePoints = New Collection

Dim query As String
query = "'Generative Shape Design'.Point.Visibility=Visible,all"
sel.Clear
sel.Search query

For i = 1 To sel.Count
visiblePoints.Add sel.Item(i).Value
Next

'Now select the axis system to use...
Dim fil(0)
fil(0) = "AxisSystem"
sel.Clear
ans = sel.SelectElement2(fil, "Select an axis system", False)
If ans <> "Normal" Then Exit Sub

Dim axis As AxisSystem
Set axis = sel.Item(1).Value

Debug.Print "axis system is " & axis.Name

'Get the definition of the axis system
Dim axisOrigin(2)
Dim xVect(2), yVect(2), zVect(2)
Dim vAxis As Variant
Set vAxis = axis
vAxis.GetOrigin (axisOrigin)
vAxis.GetXAxis (xVect)
vAxis.GetYAxis (yVect)
vAxis.GetZAxis (zVect)

'these vectors need to be normalized
NormalizeVector xVect, xVect
NormalizeVector yVect, yVect
NormalizeVector zVect, zVect

'display the Coordinate system data in VBA immediate window
Debug.Print "ORIGIN: " & axisOrigin(0) & ", " & axisOrigin(1) & ", " & axisOrigin(2)
Debug.Print "Vect DX: " & xVect(0) & ", " & xVect(1) & ", " & xVect(2)
Debug.Print "Vect DY: " & yVect(0) & ", " & yVect(1) & ", " & yVect(2)
Debug.Print "Vect DZ: " & zVect(0) & ", " & zVect(1) & ", " & zVect(2)

'loop through all the points getting each coordinate, and transform it into the axis system coordinate
Dim globalCoords(2)
Dim delta(2)
Dim csCoords(2)
Dim vPx As Object

For i = 1 To visiblePoints.Count
Set vPx = HSF.AddNewPointDatum(visiblePoints.Item(i))
vPx.GetCoordinates (globalCoords)
'Debug.Print "Point : " & vPx.Name & " GLOBAL: X = " & globalCoords(0) / 25.4 & " Y = " & globalCoords(1) / 25.4 & " Z = " & globalCoords(2) / 25.4 & " (Units = in)"

'vector from cs origin to point
delta(0) = globalCoords(0) - axisOrigin(0)
delta(1) = globalCoords(1) - axisOrigin(1)
delta(2) = globalCoords(2) - axisOrigin(2)

'determine components along cs axis
csCoords(0) = DotProduct(delta, xVect)
csCoords(1) = DotProduct(delta, yVect)
csCoords(2) = DotProduct(delta, zVect)

'output the results to VBA
'Debug.Print "Point : " & vPx.Name & " CS: X = " & csCoords(0) / 25.4 & " Y = " & csCoords(1) / 25.4 & " Z = " & csCoords(2) / 25.4 & " (Units = in)"
For j = 0 To 2
xl.ActiveCell.Offset(0, j).Value = csCoords(j) / 25.4
Next

xl.ActiveCell.Offset(1, 0).Select
Next


End Sub

'----------------------------------------------------------------------------

Public Function DotProduct(vect1(), vect2()) As Double
DotProduct = vect1(0) * vect2(0) + vect1(1) * vect2(1) + vect1(2) * vect2(2)
End Function

'----------------------------------------------------------------------------
Public Sub NormalizeVector(invect(), ByRef normvect())
Dim mag As Double
mag = Sqr(invect(0) * invect(0) + invect(1) * invect(1) + invect(2) * invect(2))
If mag < 0.0000001 Then Call Err.Raise(1001, , "Zero length vector cannot be normalized")
normvect(0) = invect(0) / mag
normvect(1) = invect(1) / mag
normvect(2) = invect(2) / mag
End Sub


Thanks for all of your insight!!

Branden

COE Administrator

Measure from Axis System
(in response to COE Administrator)
When I try to use this code within a macro that I have in an Excel spreadsheet, I recieve the message 'Zero length vector cannot be normalized.' I believe this is being caused from the variables 'xVect', 'yVect' and 'zVect' to be blank. Thus the value of 'mag' is zero...or less than the .0000001 that is called out in the NormalizeVector subroutine.

Can anyone help me figure out why I am recieving blank values into those variables when I try to extract the definition of the axis system that was picked?

Thanks in advance.
Dean