Submitted by jchen on Tue, 12/09/2014 - 15:17
Forums:
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!
re: dimension coordinates
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
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!
re: private message
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
What is the reference point for .AnnotationOrigin? If the annotation (a dimension in my case) is considered a rectangle, which 'corner' is the origin?
re: annotation reference point
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
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))
re: alignment position
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
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?
re: alignment position
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
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
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?
re: vertical text
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.