Using VectorArithmetic.Vector3

The NXOpen.VectorArithmetic Namespace has three classes: Matrix3, Quaternion and Vector3. The
example journal below shows the ease that the vector3 object can be created and used. The code
ask the user to select a datum plane and a datum axis and then creates a point on the datum plane
at the intersection point with the datum axis direction. The journal will not work if the datum plane
normal is perpendicular to the datum axis.

The specific example can easily be extended to other cases. For example the plane could be defined
by two axis. The plane normal is then obtained using the cross product of the two axis. Similarly
defining a point not on the plane and a projection vector defined in any of a number of ways can
also be used.

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpenUI
Imports NXOpen.VectorArithmetic
 
Module ProjectionPoint2
    Dim s As Session = Session.GetSession()
    Dim ui As UI = ui.GetUI()
    Dim ufs As UFSession = UFSession.GetUFSession()
    Dim wp As Part = s.Parts.Work
 
    Sub Main()
        Dim dPlane1 As DatumPlane = Nothing
        Dim dAxis1 As DatumAxis = Nothing
        Dim pointTag As Tag = Tag.Null
        ' select a datum plane
        Dim response1 As Selection.Response = select_a_datumPlane(dPlane1)
        ' select a datum axis
        Dim response2 As Selection.Response = select_a_datumAxis(dAxis1)
        ' get datum plane data
        Dim dplaneOrigin1 As Point3d = dPlane1.Origin
        Dim dplaneOrigin2 As Vector3 = New Vector3(dplaneOrigin1.X, dplaneOrigin1.Y, dplaneOrigin1.Z)
        Dim dplaneNormal1 As Vector3d = dPlane1.Normal
        Dim dplaneNormal2 As Vector3 = New Vector3(dplaneNormal1.X, dplaneNormal1.Y, dplaneNormal1.Z)
        ' get datum axis data
        Dim daxisOrigin1 As Point3d = dAxis1.Origin
        Dim daxisOrigin2 As Vector3 = New Vector3(daxisOrigin1.X, daxisOrigin1.Y, daxisOrigin1.Z)
        Dim daxisDirection1 As Vector3d = dAxis1.Direction
        Dim daxisDirection2 As Vector3 = New Vector3(daxisDirection1.X, daxisDirection1.Y, daxisDirection1.Z)
        ' determine point on dplane
        ' subtraction  of dplaneOrigin - daxisOrigin
        Dim subvector1 As Vector3 = dplaneOrigin2 - daxisOrigin2
        ' dplaneNormal dot subpoint1
        Dim sub1 As Double = dplaneNormal2.Dot(subvector1)
        ' dplaneNormal2 dot daxisDirection2
        Dim sub2 As Double = dplaneNormal2.Dot(daxisDirection2)
        ' w1 is the parameter value of a line from daxisOrigin to the dplane along daxisNormal
        Dim w1 As Double = sub1 / sub2
        ' calculate the point on the dpane
        ' scale daxisDirection2
        Dim scaleddaxis1 As Vector3 = daxisDirection2 * w1
        ' add daxisorigin2 plus scaleddaxis1
        Dim finalvector As Vector3 = daxisOrigin2 + scaleddaxis1
        Dim pointOnDplane As Point3d = New Point3d(finalvector.x, finalvector.y, finalvector.z)
        ' create the point
        Dim pointobj1 As Point = wp.Points.CreatePoint(pointOnDplane)
        pointobj1.SetVisibility(SmartObject.VisibilityOption.Visible)
End1:
    End Sub
 
    Public Function select_a_datumPlane(ByRef dplane As DatumPlane) As Selection.Response
        Dim message As String = "Select a datum plane"
        Dim selectionMask_array(0) As Selection.MaskTriple
        With selectionMask_array(0)
            .Type = UFConstants.UF_datum_plane_type
            .Subtype = 0
            .SolidBodySubtype = 0
        End With
        Dim cursor As Point3d = Nothing
        Dim resp As Selection.Response = _
        ui.SelectionManager.SelectTaggedObject("Dplane Selection", message, _
            Selection.SelectionScope.WorkPart, _
            Selection.SelectionAction.ClearAndEnableSpecific, _
            False, False, selectionMask_array, dplane, cursor)
        If resp = Selection.Response.ObjectSelected Or _
           resp = Selection.Response.ObjectSelectedByName Then
            Return Selection.Response.Ok
        ElseIf resp = Selection.Response.Back Then
            Return Selection.Response.Back
        Else
            Return Selection.Response.Cancel
        End If
    End Function
 
    Public Function select_a_datumAxis(ByRef daxis As DatumAxis) As Selection.Response
        Dim message As String = "Select a datum axis"
        Dim selectionMask_array(0) As Selection.MaskTriple
        With selectionMask_array(0)
            .Type = UFConstants.UF_datum_axis_type
            .Subtype = 0
            .SolidBodySubtype = 0
        End With
        Dim cursor As Point3d = Nothing
        Dim resp As Selection.Response = _
        ui.SelectionManager.SelectTaggedObject("DAxis Selection", message, _
            Selection.SelectionScope.WorkPart, _
            Selection.SelectionAction.ClearAndEnableSpecific, _
            False, False, selectionMask_array, daxis, cursor)
        If resp = Selection.Response.ObjectSelected Or _
           resp = Selection.Response.ObjectSelectedByName Then
            Return Selection.Response.Ok
        ElseIf resp = Selection.Response.Back Then
            Return Selection.Response.Back
        Else
            Return Selection.Response.Cancel
        End If
    End Function
 
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
        'Unloads the image immediately after execution within NX
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
    End Function
End Module

Comments

Seems ridiculous. Why do we need a new VectorArithmetic.Vector3 class; we already have NXOpen.Vector3d. Similarly, why do we need VectorArithmetic.Matrix3 when we already have NXOpen.Matrix3x3. Looks like the people who implemented the VectorArithmetic class didn't know anything about the existing types. And, to make matters worse, the components of a Vector3 are single-precision floats (in NX8.5), not doubles.

The SNAP Position, Vector, and Orientation classes are a far better design. And these classes are available in the free MiniSNAP version, so you can use them even if you don't have a SNAP license.

Here's what the computational part of the code looks like if you use MiniSnap (put Imports MiniSnap at the top of the file):

' Get datum plane data
Dim dplaneOrigin As Position = dPlane.Origin
Dim dplaneNormal As Vector = dPlane.Normal
 
' Get datum axis data
Dim daxisOrigin As Position = dAxis.Origin
Dim daxisDirection As Vector = dAxis.Direction
 
' Calculation of point on dplane. Vector math.
Dim subvector As Vector = dplaneOrigin - daxisOrigin
Dim sub1 As Double = dplaneNormal*subvector
Dim sub2 As Double = dplaneNormal*daxisDirection
Dim w1 As Double = sub1 / sub2    
Dim pointOnDplane As Position = daxisOrigin + w1*daxisDirection

I have no issue with the comment that Snap is much more simpler to code. If a user does not use Snap then the added VectorArithmetic namespace can be useful for the following reasons.
1. We cannot do add, subtract, divide using the +, -, / operators using vector3d. These operator can be used with vector3 directly
2. We cannot do dot or cross product of Vector3d directly. We have two ways of doing this using Vector3d. One is to use UF_VEC wrapper functions. However one needs to use Double(2) array rather then Vector3d.X, Vector3d.Y and Vector3d.Z values. As I have done, write ones own functions which use Vector3d values

Similar arguments apply to matrix3 versus matrix3x3

Frank Swinkels

I agree that Vector3d and Point3d are brain-dead.

But MiniSNAP is free. Everyone has it. It includes the Position and Vector classes. I don't see why anyone would want to use the VectorArithmetic classes instead.

Another benefit of the Snap/MiniSnap classes ... they are highly interoperable with Point3d and Vector3d, because implicit conversions are performed behind the scenes. In my code above, there are several examples of this.