Continue to Site

Eng-Tips is the largest engineering community on the Internet

Intelligent Work Forums for Engineering Professionals

  • Congratulations IFRs on being selected by the Eng-Tips community for having the most helpful posts in the forums last week. Way to Go!

NX8 Journaling: Creation of a datum CSYS from plane and point data imported from a journal 1

Status
Not open for further replies.

kfraysur

Bioengineer
Feb 4, 2010
42
I am looking to add to a journal to create some datum CSYS.

Currently, the journal will path to and import two text files. The first text file contains coordinates for three sets of points that are used to create a plane. Big shoutout to FrankSwinks for helping me with that task in this thread: thread561-317741. That code looks like this:

Code:
Dim planesFile As String
Dim linestring As String = Nothing
Dim testArray() As String
Dim pnt1(2) As Double
Dim pnt2(2) As Double
Dim pnt3(2) As Double
Dim temptag As Tag = Tag.Null
Dim name1 As String = Nothing


planesFile = [highlight #FCE94F]FILE PATH DATA GOES HERE[/highlight] 

' read data and create datum planes
Dim sr As StreamReader = File.OpenText(planesFile)
      	
Try
   Do While sr.Peek >= 0
         linestring = sr.ReadLine
         testArray = Split(linestring, ",", 10)
         pnt1(0) = CType(testArray(0), Double)
         pnt1(1) = CType(testArray(1), Double)
         pnt1(2) = CType(testArray(2), Double)
         pnt2(0) = CType(testArray(3), Double)
         pnt2(1) = CType(testArray(4), Double)
         pnt2(2) = CType(testArray(5), Double)
         pnt3(0) = CType(testArray(6), Double)
         pnt3(1) = CType(testArray(7), Double)
         pnt3(2) = CType(testArray(8), Double)
         name1 = testArray(9)
         CreateDatumPlane(pnt1, pnt2, pnt3, name1)
   Loop
         Catch ex As Exception
            MsgBox("Wrong data format")
End Try

sr.Close()
sr.Dispose()

The second text file contains coordinates for sets of three points. Each set will correspond to one of the planes imported from the previous file, and the third point in each group will intersect with the corresponding datum plane previously created (so point 3 will intersect with plane 1, point 6 will intersect with plane 2, and so on) These points are imported as below (Big ups to cowski in this thread: thread561-284673 for the assist here):

Code:
Dim pointsFile as String
Dim num_points As Long
Dim x As Double
Dim y As Double
Dim z As Double
Dim strlines() As String
Dim strline() As String

'initializing variables for the alignment line on layer 62
Dim AlignLinePoint1 as Point3d
Dim AlignLinePoint2 as Point3d 

pointsFile = [highlight #FCE94F]FILE PATH DATA GOES HERE[/highlight]  

Dim tmpstream As StreamReader = File.OpenText(pointsFile)

'read the points into an array
'Load content of file to strLines array
strlines = tmpstream.ReadToEnd().Split(Environment.NewLine)
' Count number of points
num_points = UBound(strlines)
Dim i As Integer
for i = 0 to num_points - 1
	strline = strlines(i).Split(",")
	x = CDbl(strline(0))
	y = CDbl(strline(1))
	z = CDbl(strline(2))
	Dim coordinates1 As Point3d = New Point3d(x, y, z)
	Dim point1 As Point
	point1 = workPart.Points.CreatePoint(coordinates1)
	point1.SetVisibility(SmartObject.VisibilityOption.Visible)
	point1.RedisplayObject()
	coordinates1 = nothing
	point1 = nothing

	'Saves x,y,and z coordinates for the Alignment Line Point 1
	If i = 2 Then
		AlignLinePoint1.x = x
		AlignLinePoint1.y = y
		AlignLinePoint1.z = z
	End If	

	'Saves x,y,and z coordinates for the Alignment Line Point 2
	If i = num_points - 1 Then
		AlignLinePoint2.x = x
		AlignLinePoint2.y = y
		AlignLinePoint2.z = z

	End If

next

The previous code also saved the coordinates of the first and last point that intersected with the created planes. I use these points to create a line and find the midpoint of that line in the following code (Big ups to cowski again here as I got this info from his excellent site [URL unfurl="true"]http://www.nxjournaling.com[/url]):

Code:
workPart.Curves.CreateLine(AlignLinePoint1, AlignLinePoint2)
'create scalar representing the 50% distance between two points (midpoint)
Dim distanceScalar As Scalar
distanceScalar = workPart.Scalars.CreateScalar(0.5, Scalar.DimensionalityType.None, SmartObject.UpdateOption.WithinModeling)
 
'create midpoint between Import Points of DPF1 and the last DPF
'Next lines basically shift the point types to 'Point' instead of 'Point3d' due to the incompatibility of the distance scalar 
'function for use with the point creation at the midline between two points.
Dim ToeLinePoint1 as Point = workPart.Points.CreatePoint(AlignLinePoint1)
Dim ToeLinePoint2 as Point = workPart.Points.CreatePoint(AlignLinePoint2)
Dim AlignMidPoint As Point
AlignMidPoint = workPart.Points.CreatePoint(ToeLinePoint1, ToeLinePoint2, distanceScalar, SmartObject.UpdateOption.WithinModeling)
AlignMidPoint.RemoveParameters()
AlignMidPoint.SetVisibility(SmartObject.VisibilityOption.Visible)

So now that we've talked about what I can do, now I want to shift gears to what I want to do. I would like this journal to use the created points, planes, and lines to create a datum CSYS that will be oriented such that the X-axis is normal the the created datum plane, the Y-axis is pointing back toward the midpoint of the line we previously created, and its origin is at the point that intersects with the datum plane. I'm sure I worded this poorly, so I have attached a picture.

Any help would be greatly appreciated. Thanks in advance for your time and thanks for reading all this.
 
Replies continue below

Recommended for you

Unless you really want to create all the geometry that you have been indicating (planes and line) I think it is possible to create the Datum CSYS directly as follows:

Given three point data defining plane corner point P1, plane X direction point P2, and plane Y direction point P3 and two data point for a line P3 - P4 then using these five point coordinates we can determine the CSYS origin from the mathematical intersection of the line P1-P2 with the plane defined by P1,P2 and P3. The CSYS orientation is defined from the plane points P1, P2 and P3.

Before I write the code is this what you want?

Frank Swinkels
 
That sounds correct. As for the geometry I have previously talked about, it is already being created and is necessary for the file to function appropriately, so it will be there regardless.
 
Here is a first journal to create a datum csys based on selected datum plane and line.

Code:
Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.Features
Imports NXOpen.UF

Module DatumCSYS
    Dim s As Session = Session.GetSession()
    Dim ufs As UFSession = UFSession.GetUFSession()
    Dim workPart As Part = s.Parts.Work
    Sub Main()

        Dim response As Selection.Response = Nothing
        Dim response2 As Selection.Response = Nothing
        Dim dplane1 As DatumPlane = Nothing
        Dim line1 As Line = Nothing
Start1:
        response = select_a_Dplane(dplane1)
        If response = Selection.Response.Back Then GoTo End1
        If response = Selection.Response.Cancel Then GoTo End1
        response2 = select_a_Line(line1)
        If response2 = Selection.Response.Back Then GoTo Start1 ' Select a new face
        If response2 = Selection.Response.Cancel Then GoTo End1

        Dim originonplane As Point3d = GetLinePlaneIntersectionPoint(dplane1, line1)

        CreateDatumCSYS(dplane1, line1, originonplane)
End1:
    End Sub

    Function select_a_Dplane(ByRef obj As DatumPlane) As Selection.Response
        Dim ui As UI = ui.GetUI()
        Dim selectionMask_array(1) 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.SelectObject("Select a Datum Plane", "Select a Datum Plane", _
            Selection.SelectionScope.WorkPart, _
            Selection.SelectionAction.ClearAndEnableSpecific, _
            False, False, selectionMask_array, obj, 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
    Function select_a_Line(ByRef ln1 As Line)
        Dim ui As UI = ui.GetUI()
        Dim mask(0) As Selection.MaskTriple
        With mask(0)
            .Type = UFConstants.UF_line_type
            .Subtype = 0
            .SolidBodySubtype = 0
        End With
        Dim cursor As Point3d = Nothing
        Dim resp As Selection.Response = _
        ui.SelectionManager.SelectObject("Select a Line", "Select a Line", _
            Selection.SelectionScope.AnyInAssembly, _
            Selection.SelectionAction.ClearAndEnableSpecific, _
            False, False, mask, ln1, 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 GetLinePlaneIntersectionPoint(ByVal dplane1 As DatumPlane, ByVal line1 As Line) As Point3d
        ' get intersection pt of line on datum plane
        ' datum plane data
        Dim dplaneOrigin(2) As Double
        Dim dplaneNormal(2) As Double
        ufs.Modl.AskDatumPlane(dplane1.Tag, dplaneOrigin, dplaneNormal)
        ' line data for line pnt and line vector
        Dim startpnt As Point3d = line1.StartPoint
        Dim endpnt As Point3d = line1.EndPoint
        Dim pnt1() As Double = {startpnt.X, startpnt.Y, startpnt.Z}
        Dim pnt2() As Double = {endpnt.X, endpnt.Y, endpnt.Z}
        Dim distance1 As Double = Nothing
        Dim distance2 As Double = Nothing
        Dim linevec(2) As Double
        Dim tol1 As Double = 0.001
        Dim mag1 As Double = Nothing
        ufs.Vec3.Distance(dplaneOrigin, pnt1, distance1)
        ufs.Vec3.Distance(dplaneOrigin, pnt2, distance2)
        Dim point1(2) As Double
        Dim sub1 As Double = Nothing
        Dim sub2 As Double = Nothing
        Dim w As Double = Nothing
        If distance1 > distance2 Then
            ' use startpnt and pnt1
            ufs.Vec3.Sub(pnt1, pnt2, linevec)
            ufs.Vec3.Unitize(linevec, tol1, mag1, linevec)
            ' dplaneOrigin - line origin
            point1(0) = dplaneOrigin(0) - pnt1(0)
            point1(1) = dplaneOrigin(1) - pnt1(1)
            point1(2) = dplaneOrigin(2) - pnt1(2)
            ' dplaneNormal dot point1
            ufs.Vec3.Dot(dplaneNormal, point1, sub1)
            ' dplaneNormal dot linevec
            ufs.Vec3.Dot(dplaneNormal, linevec, sub2)
            ' w is the parameter value of a line from the line point to the dplane along line vector
            w = sub1 / sub2
            ' calculate the point on the dpane
            point1(0) = pnt1(0) + w * linevec(0)
            point1(1) = pnt1(1) + w * linevec(1)
            point1(2) = pnt1(2) + w * linevec(2)
        Else
            ' use endpnt and pnt2
            ufs.Vec3.Sub(pnt2, pnt1, linevec)
            ufs.Vec3.Unitize(linevec, tol1, mag1, linevec)
            ' dplaneOrigin - line origin
            point1(0) = dplaneOrigin(0) - pnt2(0)
            point1(1) = dplaneOrigin(1) - pnt2(1)
            point1(2) = dplaneOrigin(2) - pnt2(2)
            ' dplaneNormal dot point1
            ufs.Vec3.Dot(dplaneNormal, point1, sub1)
            ' dplaneNormal dot linevec
            ufs.Vec3.Dot(dplaneNormal, linevec, sub2)
            ' w is the parameter value of a line from the line point to the dplane along line vector
            w = sub1 / sub2
            ' calculate the point on the dpane
            point1(0) = pnt2(0) + w * linevec(0)
            point1(1) = pnt2(1) + w * linevec(1)
            point1(2) = pnt2(2) + w * linevec(2)
        End If
        ' create the point
        Dim pointTag As Tag = Tag.Null
        ufs.Curve.CreatePoint(point1, pointTag)
        Dim pnt3d As Point3d = New Point3d(point1(0), point1(1), point1(2))
        Return pnt3d
    End Function

    Public Sub CreateDatumCSYS(ByVal dplane1 As DatumPlane, ByVal line1 As Line, ByVal originpt As Point3d)
        ' datum plane data
        Dim dplaneOrigin(2) As Double
        Dim xvec(2) As Double
        ufs.Modl.AskDatumPlane(dplane1.Tag, dplaneOrigin, xvec)
        Dim startpnt As Point3d = line1.StartPoint
        Dim endpnt As Point3d = line1.EndPoint
        Dim linevec(2) As Double
        ' get midpoint of line
        Dim midpnt(2) As Double
        midpnt(0) = (startpnt.X + endpnt.X) / 2.0
        midpnt(1) = (startpnt.Y + endpnt.Y) / 2.0
        midpnt(2) = (startpnt.Z + endpnt.Z) / 2.0
        Dim yvec(2) As Double
        Dim zvec(2) As Double
        Dim originpt1() As Double = {originpt.X, originpt.Y, originpt.Z}
        ufs.Vec3.Sub(midpnt, originpt1, yvec)
        ufs.Vec3.Cross(xvec, yvec, zvec)
        If xvec(2) > 0.0 Then
            If yvec(2) > 0.0 Then
                ufs.Vec3.Cross(zvec, xvec, yvec)
            Else
                ufs.Vec3.Cross(xvec, zvec, yvec)
            End If
        Else
            If yvec(2) < 0.0 Then
                ufs.Vec3.Cross(zvec, xvec, yvec)
            Else
                ufs.Vec3.Cross(xvec, zvec, yvec)
            End If
        End If

        Dim coordsx As Point3d = New Point3d(originpt.X + xvec(0), originpt.Y + xvec(1), originpt.Z + xvec(2))
        Dim coordsy As Point3d = New Point3d(originpt.X + yvec(0), originpt.Y + yvec(1), originpt.Z + yvec(2))
        Dim nullFeatures_Feature As Features.Feature = Nothing
        Dim datumCsysBuilder1 As Features.DatumCsysBuilder
        datumCsysBuilder1 = workPart.Features.CreateDatumCsysBuilder(nullFeatures_Feature)
        Dim point1 As Point
        point1 = workPart.Points.CreatePoint(originpt)
        Dim point2 As Point
        point2 = workPart.Points.CreatePoint(coordsx)
        Dim point3 As Point
        point3 = workPart.Points.CreatePoint(coordsy)
        Dim xform1 As Xform
        xform1 = workPart.Xforms.CreateXform(point1, point2, point3, SmartObject.UpdateOption.WithinModeling, 1.0)
        Dim cartesianCoordinateSystem1 As CartesianCoordinateSystem
        cartesianCoordinateSystem1 = workPart.CoordinateSystems.CreateCoordinateSystem(xform1, SmartObject.UpdateOption.WithinModeling)
        datumCsysBuilder1.Csys = cartesianCoordinateSystem1
        datumCsysBuilder1.DisplayScaleFactor = 1.25
        Dim nXObject1 As NXObject
        nXObject1 = datumCsysBuilder1.Commit()
        datumCsysBuilder1.Destroy()
    End Sub
    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

Regards

Frank Swinkels
 
Thanks for the help Frank. I believe I can use this to create something that will automatically generate the CSYS without any manual user input. My next step will be importing a seperate part and aligning it to the created datum CSYS. I'm not sure when I will get to this, but once I get it a little more automated, I will post the code for others to view.

Again, thanks for taking the time.
 
So I was able to use the code from Frank in this thread to automate the datum CSYS creation. My issue is that the direction of the Y-axis seems to be inconsistent and I can't figure out why.

In Frank's code, the user specifies the plane normal of the X-axis, the line for the direction of the Y-axis, and the origin point of the datum CSYS. From the previous code I had done, the journal reads in a file with three points and creates a plane. I save these planes in an array to call later to pass to the CreateDatumCSYS() function in Frank's code. The origin point of the CSYS is established by every third point in the text file that is imported by the journal in the second bit of code I posted, and this point location is passed to the CreateDatumCSYS() function at each location.

The problem appears to be the line that is passed as the second variable in the CreateDatumCSYS() function. This line will always have a starting point that is the same as the desired origin point of the CSYS at that location (a known value as previously stated). The ending point of the line will always be the AlignMidPoint variable, which is a point I establish in the third bit of code in the original post. I use these two points to create the line that is passed as the second variable in the CreateDatumCSYS() function. When I do this, there is an inconsistency in the direction of the resulting Y-axis of the CSYS that is created, and it seems to not matter the order of the points that are used to create the line passed in the CreateDatumCSYS() function.

I'm not sure how clear that last paragraph is, but I always want the Y-axis of the created datum CSYS to be pointing back toward the AlignMidPoint defined earlier (third bit of code in the original post).

________________________________________________________________________________________________________________________________________


On a separate note but something I touched on in the last post, how difficult would it be to take all points, lines, bodies, everything from all layers and move them from a defined CSYS to the part's absolute coordinate system? This would essentially automate the process of doing a 'Move Object' function of the 'CSYS to CSYS' variety and selecting everything in the part.

Thanks to Frank for the help he has given already and thanks to anyone else who might be able to lend a hand.

 
Regarding the orientation of the csys, in my example code I did test for two conditions for determining the csys orientation when in fact I think the code will need to consider four conditions. I will have another look at it.

Frank Swinkels
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor