Obtaining information from datum axis

Hi all! I am working on a program that let's the user mark points on a piece and returns a text file with the coordinates of each point the user defined, but I also need to retrieve the angle of the face each point was made on, to solve this I found the Datum Axis option but I don't know how to retrieve the direction (Unit Vector with 3 components), can anyone tell me how to do that?

Thanks in advance!

I recommend a different approach.

If you have the (u,v) parameter values at the point, use NXOpen.UF.UFEvalsf.Evaluate to get the surface normal at the point.

If you only have the (x,y,z) coordinates of the point, first use NXOpen.UF.UFEvalsf.FindClosestPoint to get the (u,v) values, and then proceed as above.

Using SNAP, the code is just

Dim uv As Double() = surf.Parameters(pt)
Dim norm As Vector = surf.Normal(uv)

It's a bit more complicated using NX/Open, but the idea is exactly the same.

But, to answer your original question ... a DatumAxis object has a Direction property, which is a Vector3d.

I'm using Visual Basic, does the U, V approach works with VB?

Also how do I get the direction of the datum axis in respect to a WCS defined by the user?

Thanks for the reply!

Orlando

> does the U, V approach works with VB?

Yes. The two lines I showed are VB code that calls SNAP functions. If you don't have SNAP, then you have to use the functions in NXOpen.UF.UFEvalsf instead. Again, you can call these functions from VB code.

> how do I get the direction of the datum axis in respect to a WCS

The DatumAxis.Direction property will give you a vector whose components are expressed wrt the ACS. To map to WCS, use Snap.NX.CoordinateSystem.MapAcsToWcs or NXOpen.UF.UFCsys.MapPoint. Note that the latter maps *points*, not vectors, so you'll have to map two points and then subtract to get a vector. The SNAP function can map vectors directly.

Thanks for the reply, I do not have SNAP, I tried using the NXOpen.UF.UFEvalsf but I don't know what the parameters mean.

Public Sub FindClosestPint(evaluator As System.IntPtr, point() As Double, ByRef srf_pos3 As NXOpen.UF.UFEvalsf.Pos3)

Public Sub Evaluate(evaluator As System.Int.Ptr, deriv_flag As Integer, uv_pair() As Double, ByRef surf_eval As NxOpen.UF.ModlSrfValue)

Can you please explain them to me?

Orlando

What code do you have so far to select points/surfaces?

The code lets the user open a CAD file, then enters modeling and opens the Point window. From the code I can already change the coordinates from absolute to WCS. But i want to know the angle of the face each point is made in reference to the WCS.

Public Sub puntos()

theSession = Session.GetSession()
theUFSession = UFSession.GetUFSession()

Dim theUI As UI = UI.GetUI()

'Insert code here
Dim base_pt As Double() = New Double(2) {}

Dim cont As Integer
cont = 0

'Dim arreglopunto() As String = {1, cont}
Dim arreglopuntox() As Double = {1, cont}
Dim arreglopuntoy() As Double = {1, cont}
Dim arreglopuntoz() As Double = {1, cont}

While select_point("Select Point", base_pt) = UFConstants.UF_UI_OK

'theUI.NXMessageBox.Show("Selected Point", NXMessageBox.DialogType.Information, (("X:" & base_pt(0).ToString() & vbLf & "Y:") + base_pt(1).ToString() & vbLf & "Z:") + base_pt(2).ToString())
Dim workPart As Part = theSession.Parts.Work

Dim destinationPoint1 As Point3d = New Point3d
destinationPoint1.X = base_pt(0)
destinationPoint1.Y = base_pt(1)
destinationPoint1.Z = base_pt(2)

Dim point3 As Point
point3 = workPart.Points.CreatePoint(destinationPoint1)

Dim nullFeatures_Feature As Features.Feature = Nothing
Dim pointFeatureBuilder1 As Features.PointFeatureBuilder
pointFeatureBuilder1 = workPart.BaseFeatures.CreatePointFeatureBuilder(nullFeatures_Feature)

pointFeatureBuilder1.Point = point3

Dim nXObject1 As NXObject
nXObject1 = pointFeatureBuilder1.Commit()

Dim doublee As Point3d = point3.Coordinates

If cont = 0 Then
MsgBox("-El eje de las X debe quedar apuntando a la derecha y el eje Z hacia arriba" & (Chr(10)) & (Chr(10)) & "-Si hace falta acomodar da doble click en el eje de coordenadas que aparecerá en la pieza" & (Chr(10)) & (Chr(10)) & "-Al finalizar presiona Esc")
Dim origin1 As Point3d = New Point3d(doublee.X, doublee.Y, doublee.Z)
Dim matrix1 As Matrix3x3 = New Matrix3x3()
workPart.WCS().SetOriginAndMatrix(origin1, matrix1)

Else : End If

'Manda llamar a la función que cambia el eje de coordenadas absoluto al definido por el usuario
doublee = Abs2WCS(doublee)

If cont = 0 Then

Else
Dim lw As ListingWindow = theSession.ListingWindow
lw.Open()
lw.WriteLine(doublee.ToString)
End If

'ReDim Preserve arreglopunto(cont)
ReDim Preserve arreglopuntox(cont)
ReDim Preserve arreglopuntoy(cont)
ReDim Preserve arreglopuntoz(cont)

For i As Integer = 0 To cont

arreglopuntox(cont) = doublee.X
arreglopuntoy(cont) = doublee.Y
arreglopuntoz(cont) = doublee.Z

Next i

Dim crearArchivo As String = "C:\Users\sse\Desktop\" & nombreArchivoSinExt & ".txt"
Dim fs As FileStream = Nothing

fs = File.Create(crearArchivo)
Using fs
End Using

Using sw As StreamWriter = New StreamWriter(crearArchivo)

sw.WriteLine("Aquí va la primera parte del programa")

For i As Integer = 1 To cont
sw.WriteLine("Punto " & i & ": X=" & arreglopuntox(i) & " Y=" & arreglopuntoy(i) & " Z=" & arreglopuntoz(i))
sw.WriteLine("")

Next i
End Using

cont = cont + 1

End While

'cierra el programa
If select_point("Select Point", base_pt) = UFConstants.UF_UI_CANCEL Then
varcerrar = 1
Else
varcerrar = 0
End If
If varcerrar = 1 Then
cerrar()
Dim pProcess() As Process = System.Diagnostics.Process.GetProcessesByName("ugraf")
For Each p As Process In pProcess
p.Kill()
Next
End If

End Sub

'Función para retornar valores de puntos seleccionados
Public Shared Function select_point(ByVal cue As String, ByRef base_pt As Double()) As Integer
Dim point_tag As NXOpen.Tag = NXOpen.Tag.Null
Dim response As Integer = 0
Dim base_method As UFUi.PointBaseMethod = UFUi.PointBaseMethod.PointOnSurfacePt

theUFSession.Ui.LockUgAccess(NXOpen.UF.UFConstants.UF_UI_FROM_CUSTOM)
theUFSession.Ui.PointConstruct(cue, base_method, point_tag, base_pt, response)
theUFSession.Ui.UnlockUgAccess(NXOpen.UF.UFConstants.UF_UI_FROM_CUSTOM)
Return response
End Function

'Función para cambiar las coordenadas de absolutas a las definidas por el usuario
Public Shared Function Abs2WCS(ByVal inPt As Point3d) As Point3d
Dim pt1(2), pt2(2) As Double
Dim ufs As UFSession = UFSession.GetUFSession()

pt1(0) = inPt.X
pt1(1) = inPt.Y
pt1(2) = inPt.Z

ufs.Csys.MapPoint(UFConstants.UF_CSYS_ROOT_COORDS, pt1, _
UFConstants.UF_CSYS_ROOT_WCS_COORDS, pt2)

Abs2WCS.X = pt2(0)
Abs2WCS.Y = pt2(1)
Abs2WCS.Z = pt2(2)

End Function

End Class

Orlando

Here is how you do it using SNAP functions

Dim faceTag As NXOpen.Tag = ... whatever
Dim refPoint As Position = ... whatever
Dim uv As Double() = face.Parameters(refPoint)
Dim facePoint As Position = face.Position(uv)
Dim faceNormal As Vector = face.Normal(uv)
Dim facePointWCS As Position = Snap.NX.CoordinateSystem.MapAcsToWcs(facePoint)
Dim faceNormalWCS As Vector = Snap.NX.CoordinateSystem.MapAcsToWcs(faceNormal)

And here's how you do it using NXOpen functions

Dim faceTag As NXOpen.Tag = ... whatever
Dim refPoint As Double() = ... whatever
Dim ufs As NXOpen.UF.UFSession = NXOpen.UF.UFSession.GetUFSession()
Dim evalStruct As System.IntPtr
ufs.Evalsf.Initialize2(faceTag, evalStruct)
Dim surfPointPos As NXOpen.UF.UFEvalsf.Pos3
ufs.Evalsf.FindClosestPoint(evalStruct, refPoint, surfPointPos)
Dim uv As Double() = surfPointPos.uv
Dim facePoint As Double() = surfPointPos.pnt3
Dim surfPointData As NXOpen.UF.ModlSrfValue
ufs.Evalsf.Evaluate(evalStruct, 0, uv, surfPointData)
Dim faceNormal As Double() = surfPointData.srf_unormal
ufs.Evalsf.Free(evalStruct)
' Map point and normal to WCS

Sorry. This line of code

ufs.Evalsf.Evaluate(evalStruct, 0, uv, surfPointData)

should be replaced by these two lines

Dim mode As Integer = NXOpen.UF.UFConstants.UF_MODL_EVAL_UNIT_NORMAL
ufs.Evalsf.Evaluate(evalStruct, mode, uv, surfPointData)

Great, thanks for the reply! But I have another question, how do I obtain the faceTag parameter?

And also the ufs.Evalsf.Free(evalStruct) gives me the following error: Method not found Void NXOpen.UF.UFEvalsf.Free(IntPtr ByRef)

Orlando

If I declare Dim faceTag As NXOpen.Tag = NXOpen.Tag.Null, the next error appears: NXOpen.NXException: The first parameter passed in was invalid.

Orlando

You will need a reference to the face of interest in your code. How do you know which face to process? Will the user select a face?

No, I do not have that in the code, the user will only mark points, how do I add face selection?

Orlando

If you have access to the GTAC forum, you may want to look at:
https://bbs.industrysoftware.automation.siemens.com/vbulletin/showthread...

Frank Swinkels posted some code that allows face selection and creates a sphere tangent to the face (it also retrieves the face normal at the point). If you don't have access, I'll contact Frank and ask his permission to re-post the code here.

Thank you, I do have access to that forum, let me check the code you posted.

Orlando

I still have problems with the ufs.Evalsf.Free(evalStruct) line.

Also how do I send the refpoint?

Orlando

Unless you are programming in C/C++, I wouldn't worry about calling the Evalsf.Free function; the garbage collector will free up the memory eventually.

Sorry, it should be NXOpen.UF.Evalsf.Free(evalStruct). My apologies.
But you should have been able to look up the "Free" function for yourself. Don't you have any documentation? If you don't, use Visual Studio, or some other good IDE, so that you can get help via the Object Browser.

It think it's safer to call the Free function. If lower-level unmanaged code allocates memory, the .NET garbage collector won't know about this and may not be able to free it, and you'll have a memory leak.

Regarding the faceTag: the user is selecting a face, right? The selection function will either return a tag, or it will return an object from which you can get a tag.

If you are using .NET, you don't need to call the UF_free functions.

From the .NET reference API (Mapping UF to NXOpen -> Miscellaneous structures and types):

Treat all the arguments with the "Output to be freed" annotation as an output parameter. The system takes care of freeing memory.

If you look in the folder called C:\Program Files\Siemens\NX x.x\UGOPEN\SNAP\Examples\More Examples\SphereOnFace
you will find a sample app that might be useful. It lets the user select a face, and indicate a point on the face, and then it places a sphere tangent to the face at the indicated point. So, it does all the stuff with surface points and nomals, and so on.

There's a Vis Studio project in that folder, but the basic code is shown blow:

<\code>
Option Infer On
Option Strict Off
Imports Snap, Snap.Create, Snap.NX.ObjectTypes

Partial Public Class SphereOnFace : Inherits UI.BlockForm

' Member variables of a SphereOnFace object
Dim selectionBlock As Snap.UI.Block.SelectObject
Dim diameterBlock As Snap.UI.Block.Double
Dim flipButton As New Snap.UI.Block.Button
Dim diameter As Double = 10.0
Dim flip As Double = 1.0

'Creates a new SphereOnFace dialog
Public Sub New()

Me.Title = "Sphere On Face" ' Title of dialog

' Create a selection block
selectionBlock = New Snap.UI.Block.SelectObject()
selectionBlock.LabelString = "Select target face"
selectionBlock.Cue = "Please select a face"

' Create a double block to enter diameter
diameterBlock = New Snap.UI.Block.Double("Sphere diameter")
diameterBlock.Value = 10

' Create a button to flip sides
flipButton = New Snap.UI.Block.Button("Flip sides")

' Add the three blocks to the BlockForm
Me.AddBlocks(selectionBlock, diameterBlock, flipButton)

End Sub

Public Shared Sub Main()

Dim myForm As New SphereOnFace() ' Create a dialog
myForm.Show() ' Display it

End Sub

Public Overrides Sub OnShow()

selectionBlock.SetFaceFilter()

End Sub

Public Overrides Sub OnUpdate(changedBlock As Snap.UI.Block.General)

If changedBlock = selectionBlock Then
diameter = diameterBlock.Value
Dim pickPoint = selectionBlock.PickPoint
Dim selectedFace = selectionBlock.SelectedObjects(0)
CreateSphere(pickPoint, selectedFace)
selectedFace.IsHighlighted = False

ElseIf changedBlock = flipButton Then
flip = -flip

End If

End Sub

Private Sub CreateSphere(point As Position, surface As NX.Face)

Dim uv = surface.Parameters(point)
Dim surfPoint = surface.Position(uv)
Dim surfNormal = surface.Normal(uv)
Dim center = surfPoint + flip * 0.5 * diameter * surfNormal
Sphere(center, diameter)

End Sub

End Class