Hole on Datum in reference to WCS

I want to create a Journal that will create holes in reference to WCS. We wan't to have a button which (after placing the WCS on a face ; Z axis perpendicular to plane) will create hole at X,Y coordinates in reference to WCS.

Since AFAIK the only option in UG to position a hole is a sketch or datum, my idea is to create a Datum in WCS, reposition it to the new coords and create a Hole attached to this datum.

UPDATE:

I came up with code that creates Datums and Holes and looks like it works but the problem is that the Datums are broken. Origin is detached from Datum and after modification of one Datum all Datum CSYS are goint to the same point.

Can someone help me with that? I think the problem lies in the fixed reference to "POINT 1" CType(datumCsys2.FindObject("POINT 1")
I wanted to use CType(datumCsys2.Location) but it's a Point3D

I dont really know what effect has the:
rule1
helpPoint1

in .HolePosition.AddToSection(rules1, nullNXOpen_NXObject, nullNXOpen_NXObject, nullNXOpen_NXObject, helpPoint1, NXOpen.Section.Mode.Create, False)

"working" code

' NX 10.0.1.4
' Journal created by wizdar on Mon Mar 21 12:52:39 2016 Mitteleuropäische Zeit
'
Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF

Module NXJournal
Dim theSession As NXOpen.Session = NXOpen.Session.GetSession()
Dim workPart As NXOpen.Part = theSession.Parts.Work
Dim ufs As UFSession = UFSession.GetUFSession()
Dim displayPart As NXOpen.Part = theSession.Parts.Display

Sub Main (ByVal args() As String)

Dim markId1 As NXOpen.Session.UndoMarkId
markId1 = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Visible, "Start")

'How to make body select??
Dim body1 As NXOpen.Body
body1 = SelectSolid()

Dim itargetBodies(0) As NXOpen.Body
itargetBodies(0) = body1

If Not workPart.Preferences.Modeling.GetHistoryMode Then
Throw(New Exception("Create or edit of a Feature was recorded in History Mode but playback is in History-Free Mode."))
End If

CreateHole(0, 0, itargetBodies)
CreateHole(15, 0, itargetBodies)
CreateHole(30, 0, itargetBodies)

End Sub

Sub CreateHole (xcoord As Double, ycoord As Double, targetBodies As NXOpen.Body())

Dim nullNXOpen_Features_Feature As NXOpen.Features.Feature = Nothing

Dim datumCsysBuilder1 As NXOpen.Features.DatumCsysBuilder
datumCsysBuilder1 = workPart.Features.CreateDatumCsysBuilder(nullNXOpen_Features_Feature)

Dim cartesianCoordinateSystem1 As NXOpen.CartesianCoordinateSystem
cartesianCoordinateSystem1 = workPart.WCS.CoordinateSystem

'Define origin

Dim orPt As Point3d
orPt.X = xcoord
orPt.Y = ycoord
orPt.Z = 0
'New origin for CSYS
cartesianCoordinateSystem1.Origin = WCS2Abs(orPt)

datumCsysBuilder1.Csys = cartesianCoordinateSystem1

datumCsysBuilder1.DisplayScaleFactor = 0.5

Dim nXObject1 As NXOpen.NXObject
nXObject1 = datumCsysBuilder1.Commit()

Dim datumCsys2 As NXOpen.Features.DatumCsys = CType(nXObject1, NXOpen.Features.DatumCsys)

'Need to select datum origin.

Dim point1 As NXOpen.Point = CType(datumCsys2.FindObject("POINT 1"), NXOpen.Point)

'Dim point1 As NXOpen.Point = CType(datumCsys2.Location, NXOpen.Point)

datumCsysBuilder1.Destroy()

'Create Hole Part
Dim nullNXOpen_Features_HolePackage As NXOpen.Features.HolePackage = Nothing

Dim holePackageBuilder1 As NXOpen.Features.HolePackageBuilder
holePackageBuilder1 = workPart.Features.CreateHolePackageBuilder(nullNXOpen_Features_HolePackage)

'Point

Dim points1(0) As NXOpen.Point
points1(0) = point1
Dim curveDumbRule1 As NXOpen.CurveDumbRule
curveDumbRule1 = workPart.ScRuleFactory.CreateRuleCurveDumbFromPoints(points1)

Dim rules1(0) As NXOpen.SelectionIntentRule
rules1(0) = curveDumbRule1
Dim nullNXOpen_NXObject As NXOpen.NXObject = Nothing

Dim helpPoint1 As NXOpen.Point3d = New NXOpen.Point3d(0.0, 0.0, 0.0)

With holePackageBuilder1

.HolePosition.AllowSelfIntersection(True)
.HolePosition.AddToSection(rules1, nullNXOpen_NXObject, nullNXOpen_NXObject, nullNXOpen_NXObject, helpPoint1, NXOpen.Section.Mode.Create, False)
.BooleanOperation.Type = NXOpen.GeometricUtilities.BooleanOperation.BooleanType.Subtract
.BooleanOperation.SetTargetBodies(targetBodies)

End With

'Hole Type 6
With holePackageBuilder1

.GeneralHoleForm = Features.HolePackageBuilder.HoleForms.Simple
.HoleDepthLimitOption = Features.HolePackageBuilder.HoleDepthLimitOptions.ThroughBody
.GeneralSimpleHoleDiameter.RightHandSide = "6"
.GeneralSimpleHoleDepth.RightHandSide = "12"
.Tolerance = 0.001

End With

'Commit Hole
Dim nXObject2 As NXOpen.NXObject
nXObject2 = holePackageBuilder1.Commit()

holePackageBuilder1.Destroy()

End Sub

Function SelectSolid() As Body

Dim ui As UI = ui.GetUI
Dim message As String = "Select solid body"
Dim title As String = "Selection"

Dim scope As Selection.SelectionScope = Selection.SelectionScope.WorkPart
Dim keepHighlighted As Boolean = False
Dim includeFeatures As Boolean = True

Dim selectionAction As Selection.SelectionAction = _
Selection.SelectionAction.ClearAndEnableSpecific

Dim selectionMask_array(0) As Selection.MaskTriple
With selectionMask_array(0)
.Type = UFConstants.UF_solid_type
.Subtype = 0
.SolidBodySubtype = UFConstants.UF_UI_SEL_FEATURE_SOLID_BODY
End With

Dim selectedObject As NXObject = Nothing
Dim cursor As Point3d

ui.SelectionManager.SelectObject(message, title, scope, _
selectionAction, includeFeatures, _
keepHighlighted, selectionMask_array, _
selectedObject, cursor)

Dim solid As Body = CType(selectedObject, Body)

If solid Is Nothing Then
Return Nothing
End If

Return solid

End Function

Function Abs2WCS(ByVal inPt As Point3d) As Point3d
Dim pt1(2), pt2(2) As Double

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

Function WCS2Abs(ByVal inPt As Point3d) As Point3d
Dim pt1(2), pt2(2) As Double

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

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

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

End Function

Public Function GetUnloadOption(ByVal dummy As String) As Integer

'Unloads the image when the NX session terminates
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination

End Function

End Module

Post and code updated. It works but in a bad way. DatumCSYS are broken.

Edit:
DatumCSYS look like they are dependant on each other :/. Not only the origin point but also orientation.

Edit2:
Only one CSYS (non-datum)is created and the Datums are linked to the same CSYS. I don't know why Journal is not creating one CSYS for Each Datum.

After 3 days of fighting with UG and different approach I have a working code.
Probably some parts are not necessary, few commented lines are still in, but it works nice.
Both in the context of assembly and part.

I modified the function WCS2Abs to create WCS2Wrk functions by replacing
UF_CSYS_ROOT_COORDS with UF_CSYS_WORK_COORDS.

For some reason I needed to specify the Csys with dialog when in assy.
Best would be if that step could be omitted and to use only WCS position and orientation.

' NX 10.0.1.4
' Journal created by wizdar on Mon Mar 21 12:52:39 2016 Mitteleuropäische Zeit
'
Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF
Imports System.Windows.Forms

Module NXJournal
Dim theSession As NXOpen.Session = NXOpen.Session.GetSession()
Dim workPart As NXOpen.Part = theSession.Parts.Work
Dim ufs As UFSession = UFSession.GetUFSession()
Dim displayPart As NXOpen.Part = theSession.Parts.Display
Dim theUISession As UI = UI.GetUI()

Sub Main (pattern_type() As String)

Dim markId1 As NXOpen.Session.UndoMarkId
markId1 = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Visible, "Start")

If IsNothing(displayPart) Then
'active part required
Return
End If

'9 element orientation matrix of specified csys
'arrays are zero based
Dim myCsys(8) As Double

'3 element array: origin point of specified csys
Dim myOrigin(2) As Double

'tag variable used as input/output for the .SpecifyCsys method
'passing a null tag into the function uses the current WCS as the starting csys
Dim newCsysTag As Tag = Tag.Null

'variable to hold the user specified coordinate system
Dim newCsys As CartesianCoordinateSystem

Dim response As Integer

'If you want to know the option the user used to specify the csys, pass in a variable.
'The initial value of the variable will control the default option shown to the user.
'After the function returns, this variable will hold the actual option used.

'optional message to user
REM MessageBox.Show("Orient manipulator to the desired location/orientation", "Specify Coordinate System", MessageBoxButtons.OK, MessageBoxIcon.Information)
theUISession.LockAccess()

'if you don't care what option was used to specify the csys, simply pass in an integer that specified the default method to show to the user
response = ufs.Ui.SpecifyCsys("Specify Desired Orientation", 5, myCsys, myOrigin, newCsysTag)

theUISession.UnlockAccess()

If response = Selection.Response.Ok Then
'get CartesianCoordinateSystem object from tag
newCsys = Utilities.NXObjectManager.Get(newCsysTag)
displayPart.WCS.SetCoordinateSystem(newCsys)

Else
Return
End If

'How to make body select??
Dim body1 As NXOpen.Body
body1 = SelectSolid()

If not IsNothing(body1) Then

Dim itargetBodies(0) As NXOpen.Body
itargetBodies(0) = body1

Select Case pattern_type(0)
Case "1"
CreateHole(newCsys, 0 , 0, "8H_Blind" ,itargetBodies)
CreateHole(newCsys, 15, 0, "M8_Blind" ,itargetBodies)
CreateHole(newCsys, 45, 0, "8H_Blind" ,itargetBodies)
CreateHole(newCsys, 60, 0, "M8_Blind" ,itargetBodies)

Case "2"
CreateHole(newCsys, 0 , 0, "6H" ,itargetBodies)
CreateHole(newCsys, 15, 0, "M8" ,itargetBodies)
CreateHole(newCsys, 30, 0, "6H" ,itargetBodies)
Case "3"
CreateHole(newCsys, 0 , 0, "6H" ,itargetBodies)
CreateHole(newCsys, 15, 0, "D9" ,itargetBodies)
CreateHole(newCsys, 30, 0, "6H" ,itargetBodies)
CreateHole(newCsys, 45, 0, "D9" ,itargetBodies)

Case "4"
CreateHole(newCsys, 0 , 0, "6H" ,itargetBodies)
CreateHole(newCsys, 15, 0, "M8" ,itargetBodies)
CreateHole(newCsys, 30, 0, "6H" ,itargetBodies)
CreateHole(newCsys, 45, 0, "M8" ,itargetBodies)
Case "5"
CreateHole(newCsys , 0, 0, "6H" ,itargetBodies)
CreateHole(newCsys, 30, 0, "6H" ,itargetBodies)
CreateHole(newCsys, 0, 16, "D9" ,itargetBodies)
CreateHole(newCsys, 0, -16, "D9" ,itargetBodies)
CreateHole(newCsys, 30, 16, "D9" ,itargetBodies)
CreateHole(newCsys, 30, -16, "D9" ,itargetBodies)
Case "6"
CreateHole(newCsys, 0 , 0, "M8" ,itargetBodies)
CreateHole(newCsys, 90, 0, "M8" ,itargetBodies)
CreateHole(newCsys, 0, 40, "M8" ,itargetBodies)
CreateHole(newCsys, 90,40, "M8" ,itargetBodies)

End Select

Else
End If
End Sub

Function CreateDatum(xcoord As Double, ycoord As Double, datumCsys As CartesianCoordinateSystem) As NXOpen.Features.DatumCsys

Dim nullNXOpen_Features_Feature As NXOpen.Features.Feature = Nothing

Dim datumCsysBuilder1 As NXOpen.Features.DatumCsysBuilder
datumCsysBuilder1 = workPart.Features.CreateDatumCsysBuilder(nullNXOpen_Features_Feature)

Dim orPt As Point3d
orPt.X = xcoord
orPt.Y = ycoord
orPt.Z = 0

'New origin for CSYS
Dim origin As NXOpen.Point3d
origin = WCS2Wrk(orPt)

Dim orientation As NXOpen.NXMatrix
orientation = datumCsys.Orientation
'orientation = displayPart.WCS.CoordinateSystem.Orientation

Dim cartesianCoordinateSystem1 As NXOpen.CartesianCoordinateSystem
cartesianCoordinateSystem1 = workPart.CoordinateSystems.CreateCoordinateSystem(origin, orientation, False)

'Define origin

datumCsysBuilder1.Csys = cartesianCoordinateSystem1

datumCsysBuilder1.DisplayScaleFactor = 0.5

Dim nXObject1 As NXOpen.NXObject
nXObject1 = datumCsysBuilder1.Commit()
datumCsysBuilder1.Destroy()

Return CType(nXObject1, NXOpen.Features.DatumCsys)
End Function

Sub CreateHole(holeCsys As CartesianCoordinateSystem, _xc As Double, _yc As Double, h_type As String ,targetBodies As NXOpen.Body())

Dim datumCsys2 As NXOpen.Features.DatumCsys
datumCsys2 = CreateDatum(_xc,_yc, holeCsys)

'Need to select datum origin.

Dim point1 As NXOpen.Point = CType(datumCsys2.FindObject("POINT 1"), NXOpen.Point)

'Dim point1 As NXOpen.Point = CType(datumCsys2.Location, NXOpen.Point)

'Create Hole Part
Dim nullNXOpen_Features_HolePackage As NXOpen.Features.HolePackage = Nothing

Dim holePackageBuilder1 As NXOpen.Features.HolePackageBuilder
holePackageBuilder1 = workPart.Features.CreateHolePackageBuilder(nullNXOpen_Features_HolePackage)

'Point

Dim points1(0) As NXOpen.Point
points1(0) = point1
Dim curveDumbRule1 As NXOpen.CurveDumbRule
curveDumbRule1 = workPart.ScRuleFactory.CreateRuleCurveDumbFromPoints(points1)

Dim rules1(0) As NXOpen.SelectionIntentRule
rules1(0) = curveDumbRule1
Dim nullNXOpen_NXObject As NXOpen.NXObject = Nothing

Dim helpPoint1 As NXOpen.Point3d = New NXOpen.Point3d(0.0, 0.0, 0.0)

With holePackageBuilder1

.HolePosition.AllowSelfIntersection(True)
.HolePosition.AddToSection(rules1, nullNXOpen_NXObject, nullNXOpen_NXObject, nullNXOpen_NXObject, helpPoint1, NXOpen.Section.Mode.Create, False)
.BooleanOperation.Type = NXOpen.GeometricUtilities.BooleanOperation.BooleanType.Subtract
.BooleanOperation.SetTargetBodies(targetBodies)
.Tolerance = 0.001
.HoleDepthLimitOption = Features.HolePackageBuilder.HoleDepthLimitOptions.ThroughBody
End With

Select Case h_type
'Hole Type 6H6
Case "6H"
With holePackageBuilder1
.Type = Features.HolePackageBuilder.Types.GeneralHole
.GeneralHoleForm = Features.HolePackageBuilder.HoleForms.Simple
.GeneralSimpleHoleDiameter.RightHandSide = "6"

End With

Case "8H_Blind"
With holePackageBuilder1
.HoleDepthLimitOption = Features.HolePackageBuilder.HoleDepthLimitOptions.Value
.GeneralSimpleHoleDepth.Value = 20
.Type = Features.HolePackageBuilder.Types.GeneralHole
.GeneralHoleForm = Features.HolePackageBuilder.HoleForms.Simple
.GeneralSimpleHoleDiameter.RightHandSide = "8"

End With
'Hole Type D9
Case "D9"
With holePackageBuilder1
.Type = Features.HolePackageBuilder.Types.ScrewClearanceHole
.ScrewClearanceHoleForm = Features.HolePackageBuilder.HoleForms.Simple
.ScrewClearanceStartChamferEnabled = False
.ScrewClearanceEndChamferEnabled = False
.ScrewSize = "M8"
.ScrewStandard = "ISO"
.ScrewFitOption = "Normal (H13)"
.ScrewType = "General Screw Clearance"
.ScrewClearanceHoleDiameter.Value = 9

End With
'Hole Type M8
Case "M8"
With holePackageBuilder1

.Type = Features.HolePackageBuilder.Types.ThreadedHole
.ThreadSize = "M8"
.ThreadStandard = "DAG Metric"
.ThreadLengthOption = Features.HolePackageBuilder.ThreadLengthOptions.Full
.RadialEngageOption = "0.75"

End With
Case "M8_Blind"
With holePackageBuilder1
.HoleDepthLimitOption = Features.HolePackageBuilder.HoleDepthLimitOptions.Value

.Type = Features.HolePackageBuilder.Types.ThreadedHole
.ThreadedHoleDepth.Value = "16"
.ThreadSize = "M8"
.ThreadStandard = "DAG Metric"
.ThreadLengthOption = Features.HolePackageBuilder.ThreadLengthOptions.Full
.RadialEngageOption = "0.75"

End With

End Select

'Commit Hole
Dim nXObject2 As NXOpen.NXObject
Try

If holePackageBuilder1.Validate() Then nXObject2 = holePackageBuilder1.Commit()

Catch ex As Exception
MessageBox.Show(ex.Message)
Finally

holePackageBuilder1.Destroy()
End Try

End Sub

Function SelectSolid() As Body

Dim ui As UI = ui.GetUI
Dim message As String = "Select solid body"
Dim title As String = "Selection"

Dim scope As Selection.SelectionScope = Selection.SelectionScope.WorkPart
Dim keepHighlighted As Boolean = False
Dim includeFeatures As Boolean = True

Dim selectionAction As Selection.SelectionAction = _
Selection.SelectionAction.ClearAndEnableSpecific

Dim selectionMask_array(0) As Selection.MaskTriple
With selectionMask_array(0)
.Type = UFConstants.UF_solid_type
.Subtype = 0
.SolidBodySubtype = UFConstants.UF_UI_SEL_FEATURE_SOLID_BODY
End With

Dim selectedObject As NXObject = Nothing
Dim cursor As Point3d

ui.SelectionManager.SelectObject(message, title, scope, _
selectionAction, includeFeatures, _
keepHighlighted, selectionMask_array, _
selectedObject, cursor)

Dim solid As Body = CType(selectedObject, Body)

If solid Is Nothing Then
Return Nothing
End If

Return solid

End Function

Function Wrk2WCS(ByVal inPt As Point3d) As Point3d
Dim pt1(2), pt2(2) As Double

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

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

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

End Function

Function WCS2Wrk(ByVal inPt As Point3d) As Point3d
Dim pt1(2), pt2(2) As Double

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

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

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

End Function

Public Function GetUnloadOption(ByVal dummy As String) As Integer

'Unloads the image when the NX session terminates
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination

End Function

End Module

I have a problem with my code, that when I run it in context of the assembly after the holes are created and when I try to use measure distance and then choose the type of measure I get "Null Tag not allowed".
Only thing I can do is to click the WCS Dyn Icon as normally would do to reposition the WCS and then it works again.