Dear All
I have been struggling in a certain code using vb.net and I really need help. I searched the internet but to no avail.
Before putting the code on, let me explain to you my problem: My assembly reads a dwg that contains an unnamed UCS in a viewport of a certain layout. All I need is to read that UCS. I found that unnamed UCSs are not found in the UCS tables, so the only suggested way was to use the editor property CurrentUserCoordinateSystem. I am using this way but always failing.
The steps I am following are:
1- activate the layout
2- switch to model space
3- read the CurrentUserCoordinateSystem
But I am always getting the WCS and not the UCS in the viewport. An important note is that, if I activate the model space of the viewport then run my assembly, it would work and get the actual UCS. Please help me figuring out the problem, it is taking me days without success. Here is the code:
lytmgr.CurrentLayout = pstrres.StringResult ed.SwitchToModelSpace() ucs = ed.CurrentUserCoordinateSystem ed.WriteMessage(vbLf & "UCS is " & ucs.ToString) Dim dmat As Double() = ucs.ToArray() dmat(3) = 0 dmat(7) = 0 dmat(11) = 0 ucs = New Matrix3d(dmat) ucs = ucs.Transpose() ed.WriteMessage(vbLf & "Real ucs is " & ucs.ToString) ed.SwitchToPaperSpace()
Thanks in advance
We need a sample project to investigate this further...
You will find in the attached zipped file, a test drawing and a visual studio project that contains an assembly for autocad 2013. Run the code and you will see that it is not giving the required results. Waiting your answer
Hi,
Can you please try this code snippet to retrieve the UCS of the viewport using the COM API ?
' Needs Autodesk.AutoCAD.Interop and Autodesk.AutoCAD.Interop.Common references Imports Autodesk.AutoCAD.Interop Imports Autodesk.AutoCAD.Interop.Common <CommandMethod("GetUCS", CommandFlags.NoTileMode)> _ Public Sub GetUCS_PaperSpace() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor Dim db As Database = doc.Database Dim peo As New PromptEntityOptions("Select a viewport : ") peo.SetRejectMessage("Select a viewport.") peo.AddAllowedClass(GetType(Autodesk.AutoCAD.DatabaseServices.Viewport), True) Dim per As PromptEntityResult = ed.GetEntity(peo) If per.Status <> PromptStatus.OK Then Return End If Dim vpId As ObjectId = per.ObjectId Dim acadDoc As AcadDocument = Autodesk.AutoCAD.ApplicationServices.DocumentExtension.GetAcadDocument(doc) acadDoc.MSpace = True Using tr As Transaction = db.TransactionManager.StartTransaction() Dim vp As Autodesk.AutoCAD.DatabaseServices.Viewport = TryCast(tr.GetObject(vpId, OpenMode.ForRead), Autodesk.AutoCAD.DatabaseServices.Viewport) acadDoc.ActivePViewport = vp.AcadObject Dim ucsMat As Matrix3d = ed.CurrentUserCoordinateSystem Dim cs As CoordinateSystem3d = ucsMat.CoordinateSystem3d ed.WriteMessage([String].Format(vbLf & "Origin : {0}", cs.Origin)) ed.WriteMessage([String].Format(vbLf & "X Vec : {0}", cs.Xaxis)) ed.WriteMessage([String].Format(vbLf & "Y Vec : {0}", cs.Yaxis)) tr.Commit() End Using acadDoc.MSpace = False End Sub
Dear Balaji_Ram
I tried this snippet and it didnt work. It is giving me the world UCS.
Let me clarify something to you first, the snippet works when the UCS is named, and also my VB.Net code works when the UCS is named. What I want actually is to get the unnamed ucs of a viewport.
I know it is not saved in the database, but can I save it in code, or get it so I can work on it.
Thanks
Hi,
I'm not sure to understand, why not to check UCSXDIR and UCSYDIR ?
Gaston Nunez
Here are the two functions I am using, I have collected everything on the internet to be able to solve my problem, but still to no avail. Please help me, I have been suffering in this problem for about a month.
The getActiveUcs function checks to see if there is a named ucs, if not it creates a named ucs from the unnamed ucs.
The getUCS function applies the first function to the required viewport.
Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.DatabaseServices Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.EditorInput Imports Autodesk.AutoCAD Imports Autodesk.AutoCAD.Geometry Imports Autodesk.AutoCAD.Interop Imports Autodesk.AutoCAD.Interop.Common Public Class Test <CommandMethod("GetUCS", CommandFlags.NoTileMode)> _ Public Sub GetUCS_PaperSpace() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor Dim db As Database = doc.Database Dim peo As New PromptEntityOptions("Select a viewport : ") peo.SetRejectMessage("Select a viewport.") peo.AddAllowedClass(GetType(Autodesk.AutoCAD.DatabaseServices.Viewport), True) Dim per As PromptEntityResult = ed.GetEntity(peo) If per.Status <> PromptStatus.OK Then Return End If Dim vpId As ObjectId = per.ObjectId Dim acadDoc As AcadDocument = Autodesk.AutoCAD.ApplicationServices.DocumentExtension.GetAcadDocument(doc) acadDoc.MSpace = True Using tr As Transaction = db.TransactionManager.StartTransaction() Dim vp As Autodesk.AutoCAD.DatabaseServices.Viewport = TryCast(tr.GetObject(vpId, OpenMode.ForRead), Autodesk.AutoCAD.DatabaseServices.Viewport) acadDoc.ActivePViewport = vp.AcadObject Dim ucs As AcadUCS = getActiveUcs() ed.WriteMessage([String].Format(vbLf & "Origin : {0}", ucs.ToString)) Dim ucsMat As Matrix3d = ed.CurrentUserCoordinateSystem Dim cs As CoordinateSystem3d = ucsMat.CoordinateSystem3d ed.WriteMessage([String].Format(vbLf & "Origin : {0}", cs.Origin)) ed.WriteMessage([String].Format(vbLf & "X Vec : {0}", cs.Xaxis)) ed.WriteMessage([String].Format(vbLf & "Y Vec : {0}", cs.Yaxis)) tr.Commit() End Using acadDoc.MSpace = False End Sub Function getActiveUcs() As AcadUCS ' get the active UCS ' if the UCS is not saved, save it Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ThisDrawing As AcadDocument = Autodesk.AutoCAD.ApplicationServices.DocumentExtension.GetAcadDocument(doc) Dim ed As Editor = doc.Editor Dim Origin Dim xaxis Dim yaxis Dim Zero(0 To 2) As Double Zero(0) = 0 : Zero(1) = 0 : Zero(2) = 0 Dim currentUCSName As String currentUCSName = ThisDrawing.GetVariable("UCSNAME") If currentUCSName = "" Then ' Current UCS is not saved so get the data and save it ' A ucs is saved when a user makes and saves one or ' a user clicks on an isoview button If ThisDrawing.GetVariable("WORLDUCS") = 1 Then ' active UCS is identical to WCS xaxis = Zero : yaxis = Zero xaxis(0) = 1 : yaxis(1) = 1 getActiveUcs = ThisDrawing.UserCoordinateSystems.Add(Zero, xaxis, yaxis, "World") Else Origin = ThisDrawing.GetVariable("UCSORG") xaxis = ThisDrawing.GetVariable("UCSXDIR") yaxis = ThisDrawing.GetVariable("UCSYDIR") getActiveUcs = ThisDrawing.UserCoordinateSystems.Add(Zero, xaxis, yaxis, "Active") 'Changing the origin later stops the error message '-2145320930 UCS X axis and Y axis are not perpendicular getActiveUcs.Origin = Origin ThisDrawing.ActiveUCS = getActiveUcs End If Else getActiveUcs = ThisDrawing.UserCoordinateSystems.Item(currentUCSName) End If End Function End Class
This code doesnt work for the first time it is applied, but if you do the function again it works!!!!!!
I am not able to figure out the problem, any help is much appreciated.
I am trying out with your code and will get back to you soon.
Hi,
The problem is not with the code and seems specific to that paperspace viewport of the drawing that you shared. After I switched to the modelspace and saved the drawing in AutoCAD, it worked ok. The UCS in that viewport might have been set incorrectly but it is hard to identify why and how.
Your code as well as the code that I posted earlier work correctly for any other viewport created with an unnamed UCS. Both the code works ok with the attached drawings. These drawings were saved after the viewport UCS was set right using the above step.
Hi,
To me this problem seems specific to this drawing and the code has worked for even a new layout created in the same drawing. I could not find a way to resolve this issue for the layout that you are testing with.
A workaround to get the UCS origin, x direction and y direction for the viewport could be get the values directly by retrieving the values for DXF codes 110, 111 and 112. I still do not like approaching it this way
Here is a sample code that will display the DXF codes after you select the paperspace viewport. You can use the values from the above DXF codes to get the UCS values.
<DllImport("acdb19.dll", CallingConvention:=CallingConvention.Cdecl, EntryPoint:="?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")> _ Public Shared Function acdbGetAdsName_R19_64(name As Long(), objId As ObjectId) As Integer End Function <DllImport("accore.dll", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl, EntryPoint:="acdbEntGet")> _ Public Shared Function acdbEntGet(ename As Long()) As System.IntPtr End Function <DllImport("accore.dll", CharSet:=CharSet.Ansi, CallingConvention:=CallingConvention.Cdecl, EntryPoint:="acdbEntGetX")> _ Public Shared Function acdbEntGetX(ename As Long(), rb As IntPtr) As System.IntPtr End Function <CommandMethod("GetEntityDxf")> _ Public Shared Sub GetEntityDxf() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim ed As Editor = doc.Editor Dim per As PromptEntityResult = ed.GetEntity(vbLf & "Select an Entity: ") If per.Status <> PromptStatus.OK Then Return End If Dim ename As Long() = New Long() {0, 0} ' extract the id into an ename Dim result As Integer = acdbGetAdsName_R19_64(ename, per.ObjectId) ' now I have the ename lets entget it into a result buffer Dim rb As New ResultBuffer() Interop.AttachUnmanagedObject(rb, acdbEntGet(ename), True) ' print out what we have Dim iter As ResultBufferEnumerator = rb.GetEnumerator() While iter.MoveNext() Dim TmpVal As TypedValue = iter.Current Dim strValue As String = (If(TmpVal.Value IsNot Nothing, TmpVal.Value.ToString(), "*Nothing*")) ed.WriteMessage(vbLf & " - Code: " & TmpVal.TypeCode.ToString() & " = " & strValue) End While End Sub