Author Topic: zoom to extents of Entity in paperspace or model using only objectid  (Read 5142 times)

0 Members and 1 Guest are viewing this topic.

nekitip

  • Guest
Hello to everyone and first to excuse myself - I have been absent from programming world for over a year or more, so i might have missed something you have already talked about. :)
Here is my question:
I am trying to zoom to entity extents by knowing objectid. Most, if not all examples found online have at some point
Code: [Select]
Editor.GetCurrentView()But it doesnt help me, because - entity can be in paperspace and also, if in paperspace, there can be viewport active (last time when user has been there, it was left active).
So far, I'm going in this direction:
1) find blocktablerecord of entity's owner
2) check if any layout have the same BTR
3) switch to that layout
4) set viewport to layout's default
5) zoomto extents

numbers 1,2,3 are something that i wasnt able to google about, seems not so people had this problem, so here is my code for that.
number 4) is where I loose it, and posibly it is all wrong approach after all?

1,2,3 code:
Code - vb.net: [Select]
  1. Private Sub setcurrentLayoutOfEntity(ByRef oid As ObjectId)
  2.             Dim doc As Document = Application.DocumentManager.MdiActiveDocument
  3.             Dim db As Database = doc.Database
  4.  
  5.             Using trans As Transaction = db.TransactionManager.StartTransaction()
  6.                 Dim bt As BlockTable = trans.GetObject(db.BlockTableId, OpenMode.ForRead)
  7.                 Dim ent As Entity = trans.GetObject(oid, OpenMode.ForRead)
  8.                 Dim btr As BlockTableRecord = trans.GetObject(ent.BlockId, OpenMode.ForRead)
  9.                 Dim layoutdic As DBDictionary = trans.GetObject(db.LayoutDictionaryId, OpenMode.ForRead)
  10.  
  11.                 For Each laye As DBDictionaryEntry In layoutdic
  12.                     Dim lay As Layout = trans.GetObject(laye.Value, OpenMode.ForRead)
  13.                     If lay.BlockTableRecordId = ent.BlockId Then
  14.                         If lay.TabSelected = False Then
  15.                             Using lock As DocumentLock = doc.LockDocument()
  16.                                 LayoutManager.Current.CurrentLayout = lay.LayoutName
  17.                             End Using
  18.                         End If
  19.                         Exit For
  20.                     End If
  21.                 Next
  22.                 trans.Commit()
  23.             End Using
  24.         End Sub
for 5) I have some code from possibly from this forum (maybe Gile?), although it is a bit overkill in this scenario:
Code - vb.net: [Select]
  1. Private Sub ZoomObjects(idCol As List(Of ObjectId))
  2.             Dim doc As Document = Application.DocumentManager.MdiActiveDocument
  3.             Dim db As Database = doc.Database
  4.             Dim ed As Editor = doc.Editor
  5.             Using trans As Transaction = db.TransactionManager.StartTransaction()
  6.                 Using view As ViewTableRecord = ed.GetCurrentView()
  7.                     Dim WCS2DCS As Matrix3d = Matrix3d.PlaneToWorld(view.ViewDirection)
  8.                     WCS2DCS = Matrix3d.Displacement(view.Target - Point3d.Origin) * WCS2DCS
  9.                     WCS2DCS = Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) * WCS2DCS
  10.                     WCS2DCS = WCS2DCS.Inverse()
  11.                     Dim ent As Entity = DirectCast(trans.GetObject(idCol(0), OpenMode.ForRead), Entity)
  12.                     Dim ext As Extents3d = ent.GeometricExtents
  13.                     For Each oid As ObjectId In idCol
  14.                         ent = DirectCast(trans.GetObject(oid, OpenMode.ForRead), Entity)
  15.                         Dim tmp As Extents3d = ent.GeometricExtents
  16.                         ext.AddExtents(tmp)
  17.                     Next
  18.                     ext.TransformBy(WCS2DCS)
  19.                     view.Width = ext.MaxPoint.X - ext.MinPoint.X
  20.                     view.Height = ext.MaxPoint.Y - ext.MinPoint.Y
  21.                     view.CenterPoint = New Point2d((ext.MaxPoint.X + ext.MinPoint.X) / 2.0, (ext.MaxPoint.Y + ext.MinPoint.Y) / 2.0)
  22.  
  23.                     ed.SetCurrentView(view)
  24.                     trans.Commit()
  25.                 End Using
  26.             End Using
  27.         End Sub


thank you!

nekitip

  • Guest
Re: zoom to extents of Entity in paperspace or model using only objectid
« Reply #1 on: July 01, 2014, 05:56:15 AM »
also, in steps 1,2,3 there can be some other way to switch to different layout, since Entity:
Code - vb.net: [Select]
  1. Dim ent As Entity = trans.GetObject(oid, OpenMode.ForRead)
has also information about paper or model space like:
Code: [Select]
ent.BlockName = "*Paper_Space176"but i have lost half of the day trying to figure out how it could be used instead comparing BTRs objectids and gave up on that

Keith Brown

  • Swamp Rat
  • Posts: 597
Re: zoom to extents of Entity in paperspace or model using only objectid
« Reply #2 on: July 01, 2014, 08:18:33 AM »
I am still learning the API so this might not be much help to you but you are passing the entity ObjectID into your method and then getting the database from the current document.  This makes the assumption that the current document is the document that the entity came from.  (This could of course be a valid assumption)   You can however also get the database that the entity came from by using


Code: [Select]
oid.Database


Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

nekitip

  • Guest
Re: zoom to extents of Entity in paperspace or model using only objectid
« Reply #3 on: July 01, 2014, 11:38:35 AM »
You think something like:
Code - vb.net: [Select]
  1. Dim db As Database = oid.Database
Yes, it can be done that way. But in that way, not sure how to get document object you will need for document lock...
However the problem of this post is really how to make viewport change in paperspace (maybe in modelspace is the same problem, but i have not explore in that direction) to the default? view, to the only one that exists when you for create layout. In that way, we could have universal and working zoomto. (But i still believe that all this already exists, but i cannot find it)

Keith Brown

  • Swamp Rat
  • Posts: 597
Re: zoom to extents of Entity in paperspace or model using only objectid
« Reply #4 on: July 01, 2014, 12:28:33 PM »
You can get the document from the database with the following snippet.

Code - C#: [Select]
  1. Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.GetDocument(oid.Database);
  2.  
« Last Edit: July 01, 2014, 12:36:08 PM by Keith Brown »
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

nekitip

  • Guest
Re: zoom to extents of Entity in paperspace or model using only objectid
« Reply #5 on: July 08, 2014, 05:30:01 AM »
It may be that this is possibly solved, and this may be the solution
So, the only unsolved problem of zooming to known object id was this:
4) set viewport to layout's default
It has been bugging me for days and it seems that solution is this one liner:
Code - vb.net: [Select]
  1. If lay.LayoutName <> "Model" Then ed.SwitchToPaperSpace()
What it does - once you have your layout on (by iterating layouts and comparing its btr-s), your problem is multiple viewports that exists and possibly, one of them is left active, meaning - you cannot zoom because you are not zooming paperspace but inside that viewport.
I have trying different approaches to find all viewports that exist, comparing that to...
With this one liner, problem is solved. Now, i have not tested code in modelspace (don't know what happens it you zoom and have tiled space), but this is a good start if someone is having the same problem. Also, if someone has better solution or advice, please contribute.

And, to user who asked me if
Code - vb.net: [Select]
  1. Dim doc As Document = Application.DocumentManager.MdiActiveDocument
is needed... there are other ways to get doc, admitingly i didn't know them all, and thank you for that, but in this scenario - what is the point of zooming if your doc is not active.

so, steps are:
1) - know your handle or objectid of object you need zoom to.
2) - open file, switch layout, switch viewport
3) - zoom to extents with any of googleable ways

this is what it is all about
Code - vb.net: [Select]
  1. Private Sub openLayoutAndViewport(ByRef oid As ObjectId)
  2.             Dim doc As Document = Application.DocumentManager.MdiActiveDocument
  3.             Dim ed As Editor = doc.Editor
  4.             Dim db As Database = doc.Database
  5.  
  6.             Using trans As Transaction = db.TransactionManager.StartTransaction()
  7.                 Dim ent As Entity = trans.GetObject(oid, OpenMode.ForRead)
  8.                 Dim btr As BlockTableRecord = trans.GetObject(ent.BlockId, OpenMode.ForRead)
  9.                 Dim layoutdic As DBDictionary = trans.GetObject(db.LayoutDictionaryId, OpenMode.ForRead)
  10.  
  11.                 For Each laye As DBDictionaryEntry In layoutdic
  12.                     Dim lay As Layout = trans.GetObject(laye.Value, OpenMode.ForRead)
  13.                     If lay.BlockTableRecordId = ent.BlockId Then
  14.                         If lay.TabSelected = False Then
  15.                             Using lock As DocumentLock = doc.LockDocument()
  16.                                 LayoutManager.Current.CurrentLayout = lay.LayoutName
  17.                             End Using
  18.                         End If
  19.                         If lay.LayoutName <> "Model" Then ed.SwitchToPaperSpace()
  20.                         Exit For
  21.                     End If
  22.                 Next
  23.                 trans.Commit()
  24.             End Using
  25.         End Sub

one of ways to zoom to extents
credit for this one is possibly Gile although not sure
Code - vb.net: [Select]
  1. Private Sub ZoomObjects(idCol As List(Of ObjectId))
  2.             Dim doc As Document = Application.DocumentManager.MdiActiveDocument
  3.             Dim db As Database = doc.Database
  4.             Dim ed As Editor = doc.Editor
  5.             Using trans As Transaction = db.TransactionManager.StartTransaction()
  6.                 Using view As ViewTableRecord = ed.GetCurrentView()
  7.                     Dim WCS2DCS As Matrix3d = Matrix3d.PlaneToWorld(view.ViewDirection)
  8.                     WCS2DCS = Matrix3d.Displacement(view.Target - Point3d.Origin) * WCS2DCS
  9.                     WCS2DCS = Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) * WCS2DCS
  10.                     WCS2DCS = WCS2DCS.Inverse()
  11.                     Dim ent As Entity = DirectCast(trans.GetObject(idCol(0), OpenMode.ForRead), Entity)
  12.                     Dim ext As Extents3d = ent.GeometricExtents
  13.                     For Each oid As ObjectId In idCol
  14.                         ent = DirectCast(trans.GetObject(oid, OpenMode.ForRead), Entity)
  15.                         Dim tmp As Extents3d = ent.GeometricExtents
  16.                         ext.AddExtents(tmp)
  17.                     Next
  18.                     ext.TransformBy(WCS2DCS)
  19.                     view.Width = ext.MaxPoint.X - ext.MinPoint.X
  20.                     view.Height = ext.MaxPoint.Y - ext.MinPoint.Y
  21.                     view.CenterPoint = New Point2d((ext.MaxPoint.X + ext.MinPoint.X) / 2.0, (ext.MaxPoint.Y + ext.MinPoint.Y) / 2.0)
  22.  
  23.                     ed.SetCurrentView(view)
  24.                     trans.Commit()
  25.                 End Using
  26.             End Using
  27.         End Sub

now, this code below is not needed for this problem, but i use it as a part of this in a sense that i will open file and zoom to object
-do have in mind all the implications of using handle to access object instead of using objectid!
Code - vb.net: [Select]
  1. Public Sub zoomtotextandload(ByVal text As String, hndl As Int64)
  2.             'what if *.dwg is corrupt -try catch
  3.             'Try
  4.  
  5.             If System.IO.File.Exists(text) Then
  6.                 If Application.DocumentManager.CurrentDocument IsNot Nothing Then
  7.                     Dim edbefore As Editor = Application.DocumentManager.MdiActiveDocument.Editor
  8.                     If edbefore.Document.CommandInProgress.Length > 0 Then
  9.                         edbefore.WriteMessage("Another command active")
  10.                         Exit Sub
  11.                     End If
  12.                     If edbefore.IsDragging Then
  13.                         edbefore.WriteMessage("Another command active")
  14.                         Exit Sub
  15.                     End If
  16.                 End If
  17.  
  18.                 Dim doc As Document = Nothing
  19.                 For Each d As Document In Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager
  20.                     If d.Name = text Then
  21.                         doc = d
  22.                         Exit For
  23.                     End If
  24.                 Next
  25.                 If doc = Nothing Then doc = DocumentCollectionExtension.Open(Application.DocumentManager, text, False)
  26.                 Application.DocumentManager.MdiActiveDocument = doc
  27.  
  28.                 'now we have open dwg and will try to find object
  29.                 Dim ed As Editor = doc.Editor
  30.  
  31.                 Dim db As Database = doc.Database
  32.                 Dim hn As Handle = New Handle(hndl)
  33.                 Dim oid2 As ObjectId
  34.                 If db.TryGetObjectId(hn, oid2) Then
  35.                     If oid2.IsResident = True And Not oid2.IsErased Then
  36.                         Dim tmp1 As New List(Of ObjectId)
  37.                         tmp1.Add(oid2)
  38.                         openLayoutAndViewport(oid2)
  39.                         ZoomObjects(tmp1)
  40.                     End If
  41.                 End If
  42.             End If
  43.             'Catch ex As Exception
  44.  
  45.             'End Try
  46.         End Sub

Jeff H

  • Needs a day job
  • Posts: 6061
Re: zoom to extents of Entity in paperspace or model using only objectid
« Reply #6 on: July 08, 2014, 05:38:23 AM »
Have you tried something similar to?

Code - C#: [Select]
  1.   public void ZoomToObjects(Entity ent, double zoomFactor)
  2.         {
  3.             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.  
  5.             //int CvId = Convert.ToInt32((Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("CVPORT")));
  6.             int CvId = Settings.Variables.CVPORT;
  7.             using (Autodesk.AutoCAD.GraphicsSystem.Manager gm = doc.GraphicsManager)
  8.             using (Autodesk.AutoCAD.GraphicsSystem.View vw = gm.GetGsView(CvId, true))
  9.             {
  10.                 Extents3d ext = ent.GeometricExtents;
  11.                 vw.ZoomExtents(ext.MinPoint, ext.MaxPoint);
  12.                 vw.Zoom(zoomFactor);
  13.                 gm.SetViewportFromView(CvId, vw, true, true, false);
  14.  
  15.             }
  16.         }
  17.  
  18.  

nekitip

  • Guest
Re: zoom to extents of Entity in paperspace or model using only objectid
« Reply #7 on: July 08, 2014, 07:25:41 AM »
I must be missing something because of error:
'GetGsView' is not a member of 'Autodesk.AutoCAD.GraphicsSystem.Manager'

Some reference? I'm on acad2015
I've googled and found something like this
http://through-the-interface.typepad.com/through_the_interface/2013/03/2d-vs-3d-graphics-system-inside-autocad-request-for-information.html
But this doesnt work also because I cant figure out where is "GetGsView" located.

However, just by looking at the code, I have also failed to understand how the code will see where the entity is actually located? (in what layout)

WILL HATCH

  • Bull Frog
  • Posts: 448
Re: zoom to extents of Entity in paperspace or model using only objectid
« Reply #8 on: July 08, 2014, 03:21:58 PM »
Quote from: Myself: the broken record
Get the ARX documentation www.autodesk.com/objectarx-download

GetGsView has been changed to ObtainAcGsView and has been given a couple friends GetCurrentAcGsView and GetCurrent3dAcGsView

Good luck determining their differences.  This is an odd area where the managed reference and native ARX reference are quite different.

nekitip

  • Guest
Re: zoom to extents of Entity in paperspace or model using only objectid
« Reply #9 on: July 09, 2014, 02:30:38 PM »
I did try to use ObtainAcGsView as suggested, but I didn't know what kerneldescriptor is, so that is why I have no results from this.
Code - vb.net: [Select]
  1. Public Sub ZoomToObjects(oib As ObjectId, zoomFactor As Double)
  2.             Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
  3.             Using trans As Transaction = doc.Database.TransactionManager.StartTransaction
  4.                 Dim ent As Entity = trans.GetObject(oib, OpenMode.ForRead)
  5.  
  6.                 'int CvId = Convert.ToInt32((Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("CVPORT")));
  7.                 Dim CvId = Convert.ToInt32((Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("CVPORT")))
  8.                 Using gm As Autodesk.AutoCAD.GraphicsSystem.Manager = doc.GraphicsManager
  9.                     Using vw As Autodesk.AutoCAD.GraphicsSystem.View = gm.ObtainAcGsView(CvId, New Autodesk.AutoCAD.GraphicsSystem.KernelDescriptor)
  10.                         Dim ext As Extents3d = ent.GeometricExtents
  11.                         vw.ZoomExtents(ext.MinPoint, ext.MaxPoint)
  12.                         vw.Zoom(zoomFactor)
  13.  
  14.                         gm.SetViewportFromView(CvId, vw, True, True, False)
  15.                     End Using
  16.                 End Using
  17.             End Using
  18.         End Sub

I'll stick to my solution from my earlier post, as it works for me until this is cleared.
Good luck  :-(

LE3

  • Guest
Re: zoom to extents of Entity in paperspace or model using only objectid
« Reply #10 on: July 09, 2014, 02:54:26 PM »
^ no time to play, but see if any of my code here could help:
http://www.theswamp.org/index.php?topic=18383.msg516587#msg516587

Jeff H

  • Needs a day job
  • Posts: 6061
Re: zoom to extents of Entity in paperspace or model using only objectid
« Reply #11 on: December 12, 2014, 05:12:15 PM »
If you search for "AcGsKernelDescriptor" inside ObjectArx folder you see inside gs.h file.   

Code - C++: [Select]
  1.     static DRAWBRIDGE_API const AcUniqueString *k2DDrawing;    // "2D Drawing"
  2.     static DRAWBRIDGE_API const AcUniqueString *k3DDrawing;    // "3D Drawing"
  3.     static DRAWBRIDGE_API const AcUniqueString *k3DSelection;  // "3D Selection"

So you need something like
Code - C#: [Select]
  1.             KernelDescriptor kd = new KernelDescriptor();
  2.             kd.addRequirement(Autodesk.AutoCAD.UniqueString.Intern("3D Drawing"));
  3.  

And end up something like
Code - C#: [Select]
  1.         public void ZoomToObjects(Entity ent, double zoomFactor)
  2.         {
  3.             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.             KernelDescriptor kd = new KernelDescriptor();
  5.             kd.addRequirement(Autodesk.AutoCAD.UniqueString.Intern("3D Drawing"));          
  6.             int CvId = Settings.Variables.CVPORT;
  7.             using (Autodesk.AutoCAD.GraphicsSystem.Manager gm = doc.GraphicsManager)
  8.             using (Autodesk.AutoCAD.GraphicsSystem.View vw = gm.ObtainAcGsView(CvId, kd))
  9.             {
  10.                 Extents3d ext = ent.GeometricExtents;
  11.                 vw.ZoomExtents(ext.MinPoint, ext.MaxPoint);
  12.                 vw.Zoom(zoomFactor);
  13.                 gm.SetViewportFromView(CvId, vw, true, true, false);
  14.  
  15.             }
  16.         }
  17.  

It takes a while  and is slow for me and with an objectId this is much faster
Code - C#: [Select]
  1.                     SelectionSet ss = SelectionSet.FromObjectIds(new[] {id});
  2.                     Application.DocumentManager.MdiActiveDocument.Editor.SetImpliedSelection(ss);
  3.                     Application.DocumentManager.MdiActiveDocument.SendStringToExecute("Zoom " + "Object ", false, false, false);
  4.  

« Last Edit: December 12, 2014, 05:15:50 PM by Jeff H »