Getting X and Y coordinates from dimensions

I'm currently trying to pull all the dimensions from a drawing into an Excel file, and I am also trying to get their X and Y coordinates (ex A1, C3 etc etc.)

Is it possible to do this with Journaling?

Would this be part of "Annotations.Dimension"?

Thank you so much!

You can get the dimension's coordinate information through the dimension object's .AnnotationOrigin property. This will report the numerical values of the X and Y position of the dimension.

However, given your example, A1 or C3, I assume you are looking for the sheet zone that contains the dimension. I could not find a direct way to get this information from the API (you can get this information for drafting views through the drawingSheet.GetSheetZoneReference or drawingSheet.GetZoneReference methods). I wrote some code that will query the drawing sheet's borders and zones and calculate the position of the dimension. The return value is in the format: {sheet number}{vertical zone letter}{horizontal zone number}; this is similar to the output from the drawingSheet object's .GetSheetZoneReference method.

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF
 
Module Module3
 
    Dim theSession As Session = Session.GetSession()
    Dim theUfSession As UFSession = UFSession.GetUFSession
 
    Sub Main()
 
        If IsNothing(theSession.Parts.Work) Then
            'active part required
            Return
        End If
 
        Dim workPart As Part = theSession.Parts.Work
        Dim lw As ListingWindow = theSession.ListingWindow
        lw.Open()
 
        For Each tempDim As Annotations.Dimension In workPart.Dimensions
            Dim mainText() As String
            Dim dualText() As String
            tempDim.GetDimensionText(mainText, dualText)
            lw.WriteLine(mainText(0))
            lw.WriteLine(ReportDimensionSheetZone(AskDrawingSheet(tempDim), tempDim))
            lw.WriteLine("")
        Next
 
        lw.Close()
 
    End Sub
 
    ' This function will work for:
    '     an object which "Resides on drawing" or is "View Dependent In" a DraftingView
    '     a DraftingView
    '     a DrawingSheet.View
    ' Returns Nothing for all other (ie. model mode) objects
    Function AskDrawingSheet(ByVal theObject As TaggedObject) As Drawings.DrawingSheet
 
        Dim theView As View = TryCast(theObject, View)
        If Not theView Is Nothing Then
            Dim sheetTag As Tag = Nothing
            Try
                theUfSession.Draw.AskDrawingOfView(theView.Tag, sheetTag)
                Return Utilities.NXObjectManager.Get(sheetTag) ' the drawing it is on
            Catch ex As NXException
                Return Nothing  ' it is a model view
            End Try
        End If
 
        Dim viewName As String = Nothing
        Dim status As Integer = Nothing
        Try
            theUfSession.View.AskViewDependentStatus(theObject.Tag, status, viewName)
        Catch ex As NXException
            Return Nothing
        End Try
        If status = 0 Then Return Nothing ' it is a model mode object
 
        Dim viewTag As Tag = Nothing
        theUfSession.View.AskTagOfViewName(viewName, viewTag)
        Dim viewType As Integer = Nothing
        Dim viewSubtype As Integer = Nothing
        theUfSession.View.AskType(viewTag, viewType, viewSubtype)
        If viewType = 0 Then Return Nothing ' it is view dependent in a modeling view
 
        Dim drawingTag As Tag = Nothing
        theUfSession.Draw.AskDrawingOfView(viewTag, drawingTag)
        Return Utilities.NXObjectManager.Get(drawingTag)  ' the drawing it is on!
 
    End Function
 
    Function ReportDimensionSheetZone(ByVal theSheet As Drawings.DrawingSheet, ByVal theDimension As Annotations.Dimension) As String
 
        'sheet number / vertical zone / horizontal zone
 
        Dim borderBuilder As Drawings.BordersAndZonesBuilder
 
        If IsNothing(theSheet.BordersAndZones) Then
            Return Nothing
        End If
 
        borderBuilder = theSession.Parts.Work.Drafting.BordersAndZonesObjects.CreateBordersAndZonesBuilder(theSheet.BordersAndZones)
 
        Dim numHorizontalZones As Integer = (theSheet.Length - borderBuilder.LeftMargin - borderBuilder.RightMargin) / borderBuilder.HorizontalSize
        Dim numVerticalZones As Integer = (theSheet.Height - borderBuilder.BottomMargin - borderBuilder.TopMargin) / borderBuilder.VerticalSize
 
        'calculate zone wrt bottom left of drawing (ZoneOrigin.BottomLeft)
        Dim Hcell As Double = (theDimension.AnnotationOrigin.X - borderBuilder.LeftMargin) / borderBuilder.HorizontalSize
        Dim Vcell As Double = (theDimension.AnnotationOrigin.Y - borderBuilder.BottomMargin) / borderBuilder.VerticalSize
 
        Hcell = Math.Ceiling(Hcell)
        Vcell = Math.Ceiling(Vcell)
 
        Dim theZoneOrigin As Drawings.BordersAndZonesBuilder.ZoneOrigin = borderBuilder.Origin
        borderBuilder.Destroy()
 
        Dim verticalLetterNum As Integer
        Dim verticalLetter As Char
 
        Dim horizontalNum As Integer
 
        If theZoneOrigin = Drawings.BordersAndZonesBuilder.ZoneOrigin.BottomLeft Or theZoneOrigin = Drawings.BordersAndZonesBuilder.ZoneOrigin.TopLeft Then
            horizontalNum = Hcell
        Else
            'origin on right side
            horizontalNum = numHorizontalZones - Hcell + 1
        End If
 
        If theZoneOrigin = Drawings.BordersAndZonesBuilder.ZoneOrigin.BottomLeft Or theZoneOrigin = Drawings.BordersAndZonesBuilder.ZoneOrigin.BottomRight Then
            verticalLetterNum = Asc("A") + Vcell - 1
            verticalLetter = Chr(verticalLetterNum)
 
        Else
            'origin on the top
            verticalLetterNum = Asc("A") + numVerticalZones - Vcell
            verticalLetter = Chr(verticalLetterNum)
 
        End If
 
        Dim theSheetNum As String = SheetNumber(theSheet)
 
        Return theSheetNum & verticalLetter & horizontalNum.ToString
 
    End Function
 
    Function SheetNumber(ByVal theSheet As Drawings.DrawingSheet) As String
 
        Dim sheetNum As Integer
        Dim theSheetBuilder As Drawings.DrawingSheetBuilder = theSession.Parts.Work.DrawingSheets.DrawingSheetBuilder(theSheet)
        sheetNum = theSheetBuilder.Number
 
        theSheetBuilder.Destroy()
 
        Return sheetNum.ToString
 
    End Function
 
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
 
        'Unloads the image when the NX session terminates
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination
 
        '----Other unload options-------
        'Unloads the image immediately after execution within NX
        'GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
 
        'Unloads the image explicitly, via an unload dialog
        'GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Explicitly
        '-------------------------------
 
    End Function
 
End Module

Hi. Thanks for your help with this. Is there a private message function? I have some follow up questions and need help that I'd prefer not to ask on the public forum.

Thanks!

Unfortunately we don't have a private message function; honestly, the forum itself was tacked on as almost an afterthought. However, you can email me directly at info@nxjournaling.com

What is the reference point for .AnnotationOrigin? If the annotation (a dimension in my case) is considered a rectangle, which 'corner' is the origin?

When you edit an annotation through the GUI, you can specify the "alignment position". There are three options for the horizontal alignment (left, center, and right) and three options for the vertical alignment (top, middle, and bottom), yielding a total of nine options for the alignment position.

When programming, you can access the annotation object's .AnnotationOrigin property; this property will report the location of the alignment position for the annotation object. The result may not be on a corner. You can calculate a "box" around the annotation by changing the alignment position to a corner (e.g. bottom left), making note of the origin, changing the alignment position to the opposite corner (e.g. top right) and making note of the new origin location.

Thanks! Are you sure that the AlignmentPosition property changes the (X,Y) coordinate of the .AnnotationOrigin for the dimension? If I want to write a function to calculate the "area" of any dimension label, could I do something like this?

For a dim called myDimension:

Dim letteringPreferences1 As Annotations.LetteringPreferences
letteringPreferences1 = myDimension.GetLetteringPreferences()

letteringPreferences1.AlignmentPosition = Annotations.AlignmentPosition.TopLeft
letteringPreferences1.AlignmentPosition = Annotations.AlignmentPosition.TopLeft
Dim x1 As Integer = myDimension.AnnotationOrigin.X
Dim y1 As Integer = myDimension.AnnotationOrigin.Y
letteringPreferences1.AlignmentPosition = Annotations.AlignmentPosition.BottomRight
Dim x2 As Integer = myDimension.AnnotationOrigin.X
Dim y2 As Integer = myDimension.AnnotationOrigin.Y

To define the "area" could I do:

Dim area as New System.Drawing.Rectangle(x1,y1,(x2-x1),(y2-y1))

Yes, changing the alignment position will change the coordinates returned from the .AnnotationOrigin property.

In theory, your code strategy will work but you will have to iron out the specifics (I don't think what you posted will work as-is).

I strongly suspect that the System.Drawing.Rectangle is NOT going to do what you want it to in this case, although not knowing what you are up to, I could be wrong on this point.

I'm finding that changing the alignment position does not change the coordinates returned from the .AnnotationOrigin property.

If you believe it does, would you mind posting some code that could retrieve the coordinates of the corners that define the "rectangle" that is the dimension?

I can't post any code at the moment, but the code that you posted above won't work because you have not committed the changes back to the dimension object. After you change the alignment option, you will have to call myDimension.SetLetteringPreferences() before attempting to retrieve the .AnnotationOrigin.

Some rough pseudocode would be:

get lettering preferences of the annotation
change alignment position to corner
set lettering preferences of the annotation
retrieve the annotation origin
 
repeat with opposite corner

What version of NX are you using?

I'm currently on NX8.5. Here is the code I have been working on. Essentially I want to check candidate locations for the balloon before placing it down, to avoid/minimize collisions with other features on the page. I'm trying to do so by representing the balloon and dimensions as rectangle, and checking for collisions with the .IntersectsWith method.

I realize this might be a lot to read through, but if you could shed any light on what might be going wrong, it would be very helpful! Right now the code runs but the balloons are not being placed in the right places.

 
Option Strict Off
Imports System
Imports NXOpen
Imports NXOpenUI
Imports NXOpen.UF
Imports Microsoft.VisualBasic
Imports System.Text.RegularExpressions
Imports System.Collections.Generic
Imports NXOpen.Annotations
Imports System.IO
Imports System.Collections
Imports System.Object
Imports System.Runtime.InteropServices
Imports System.Data.OleDb
Imports Microsoft.Office.Interop.Excel
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Windows.Forms.MessageBox
 
Module Module1
 
    Dim theSession As Session = Session.GetSession()
    Dim theUISession As UI = UI.GetUI
    Dim theUfSession As UFSession = UFSession.GetUFSession
    Dim workPart As Part = theSession.Parts.Work
    Dim displayPart As Part = theSession.Parts.Display
 
    Sub Main(ExportDimstoExcel)
 
        Dim counter As Integer = 1
 
        For Each myDimension As Annotations.Dimension In workPart.Dimensions
 
            Dim markId2 As Session.UndoMarkId
            markId2 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "Start")
 
            'DEFINES THE AREA OF RECTANGLE THAT IS A PLACEHOLDER FOR THE BALLOON
            Dim letteringPreferences1 As Annotations.LetteringPreferences
            letteringPreferences1 = myDimension.GetLetteringPreferences()
 
            'Set the origin of the dimension to the top left corner and get coordinates
            letteringPreferences1.AlignmentPosition = Annotations.AlignmentPosition.TopLeft
            myDimension.SetLetteringPreferences(letteringPreferences1)
            Dim x1 As Double = myDimension.AnnotationOrigin.X
            Dim y1 As Double = myDimension.AnnotationOrigin.Y
            'Move the origin of the dimension to the bottom right corner and get coordinates
            letteringPreferences1.AlignmentPosition = Annotations.AlignmentPosition.BottomRight
            myDimension.SetLetteringPreferences(letteringPreferences1)
            Dim x2 As Double = myDimension.AnnotationOrigin.X
            Dim y2 As Double = myDimension.AnnotationOrigin.Y
 
            'Define the area of the dimension with the origin at the bottom left of the rectangle
            Dim area As New System.Drawing.Rectangle(x1, y1, Math.abs(x2 - x1), Math.abs(y2 - y1))
            'Define the area of the balloon - assume that the balloon is a 6x6 square
            Dim balloonwidth As Integer = 0.38
            Dim balloonarea As New System.Drawing.Rectangle(x:=CInt(x1), y:=CInt(y1), Width:=balloonwidth, Height:=balloonwidth)
 
            Dim nullAnnotations_IdSymbol As Annotations.IdSymbol = Nothing
 
            Dim idSymbolBuilder1 As Annotations.IdSymbolBuilder
            idSymbolBuilder1 = workPart.Annotations.IdSymbols.CreateIdSymbolBuilder(nullAnnotations_IdSymbol)
 
            idSymbolBuilder1.Origin.Plane.PlaneMethod = Annotations.PlaneBuilder.PlaneMethodType.XyPlane
            idSymbolBuilder1.Type = Annotations.IdSymbolBuilder.SymbolTypes.Hexagon
            idSymbolBuilder1.UpperText = counter.ToString
            idSymbolBuilder1.Origin.Anchor = Annotations.OriginBuilder.AlignmentPosition.TopLeft
            'use the symbol size set in the part
            idSymbolBuilder1.Size = 0.38
            '                       ^0.38 is the default balloon size defined by NX
 
            'Makes the border of the hexagon thick
            idSymbolBuilder1.Style.SymbolStyle.IdSymbolWidth = Annotations.LineWidth.Three
 
            'Create a buffer that can be changed later on
            Dim buffer As Integer = 0.1
 
            'For dimensions that have a flag coming out from the right
            'If ..... Then to check for the type of flag
            '(1) Move balloonarea to location 1 and try it; location 1 is to the left of the dimension; note I use a buffer of 1
            balloonarea.Offset(-(0.4 + buffer), 0)
            'Do we need to check to make sure that we aren't colliding with the current myDimension?
            If detectcollision(balloonarea) = True Then
                '(2) Try location 2, which is to the top of the dimension
                balloonarea.X = x1
                balloonarea.Y = y1
                balloonarea.Offset((Math.abs(x2 - x1)) / 2, (Math.abs(y2 - y1)) + buffer)
                If detectcollision(balloonarea) = True Then
                    '(3) Try location 3, which is to the bottom of the dimension
                    balloonarea.X = x1
                    balloonarea.Y = y1
                    balloonarea.Offset((Math.abs(x2 - x1)) / 2, -(balloonwidth + buffer))
                    If detectcollision(balloonarea) = True Then
                        Dim origin As Point3d = New Point3d(balloonarea.X, balloonarea.Y, 0.0)
                        idSymbolBuilder1.Origin.Origin.SetValue(Nothing, Nothing, origin)
                    Else
                        Dim origin As Point3d = New Point3d(balloonarea.X, balloonarea.Y, 0.0)
                        idSymbolBuilder1.Origin.Origin.SetValue(Nothing, Nothing, origin)
                    End If
                Else
                    Dim origin As Point3d = New Point3d(balloonarea.X, balloonarea.Y, 0.0)
                    idSymbolBuilder1.Origin.Origin.SetValue(Nothing, Nothing, origin)
                End If
            Else
                Dim origin As Point3d = New Point3d(balloonarea.X, balloonarea.Y, 0.0)
                idSymbolBuilder1.Origin.Origin.SetValue(Nothing, Nothing, origin)
            End If
 
 
 
            Dim QC_IDSymbol As IDSymbol
            QC_IDSymbol = idSymbolBuilder1.Commit()
            'change IDSymbol layer to match that of the dimension or note it is attached to
            QC_IDSymbol.Layer = myDimension.Layer
 
 
            theSession.SetUndoMarkName(markId2, "Label Dimensions")
            theSession.SetUndoMarkVisibility(markId2, Nothing, Session.MarkVisibility.Visible)
            idSymbolBuilder1.Destroy()
            counter += 1
        Next
 
 
    End Sub
 
    'Helper function that for each dimension on the sheet check if it collides with the current balloon
    Function detectcollision(ByVal balloonarea As System.Drawing.Rectangle)
 
        'Check for collisions with other dimensions and balloons. First define with
        For Each collidingdim As Annotations.Dimension In workPart.Dimensions
 
            'Define area of the colliding dim as a rectangle as well
            Dim letteringPreferences2 As Annotations.LetteringPreferences
            letteringPreferences2 = collidingdim.GetLetteringPreferences()
 
            'Set the origin of the dimension to the top left corner and get coordinates
            letteringPreferences2.AlignmentPosition = Annotations.AlignmentPosition.TopLeft
            collidingdim.SetLetteringPreferences(letteringPreferences2)
            Dim x3 As Double = collidingdim.AnnotationOrigin.X
            Dim y3 As Double = collidingdim.AnnotationOrigin.Y
            'Move the origin of the dimension to the bottom right corner and get coordinates
            letteringPreferences2.AlignmentPosition = Annotations.AlignmentPosition.BottomRight
            collidingdim.SetLetteringPreferences(letteringPreferences2)
            Dim x4 As Double = collidingdim.AnnotationOrigin.X
            Dim y4 As Double = collidingdim.AnnotationOrigin.Y
 
            'Define the area of the dimension with the origin at the bottom left of the rectangle
            Dim collidingdimarea As New System.Drawing.Rectangle(x3, y3, Math.abs(x4 - x3), Math.abs(y4 - y3))
 
            If balloonarea.IntersectsWith(collidingdimarea) Then
                Exit For
                Return True
 
            End If
 
        Next
 
    End Function
 
End Module
 

This method is working perfectly for my dimensions, but there is one issue. For dimensions in which the text is oriented vertically, the origin (x,y) of all four corners is the same point for some reason. Do you know why this might be the case?

I doubt that is the intended behavior of vertical text. I'd suggest contacting GTAC and filing an Incident Report (IR). If they agree that it is a bug in the program, they will fix it in a future NX patch or version. In the meantime, they might be able to offer a work-around for your situation.