Author Topic: Zoom to entity by handle.  (Read 9668 times)

0 Members and 1 Guest are viewing this topic.

VVeli

  • Newt
  • Posts: 27
Zoom to entity by handle.
« on: September 30, 2013, 06:54:30 AM »
Hi,
I like to share this code in forum because it hits my head to wall in every week.
Have you ever try to zoom to specific object in dwg database? This is for zooming
 to exact object and object is also selected in the end. ZoomToWindow function is
borrowed from Keanīs blog.

Cheers
Veli V.
Code - vb.net: [Select]
  1. Public Shared Sub ZoomToWindow(ByVal minPoint As Point2d, ByVal maxPoint As Point2d)
  2.             Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
  3.             Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
  4.             Dim view As ViewTableRecord = ed.GetCurrentView()      'get the current view
  5.             Using trans As Transaction = db.TransactionManager.StartTransaction()
  6.                 view.Width = maxPoint.X - minPoint.X               'get the entity' extends configure the new current view
  7.                 view.Height = maxPoint.Y - minPoint.Y
  8.                 view.CenterPoint = New Point2d(minPoint.X + (view.Width / 2), minPoint.Y + (view.Height / 2))
  9.                 ed.SetCurrentView(view)                            'update the view
  10.                 trans.Commit()
  11.             End Using
  12.         End Sub
  13.  
  14. <CommandMethod("BPTools", "BPZoomToEntity", CommandFlags.Modal)> Public Sub BPZoomToEntity()
  15.             Dim doc As Document = Application.DocumentManager.MdiActiveDocument
  16.             Dim db As Database = doc.Database
  17.             Dim ed As Editor = doc.Editor
  18.             Dim stOpt As New PromptStringOptions(vbCrLf + "Enter entity handle: ")
  19.             Dim resStr As PromptResult = ed.GetString(stOpt)
  20.             If resStr.Status <> PromptStatus.OK Then Exit Sub
  21.             Dim ln As Long = Convert.ToInt64(resStr.StringResult, 16)   ' Convert hexadecimal string to 64-bit integer
  22.             Dim hn As Handle = New Handle(ln)                           ' Not create a Handle from the long integer
  23.             Dim entId As ObjectId = db.GetObjectId(False, hn, 0)        ' And attempt to get an ObjectId for the Handle
  24.             If entId <> ObjectId.Null Then
  25.                 Dim ent As Entity = Nothing
  26.                 Dim extends As Extents3d = Nothing
  27.                 Using tr As OpenCloseTransaction = doc.TransactionManager.StartOpenCloseTransaction
  28.                     ent = tr.GetObject(entId, OpenMode.ForRead)
  29.                     extends = ent.GeometricExtents
  30.                     tr.Commit()
  31.                 End Using
  32.                 BPClasses.BPZoomToEntity.ZoomToWindow(New Point2d(extends.MinPoint.X, extends.MinPoint.Y), _
  33.                                                       New Point2d(extends.MaxPoint.X, extends.MaxPoint.Y))
  34.                 ed.SetImpliedSelection(New ObjectId() {})              'If there was a pickfirst set, clear it
  35.                 ed.SetImpliedSelection(New ObjectId() {entId})
  36.             End If
  37.         End Sub
  38.  
« Last Edit: October 11, 2013, 06:38:21 AM by VVeli »

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Zoom to entity by handle.
« Reply #1 on: September 30, 2013, 09:57:43 AM »
You can try this
Code - C#: [Select]
  1.  
  2.    public void ZoomToObjects(Entity ent, double zoomFactor)
  3.         {            
  4.             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  5.          
  6.                 //int CvId = Convert.ToInt32((Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("CVPORT")));
  7.             int CvId = SystemVariables.CVPORT;
  8.                 using (Autodesk.AutoCAD.GraphicsSystem.Manager gm = doc.GraphicsManager)
  9.                 using (Autodesk.AutoCAD.GraphicsSystem.View vw = gm.GetGsView(CvId, true))
  10.                 {
  11.                     Extents3d ext = ent.GeometricExtents;
  12.                     vw.ZoomExtents(ext.MinPoint, ext.MaxPoint);
  13.                     vw.Zoom(zoomFactor);
  14.                     gm.SetViewportFromView(CvId, vw, true, true, false);
  15.                    
  16.                 }
  17.         }
  18.  

VVeli

  • Newt
  • Posts: 27
Re: Zoom to entity by handle.
« Reply #2 on: October 01, 2013, 02:21:48 AM »
Thanks Jeff!
That looks easier to update the viewport.
-Veli

Update to earlier code:
if the entity is empty block we have to catch GeometricExtents error "eNullExtents".
http://adndevblog.typepad.com/autocad/2012/12/entitygeometricextents-throws-an-exception-enullextents.html
« Last Edit: October 04, 2013, 03:22:35 AM by VVeli »

BillZndl

  • Guest
Re: Zoom to entity by handle.
« Reply #3 on: October 01, 2013, 07:25:24 AM »
//int CvId = Convert.ToInt32((Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("CVPORT"))); 

        int CvId = SystemVariables.CVPORT;

Very curious about the above line. ^
Is there a reference to this?

Thx

I've been using this for multiple object Id's in a group:
Code: [Select]
private static void ZoomToPart(ObjectId[] Eids, Transaction trans, Document doc)
        {                   
                Extents3d exts =
                    Eids.Select(id => ((Entity)trans.GetObject(id, OpenMode.ForRead)).GeometricExtents).Aggregate(
                    (e1, e2) => { e1.AddExtents(e2); return e1; });       
                                               
                int CvId = Convert.ToInt32((Application.GetSystemVariable("CVPORT")));               
                using (Manager gm = doc.GraphicsManager)
                using (View vw = gm.GetGsView(CvId, true))
                {
                    vw.ZoomExtents(exts.MinPoint, exts.MaxPoint);                   
                    gm.SetViewportFromView(CvId, vw, true, true, false);
                }   
        }
« Last Edit: October 01, 2013, 07:29:26 AM by BillZndl »

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Zoom to entity by handle.
« Reply #4 on: October 01, 2013, 07:37:21 AM »
Not to detour the thread but you can also just do a simple cast.
Code: [Select]
    var cvport = (short)Application.GetSystemVariable("CVPORT");
Revit 2019, AMEP 2019 64bit Win 10

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Zoom to entity by handle.
« Reply #5 on: October 01, 2013, 07:40:46 AM »
 :-)@Bill,
I'd guess that Jeff has an extension library with some goodies in it. :-)

@MexicanCustard,
That has me wondering ... Int16 or Int32 ??

added:
bummer, that's going to be on my mind till it's resolved ... I had thought Int32
« Last Edit: October 01, 2013, 07:50:43 AM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Zoom to entity by handle.
« Reply #6 on: October 01, 2013, 08:05:24 AM »

I have code that uses either  :|

The GetGsView takes an int (officially), but I don't s'pose it matters ....

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Zoom to entity by handle.
« Reply #8 on: October 03, 2013, 03:28:18 AM »
        int CvId = SystemVariables.CVPORT;

Very curious about the above line. ^
Is there a reference to this?
Hi Bill,
That method did return a short but once value had been marshaled and under control of CLR going from short to int is a widening conversion so it implicitly casted.
 
Was just some code had laying around and the initial idea for SystemVariable class was to be able to set variables with some type safety and other checks like making sure it fell in range, or if a bitcode was a valid number.
Also have a indexer method for variables hardly used and the ability to add methods easily for new and/or variables that I find myself needing to set more than once and in different places.
Also wanted the ability to undo or roll back to a initial state mainly when scripting a command.
Tony has some nice implementations posted here you can search for(I think in ExportLayout example and in Library thread for Layout, Plot, etc....)

Tonight was the first time in a couple months I had time to sit down and play a little and here is what I ended up with.
Initially the properties for the variables were static, but was easier to change to instance methods to be able to reuse for temporarily setting the variables, so  SystemVariables.CVPORT would now be SystemVariables.Current.CVPORT
 
 
First maybe a little example of using class
Basically in CTAB example can set it through indexer or through CTAB property which uses indexer.
 The other 2 use the TemporarySystemVariable class which inherits from SystemVariable, and it just overrides the indexer to save the initial state before calling base implementation.
Code - C#: [Select]
  1.    public class SystemVariTest : CommandClass
  2.     {
  3.        [CommandMethod("CTABSystemVariable")]
  4.        public void CTABSystemVariable()
  5.        {
  6.            
  7.            Ed.WriteLine(SystemVariables.Current["CTAB"]);
  8.            SystemVariables.Current["CTAB"] = "Layout1";
  9.            Ed.WriteLine(SystemVariables.Current["CTAB"]);
  10.            SystemVariables.Current.CTAB = "Model";
  11.        }
  12.  
  13.        [CommandMethod("UCSFOLLOWTempSystemVariable")]
  14.        public void UCSFOLLOWTempSystemVariable()
  15.        {
  16.            Ed.WriteLine(SystemVariables.Current.UCSFOLLOW);
  17.            using (TemporarySystemVariables temps = new TemporarySystemVariables())
  18.            {
  19.                Ed.WriteLine(temps.UCSFOLLOW);
  20.                temps.UCSFOLLOW = !temps.UCSFOLLOW;                            
  21.                Ed.WriteLine(temps.UCSFOLLOW);              
  22.            }
  23.            Ed.WriteLine(SystemVariables.Current.UCSFOLLOW);
  24.      
  25.        }
  26.        [CommandMethod("OSMODETempSystemVariable")]
  27.        public void OSMODETempSystemVariable()
  28.        {
  29.            Ed.WriteLine(SystemVariables.Current.OSMODE.ToString());
  30.            using (TemporarySystemVariables temps = new TemporarySystemVariables())
  31.            {
  32.                Ed.WriteLine(temps.OSMODE.ToString());
  33.                temps.OSMODE = OsnapMode.Endpoint | OsnapMode.Midpoint;
  34.                Ed.WriteLine(temps.OSMODE.ToString());
  35.            }
  36.            Ed.WriteLine(SystemVariables.Current.OSMODE.ToString());
  37.        }
  38.     }
  39.  
Here is SystemVariable Class
Code - C#: [Select]
  1. using System;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. namespace Autodesk.AutoCAD.ApplicationServices.Core
  4. {
  5.     public class SystemVariables
  6.     {
  7.         private static SystemVariables _current = new SystemVariables();
  8.         public static SystemVariables Current {get { return _current; } }
  9.         internal SystemVariables()
  10.         {
  11.         }
  12.         /// Would be nice to just let the name of the method be passed, and with .NET 4.5 a easy way
  13.         /// would be with [CallerMemberName] attribute
  14.         /// http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute.aspx
  15.         /// Requires .NET 4.5
  16.         ////private T GetSystemVariable<T>([CallerMemberName] string name = null)
  17.         ////{
  18.         ////    return (T)this[name];
  19.         ////}
  20.        
  21.         private T GetSystemVariable<T>(string name)
  22.         {
  23.             return (T)this[name];
  24.         }
  25.         private void SetSystemVariable<T>(string name, T value)
  26.         {
  27.             this[name] = value;  
  28.         }
  29.         private bool GetBoolSystemVariable(string name)
  30.         {
  31.            short val = GetSystemVariable<short>(name);
  32.            if (val == 1)
  33.             {
  34.                 return true;
  35.             }
  36.             else
  37.             {
  38.                 return false;
  39.             }
  40.         }
  41.         private void SetBoolSystemVariable(string name, bool value)
  42.         {
  43.             if (value)
  44.            {
  45.                SetSystemVariable<short>(name, 1);
  46.            }
  47.            else
  48.            {
  49.                SetSystemVariable<short>(name, 0);
  50.            }
  51.         }
  52.         public short CVPORT
  53.         {
  54.             get { return GetSystemVariable<short>("CVPORT"); }
  55.             set { SetSystemVariable<short>("CVPORT", value); }
  56.         }
  57.         public bool DWGTITLED
  58.         {
  59.             get { return GetBoolSystemVariable("DWGTITLED"); }        
  60.         }
  61.         public bool UCSFOLLOW
  62.         {
  63.             get { return GetBoolSystemVariable("UCSFOLLOW"); }
  64.             set { SetBoolSystemVariable("UCSFOLLOW", value); }
  65.         }
  66.         public string CMDNAMES
  67.         {
  68.             get { return GetSystemVariable<string>("CMDNAMES"); }
  69.         }
  70.         ///////  Think commands can have '(apostrophe) in them and would cause problem
  71.         //           public ICollection<string> CMDNAMES
  72.         //           {
  73.         //               get { return GetSystemVariable<string>("CMDNAMES").Split('\''); }
  74.         //           }
  75.         public string CTAB
  76.         {
  77.             get { return GetSystemVariable<string>("CTAB"); }
  78.             set { SetSystemVariable<string>("CTAB", value); }
  79.         }
  80.         public OsnapMode OSMODE
  81.         {
  82.             get { return GetSystemVariable<OsnapMode>("OSMODE"); }
  83.             set { SetSystemVariable<short>("OSMODE", (short)value); }
  84.         }
  85.         public virtual object this[string name]
  86.         {
  87.             get
  88.             {
  89.                 if (name.IsNullOrWhiteSpace())
  90.                 {
  91.                     throw new ArgumentNullException("{0} is Empty or Null", name);
  92.                 }
  93.                 try
  94.                 {
  95.                     return Application.GetSystemVariable(name);
  96.                 }
  97.                 catch (Autodesk.AutoCAD.Runtime.Exception ex)
  98.                 {
  99.                     if (ex.ErrorStatus == Runtime.ErrorStatus.InvalidInput)
  100.                     {
  101.                         throw new ArgumentException("InvalidName", name);
  102.                     }
  103.                     else
  104.                     {
  105.                         throw;
  106.                     }
  107.                 }
  108.             }
  109.             set
  110.             {
  111.                 try
  112.                 {
  113.                     Application.SetSystemVariable(name, value);
  114.                 }
  115.                 catch (Autodesk.AutoCAD.Runtime.Exception ex)
  116.                 {
  117.                     if (ex.ErrorStatus == Runtime.ErrorStatus.InvalidInput)
  118.                     {
  119.                         throw new ArgumentException(String.Format("{0}:{1} is Invalid", name, value));
  120.                     }
  121.                     throw;
  122.                 }
  123.             }
  124.         }
  125.     }
  126. }
  127.  

and TemporarySystem variable class
Code - C#: [Select]
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Autodesk.AutoCAD.ApplicationServices.Core
  4. {
  5.    public class TemporarySystemVariables : SystemVariables, IDisposable
  6.     {
  7.        public TemporarySystemVariables()
  8.        {
  9.        }
  10.        private Dictionary<string, object> _variables = new Dictionary<string, object>();
  11.        public override object this[string name]
  12.        {
  13.            get
  14.            {
  15.                return base[name];
  16.            }
  17.            set
  18.            {
  19.                if (!_variables.ContainsKey(name))
  20.                {
  21.                    _variables.Add(name, base[name]);
  22.                }
  23.                base[name] = value;
  24.            }
  25.        }
  26.        public void Dispose()
  27.        {
  28.            foreach (var variable in _variables)
  29.            {
  30.                base[variable.Key] = variable.Value;
  31.            }
  32.            _variables.Clear();
  33.        }
  34.     }
  35. }
  36.  
  37.  

Just threw it together and have not tested but very little, and until use it a little a bit not sure if I will be like it or not.
Sure the other guys here have better ideas they can add.
 
Will need to change WriteLine to WriteMessage, and get rid of CommandClass inheritance, etc....
I think the only thing left out was OsnapMode for OSMODE to work
Code - C#: [Select]
  1.     [Flags]
  2.     public enum OsnapMode : short
  3.     {
  4.         None = 0,
  5.         Endpoint = 1,
  6.         Midpoint = 2,
  7.         Center = 4,
  8.         Node = 8,
  9.         Quadrant = 16,
  10.         Intersection = 32,
  11.         Insertion = 64,
  12.         Perpendicular = 128,
  13.         Tangent = 256,
  14.         Nearest = 512,
  15.         Quick = 1024,
  16.         ApparentIntersection = 2048,
  17.         Extension = 4096,
  18.         Parallel = 8192,
  19.     }
  20.  

 
 
« Last Edit: October 03, 2013, 03:47:52 AM by Jeff H »

BillZndl

  • Guest
Re: Zoom to entity by handle.
« Reply #9 on: October 03, 2013, 11:02:32 AM »
Thanks Jeff.

I've been playing with the idea of getting system variables directly from a dwg database using ReadDWGFile.
Couldn't seem to get that idea to work but I ended up with a class full of properties of the System Variables in R2012.
It looks atrocious but I wrote it using the list returned by the Setvar command with some string manipulations in Autolisp (very little hand editing).
Not sure if it's good for anything except all the practice I got in .net.
The only trouble was it wouldn't let me name a property that started with a numeral (3DConversionMode and a few others).

I'll attach the files in case anyone wants to see/test them.
One is a method for testing using properties from the command line using a LispFunction.

Don't know when I'll get time to do more on this, just was curious when I saw your code.
Thanks again!

Bill



Jeff H

  • Needs a day job
  • Posts: 6144
Re: Zoom to entity by handle.
« Reply #10 on: October 03, 2013, 11:16:05 AM »
If it is a variable that is associated with drawing then most are already a property of Database object.
Database.Celtype
..
Database.Dimaso
..
etc..
 

BillZndl

  • Guest
Re: Zoom to entity by handle.
« Reply #11 on: October 03, 2013, 11:52:07 AM »
If it is a variable that is associated with drawing then most are already a property of Database object.
Database.Celtype
..
Database.Dimaso
..
etc..

Yes, I did see that.
I think the trouble I had was getting a list of the available properties from the database.
That will probably be another adventure in programming, when I get time.

BillZndl

  • Guest
Re: Zoom to entity by handle.
« Reply #12 on: October 03, 2013, 01:06:07 PM »
If it is a variable that is associated with drawing then most are already a property of Database object.
Database.Celtype
..
Database.Dimaso
..
etc..

Yes, I did see that.
I think the trouble I had was getting a list of the available properties from the database.
That will probably be another adventure in programming, when I get time.

Just opened a whole 'nother world.  :)
Code: [Select]
database.ReadDwgFile(str, System.IO.FileShare.ReadWrite, false, ""); 
                           
                            PropertyInfo[] propInfo = database.GetType().GetProperties();

                            foreach (PropertyInfo pin in propInfo)
                            {
                                editor.WriteMessage("\nProp Val: < " + pin.PropertyType.Name);
                            }

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2122
  • class keyThumper<T>:ILazy<T>
Re: Zoom to entity by handle.
« Reply #13 on: January 26, 2023, 04:25:00 PM »

< .. trim .. >

Code - C#: [Select]
  1.           using (TemporarySystemVariables temps = new TemporarySystemVariables())
  2.            {
  3.  
  4.            }


< .. trim .. >


belated thanks Jeff.
I've stolen this  :)

and thanks to Tony . . .

Regards,
Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.