How to Zoom and Select Objects

How to Zoom and Select Objects

JC_BL
Advocate Advocate
4,134 Views
8 Replies
Message 1 of 9

How to Zoom and Select Objects

JC_BL
Advocate
Advocate

I am trying to write a program to select some circles, and then zoom to those circles.  So far I can select them, or I can zoom to them.  But I cannot do both.  I would like to know if someone can tell me what I have done wrong. 

The following is a sample program that demonstrates the problem.  It tries to select all the circles in the drawing, and then it tries to zoom to the circles:

 

[CommandMethod("Test_ZoomSelectCircle", CommandFlags.Session)]
public void TestZoomSelectCircle()
   // Find all the circles in the drawing. Zoom to them, and select them.
   {
   Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
   Editor   ed  = doc.Editor;

   // Find the Object-ID of all the circles.
   List<ObjectId> lisCircleObjId = new List<ObjectId>();
   lisCircleObjId = this.lisFindObjIdOfCircle();

   // Zoom to the area where the circles are.
   Autodesk.AutoCAD.DatabaseServices.Database db = doc.Database;
   using( Transaction trans = db.TransactionManager.StartTransaction() )
      {
      // Get the 3D-coordinates of the area where the circles are.
      var extSelObj = new Extents3d();
      foreach( ObjectId idObj in lisCircleObjId )
         {
         Entity entObj = (Entity)trans.GetObject( idObj, OpenMode.ForRead );
         if ( entObj != null )
            {
            extSelObj.AddExtents( entObj.GeometricExtents );
            }
         }

      ///////////////////////////////////
      //// OPTION 1: This can zoom and select. But after the circles have been zoomed correctl,
      ////           the drawing was reversed back to the original location. This is like the
      ////           zoom has been reversed.
      String sLowerLeftCornerCoord  = extSelObj.MinPoint.X.ToString() + "," +
                                      extSelObj.MinPoint.Y.ToString() + "," +
                                      extSelObj.MinPoint.Z.ToString();
      String sUpperRightCornerCoord = extSelObj.MaxPoint.X.ToString() + "," +
                                      extSelObj.MaxPoint.Y.ToString() + "," +
                                      extSelObj.MaxPoint.Z.ToString();
      String sZoomCmd = "_.ZOOM _W " + sLowerLeftCornerCoord + " " + sUpperRightCornerCoord + " ";
      dynamic appAcad = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication;
      appAcad.ActiveDocument.SendCommand( sZoomCmd );

      ed.SetImpliedSelection( lisCircleObjId.ToArray() );
      ///////////////////////////////////

      }
   } // TestZoomSelectCircle()

private List<ObjectId> lisFindObjIdOfCircle()
   {
   Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
   Editor   ed  = doc.Editor;

   List<ObjectId> lisObjectIdFound = new List<ObjectId>();

   try
      {
      TypedValue[] aTypeValue = new TypedValue[]
         {
         new TypedValue( Convert.ToInt32( DxfCode.Start ), "CIRCLE" )
         };

      SelectionFilter       oSF  = new SelectionFilter( aTypeValue );
      PromptSelectionResult oPSR = ed.SelectAll( oSF );
      if ( oPSR.Status == PromptStatus.OK )
         {
         SelectionSet ssCircle = oPSR.Value;
         foreach( SelectedObject oCircle in ssCircle )
            {
            lisObjectIdFound.Add( oCircle.ObjectId );
            }
         }
      }
   catch( System.Exception ex )
      {
      ed.WriteMessage( "\nError in getting ObjectId of all circles on the drawing. " +
                       "Error message is: " + ex.Message );
      }

   return( lisObjectIdFound );
   }

 

The following are the various other options that I have tried:

 

      ///////////////////////////////////
      //// OPTION 2: This can zoom; but cannot select.
      String sLowerLeftCornerCoord  = extSelObj.MinPoint.X.ToString() + "," +
                                      extSelObj.MinPoint.Y.ToString() + "," +
                                      extSelObj.MinPoint.Z.ToString();
      String sUpperRightCornerCoord = extSelObj.MaxPoint.X.ToString() + "," +
                                      extSelObj.MaxPoint.Y.ToString() + "," +
                                      extSelObj.MaxPoint.Z.ToString();
      String sZoomCmd = "_.ZOOM _W " + sLowerLeftCornerCoord + " " + sUpperRightCornerCoord + " ";
      ed.Document.SendStringToExecute( sZoomCmd, true, false, true );

      ed.SetImpliedSelection( lisCircleObjId.ToArray() );
      ///////////////////////////////////

      ///////////////////////////////////
      //// OPTION 3: This cannot zoom; but can select.
      dynamic appAcad = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication;
      appAcad.ZoomWindow( extSelObj.MinPoint.ToArray(), extSelObj.MaxPoint.ToArray() );

      ed.SetImpliedSelection( lisCircleObjId.ToArray() );
      ///////////////////////////////////

      ///////////////////////////////////
      //// OPTION 4: This cannot zoom; but can select.
      Autodesk.AutoCAD.Internal.Utils.SelectObjects( lisCircleObjId.ToArray() );
      Autodesk.AutoCAD.Internal.Utils.ZoomObjects( false );
      ///////////////////////////////////

      ///////////////////////////////////
      //// OPTION 5: This cannot zoom; but can select.
      String sLowerLeftCornerCoord  = extSelObj.MinPoint.X.ToString() + ", " +
                                      extSelObj.MinPoint.Y.ToString() + ", " +
                                      extSelObj.MinPoint.Z.ToString();
      String sUpperRightCornerCoord = extSelObj.MaxPoint.X.ToString() + ", " +
                                      extSelObj.MaxPoint.Y.ToString() + ", " +
                                      extSelObj.MaxPoint.Z.ToString();
      await ed.CommandAsync( "_.ZOOM", "W", sLowerLeftCornerCoord, sUpperRightCornerCoord );

      ed.SetImpliedSelection( lisCircleObjId.ToArray() );
      ///////////////////////////////////

      ///////////////////////////////////
      //// OPTION 6: This can select and zoom. But I have to hit ENTER to start zooming,
      ////           and the selection-grips disappears after zooming.
      ed.SetImpliedSelection( lisCircleObjId.ToArray() );

      await ed.CommandAsync( "_.ZOOM", "Object", "p", "" );
      ///////////////////////////////////

 

Please let me know the correct way to zoom and select the circles (or select and then zoom to the circles).  Thanks.

 

JC_BL

0 Likes
Accepted solutions (1)
4,135 Views
8 Replies
Replies (8)
Message 2 of 9

GTVic
Advisor
Advisor

Your option #6 should work with a small change. When you preselect entities and then use the ZOOM O command then the command is done. If you send a P then you are starting the PAN command which is why you have to press ENTER.

 

 

;; example with LISP
(setq ss1 (ssget))
(ssgetfirst nil ss1) ;; select
(command "zoom" "object") ;; zoom selected - objects are no longer selected
(ssgetfirst nil ss1) ;; reselect

;; another example with LISP
(setq ss1 (ssget))
(command "zoom" "object" ss1 "") ;; zoom selection set
(command "zoom" "0.9x") ;; zoom out a bit to see easier
(ssgetfirst nil ss1) ;; select

;; example with C#, not verified
ed.SetImpliedSelection( lisCircleObjId.ToArray() );
await ed.CommandAsync( "_ZOOM", "Object");
ed.SetImpliedSelection( lisCircleObjId.ToArray() );

 

 

Here is some more code:

https://www.keanw.com/2008/06/zooming-to-a-wi.html

 

Message 3 of 9

JC_BL
Advocate
Advocate

Thanks for fixing one of the problem.  Now the ZOOM-Object command won't force me to hit <ENTER> key to continue.

 

Unfortunately, attempting to select the circles one more time after zoom still cannot keep the circles selected.  Seem like the command tends to remove the selection after finishing running (in many options that I have tried).  I have a feeling that the CommandFlags settings in the function declaration area may have something to do with this behavior.  But checking all the options in CommandFlags doesn't tell me anything.

 

Further investigation tells me that CommandFlags.Session can affect the zoom/select behavior.  But I still cannot get both zoom/select to work.

 

I have tried all these options, none work:

   zoom/select

   select/zoom

   select/zoom/select

   select/zoom/select/select

 

The following is the latest sample program with the latest finding:

 

[CommandMethod("Test_ZoomSelectCircle",
               CommandFlags.UsePickSet | CommandFlags.Redraw | CommandFlags.Session)]
public void TestZoomSelectCircle()
   // Find all the circles in the drawing. Zoom to them, and select them.
   {
   Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
   Editor   ed  = doc.Editor;

   // Find the Object-ID of all the circles.
   List<ObjectId> lisCircleObjId = new List<ObjectId>();
   lisCircleObjId = this.lisFindObjIdOfCircle();

   // Zoom to the area where the circles are.
   Autodesk.AutoCAD.DatabaseServices.Database db = doc.Database;
   using( Transaction trans = db.TransactionManager.StartTransaction() )
      {
      // Get the 3D-coordinates of the area where the circles are.
      var extSelObj = new Extents3d();
      foreach( ObjectId idObj in lisCircleObjId )
         {
         Entity entObj = (Entity)trans.GetObject( idObj, OpenMode.ForRead );
         if ( entObj != null )
            {
            extSelObj.AddExtents( entObj.GeometricExtents );
            }
         }

      ///////////////////////////////////
      //// OPTION 1:
      ////     If CommandFlags.Session is used, this will try to zoom, undone the zoom,
      ////     and then select the circles.
      ////     If CommandFlags.Session is not used, this will zoom, but won't select the circles.
      String sLowerLeftCornerCoord  = extSelObj.MinPoint.X.ToString() + "," +
                                      extSelObj.MinPoint.Y.ToString() + "," +
                                      extSelObj.MinPoint.Z.ToString();
      String sUpperRightCornerCoord = extSelObj.MaxPoint.X.ToString() + "," +
                                      extSelObj.MaxPoint.Y.ToString() + "," +
                                      extSelObj.MaxPoint.Z.ToString();
      String sZoomCmd = "_.ZOOM _W " + sLowerLeftCornerCoord + " " + sUpperRightCornerCoord + " ";
      dynamic appAcad = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication;
      appAcad.ActiveDocument.SendCommand( sZoomCmd );

      ed.SetImpliedSelection( lisCircleObjId.ToArray() );
      ///////////////////////////////////

      }
   } // TestZoomSelectCircle()

private List<ObjectId> lisFindObjIdOfCircle()
   {
   Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
   Editor   ed  = doc.Editor;

   List<ObjectId> lisObjectIdFound = new List<ObjectId>();

   try
      {
      TypedValue[] aTypeValue = new TypedValue[]
         {
         new TypedValue( Convert.ToInt32( DxfCode.Start ), "CIRCLE" )
         };

      SelectionFilter       oSF  = new SelectionFilter( aTypeValue );
      PromptSelectionResult oPSR = ed.SelectAll( oSF );
      if ( oPSR.Status == PromptStatus.OK )
         {
         SelectionSet ssCircle = oPSR.Value;
         foreach( SelectedObject oCircle in ssCircle )
            {
            lisObjectIdFound.Add( oCircle.ObjectId );
            }
         }
      }
   catch( System.Exception ex )
      {
      ed.WriteMessage( "\nError in getting ObjectId of all circles on the drawing. " +
                       "Error message is: " + ex.Message );
      }

   return( lisObjectIdFound );
   }

 

The following are the other options that I have tried and the latest finding:

 

      ///////////////////////////////////
      //// OPTION 2: Regardless if CommandFlags.Session is used or not, this can zoom,
      ////           but cannot select.
      String sLowerLeftCornerCoord  = extSelObj.MinPoint.X.ToString() + "," +
                                      extSelObj.MinPoint.Y.ToString() + "," +
                                      extSelObj.MinPoint.Z.ToString();
      String sUpperRightCornerCoord = extSelObj.MaxPoint.X.ToString() + "," +
                                      extSelObj.MaxPoint.Y.ToString() + "," +
                                      extSelObj.MaxPoint.Z.ToString();
      String sZoomCmd = "_.ZOOM _W " + sLowerLeftCornerCoord + " " + sUpperRightCornerCoord + " ";
      ed.Document.SendStringToExecute( sZoomCmd, true, false, true );

      ed.SetImpliedSelection( lisCircleObjId.ToArray() );
      ///////////////////////////////////

      ///////////////////////////////////
      //// OPTION 3: Regardless if CommandFlags.Session is used or not, this can zoom,
      ////           but cannot select.
      dynamic appAcad = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication;
      appAcad.ZoomWindow( extSelObj.MinPoint.ToArray(), extSelObj.MaxPoint.ToArray() );

      ed.SetImpliedSelection( lisCircleObjId.ToArray() );
      ///////////////////////////////////

      ///////////////////////////////////
      //// OPTION 4: Regardless if CommandFlags.Session is used or not, this cannot zoom,
      ////           but can select.
      Autodesk.AutoCAD.Internal.Utils.SelectObjects( lisCircleObjId.ToArray() );
      Autodesk.AutoCAD.Internal.Utils.ZoomObjects( false );
      ///////////////////////////////////

      ///////////////////////////////////
      //// OPTION 5:
      ////     If CommandFlags.Session is used, the zoom command will get eInvalidInput error.
      ////     If CommandFlags.Session is not used, this cannot zoom, but can select.
      String sLowerLeftCornerCoord  = extSelObj.MinPoint.X.ToString() + ", " +
                                      extSelObj.MinPoint.Y.ToString() + ", " +
                                      extSelObj.MinPoint.Z.ToString();
      String sUpperRightCornerCoord = extSelObj.MaxPoint.X.ToString() + ", " +
                                      extSelObj.MaxPoint.Y.ToString() + ", " +
                                      extSelObj.MaxPoint.Z.ToString();
      await ed.CommandAsync( "_.ZOOM", "W", sLowerLeftCornerCoord, sUpperRightCornerCoord );

      ed.SetImpliedSelection( lisCircleObjId.ToArray() );
      ///////////////////////////////////

      ///////////////////////////////////
      //// OPTION 6:
      ////     If CommandFlags.Session is used, the zoom command will get eInvalidInput error.
      ////     If CommandFlags.Session is not used, this can zoom, but cannot select.
      ed.SetImpliedSelection( lisCircleObjId.ToArray() );
      await ed.CommandAsync( "_.ZOOM", "Object" );
      ed.SetImpliedSelection( lisCircleObjId.ToArray() );
      ///////////////////////////////////

 

Please let me know if there is a way to keep the selection after zoom.  Thanks.

 

JC_BL

0 Likes
Message 4 of 9

norman.yuan
Mentor
Mentor
Accepted solution

Firstly, for zooming:

 

Some of your options would not work well, such as calling SendStringToExecute(), or COM's SendCommand(), because they would run asynchronously, thus may not run in the sequences as you expected. It is really easy to create your own zooming method with .NET API (creating a view -  a ViewTableRecord - on the area in interest and pass it to Editor.SetCurrentView() method); or you can make a dynamic call to COM's AcadApplication.ZoomXXXX() method.

 

Then, the real issue that the zooming/selection getting lost, when the command finishes, is that you have an unnecessary Transaction that wraps all the zooming and selecting code, which is not committed at the end, meaning the transaction will roll back before it gets disposed, thus the lost of zooming.

 

You should end the transaction after the entity Ids are collection and before zooming. Oh, you should always commit the transaction, even it is opened only for read, unless you have reason to Abort() it. Starting a transaction without explicitly Commit()/Abort() it is bad practice, IMO.

 

Norman Yuan

Drive CAD With Code

EESignature

Message 5 of 9

JC_BL
Advocate
Advocate

Thanks for pointing out exactly where the problem was.  I didn't know that the transaction could have this kind of effect.  Now the program works -- it can zoom and select the circles.

 

The following is the corrected version of the program with the option that I have chosen:

 

[CommandMethod("Test_ZoomSelectCircle", CommandFlags.UsePickSet | CommandFlags.Redraw)]
public void TestZoomSelectCircle()
   // Find all the circles in the drawing. Zoom to them, and select them.
   {
   Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
   Editor   ed  = doc.Editor;

   // Find the Object-ID of all the circles.
   List<ObjectId> lisCircleObjId = new List<ObjectId>();
   lisCircleObjId = this.lisFindObjIdOfCircle();

   // Find out the area where the circles are.

   var extSelObj = new Extents3d();

   Autodesk.AutoCAD.DatabaseServices.Database db = doc.Database;
   using( Transaction trans = db.TransactionManager.StartTransaction() )
      {
      // Get the 3D-coordinates of the area where the circles are.
      foreach( ObjectId idObj in lisCircleObjId )
         {
         Entity entObj = (Entity)trans.GetObject( idObj, OpenMode.ForRead );
         if ( entObj != null )
            {
            extSelObj.AddExtents( entObj.GeometricExtents );
            }
         }
      trans.Commit();
      }

   // Zoom and select the circles.
   ///////////////////////////////////
   //// OPTION 3: This works as expected (zoom and select) regardless if
   ////           CommandFlags.Session is used or not.
   dynamic appAcad = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication;
   appAcad.ZoomWindow( extSelObj.MinPoint.ToArray(), extSelObj.MaxPoint.ToArray() );

   ed.SetImpliedSelection( lisCircleObjId.ToArray() );
   ///////////////////////////////////
   } // TestZoomSelectCircle()

private List<ObjectId> lisFindObjIdOfCircle()
   {
   Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
   Editor   ed  = doc.Editor;

   List<ObjectId> lisObjectIdFound = new List<ObjectId>();

   try
      {
      TypedValue[] aTypeValue = new TypedValue[]
         {
         new TypedValue( Convert.ToInt32( DxfCode.Start ), "CIRCLE" )
         };

      SelectionFilter       oSF  = new SelectionFilter( aTypeValue );
      PromptSelectionResult oPSR = ed.SelectAll( oSF );
      if ( oPSR.Status == PromptStatus.OK )
         {
         SelectionSet ssCircle = oPSR.Value;
         foreach( SelectedObject oCircle in ssCircle )
            {
            lisObjectIdFound.Add( oCircle.ObjectId );
            }
         }
      }
   catch( System.Exception ex )
      {
      ed.WriteMessage( "\nError in getting ObjectId of all circles on the drawing. " +
                       "Error message is: " + ex.Message );
      }

   return( lisObjectIdFound );
   }

 

I decide to use this option because it is easy enough, and there is no need to use asynchronous calling, and no need to use CommandFlags.Session.  I have tried to use a View to zoom to the area.  But somehow I didn't set the CenterPoint of the view correctly, and the program zooms to the lower-left corner outside of the area.  I decide to choose the option that uses AcadApplication.ZoomWindow() that also has your blessing.

 

The following is the status of the other options after I have corrected the program to terminate the transaction:

 

   ///////////////////////////////////
   //// OPTION 1:
   ////     If CommandFlags.Session is used, this works as expected (zoom and select).
   ////     If CommandFlags.Session is not used, this can zoom, but cannot select.
   String sLowerLeftCornerCoord  = extSelObj.MinPoint.X.ToString() + "," +
                                   extSelObj.MinPoint.Y.ToString() + "," +
                                   extSelObj.MinPoint.Z.ToString();
   String sUpperRightCornerCoord = extSelObj.MaxPoint.X.ToString() + "," +
                                   extSelObj.MaxPoint.Y.ToString() + "," +
                                   extSelObj.MaxPoint.Z.ToString();
   String sZoomCmd = "_.ZOOM _W " + sLowerLeftCornerCoord + " " + sUpperRightCornerCoord + " ";
   dynamic appAcad = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication;
   appAcad.ActiveDocument.SendCommand( sZoomCmd );

   ed.SetImpliedSelection( lisCircleObjId.ToArray() );
   ///////////////////////////////////

   ///////////////////////////////////
   //// OPTION 2: Regardless if CommandFlags.Session is used or not, this can zoom,
   ////           but cannot select.
   String sLowerLeftCornerCoord  = extSelObj.MinPoint.X.ToString() + "," +
                                   extSelObj.MinPoint.Y.ToString() + "," +
                                   extSelObj.MinPoint.Z.ToString();
   String sUpperRightCornerCoord = extSelObj.MaxPoint.X.ToString() + "," +
                                   extSelObj.MaxPoint.Y.ToString() + "," +
                                   extSelObj.MaxPoint.Z.ToString();
   String sZoomCmd = "_.ZOOM _W " + sLowerLeftCornerCoord + " " + sUpperRightCornerCoord + " ";
   ed.Document.SendStringToExecute( sZoomCmd, true, false, true );

   ed.SetImpliedSelection( lisCircleObjId.ToArray() );
   ///////////////////////////////////

   ///////////////////////////////////
   //// OPTION 4: This works as expected (zoom and select) regardless if
   ////           CommandFlags.Session is used or not.
   Autodesk.AutoCAD.Internal.Utils.SelectObjects( lisCircleObjId.ToArray() );
   Autodesk.AutoCAD.Internal.Utils.ZoomObjects( false );
   ///////////////////////////////////

   ///////////////////////////////////
   //// OPTION 5:
   ////     If CommandFlags.Session is used, the zoom command gets eInvalidInput error.
   ////     If CommandFlags.Session is not used, this works as expected (zoom and select).
   String sLowerLeftCornerCoord  = extSelObj.MinPoint.X.ToString() + ", " +
                                   extSelObj.MinPoint.Y.ToString() + ", " +
                                   extSelObj.MinPoint.Z.ToString();
   String sUpperRightCornerCoord = extSelObj.MaxPoint.X.ToString() + ", " +
                                   extSelObj.MaxPoint.Y.ToString() + ", " +
                                   extSelObj.MaxPoint.Z.ToString();
   await ed.CommandAsync( "_.ZOOM", "W", sLowerLeftCornerCoord, sUpperRightCornerCoord );

   ed.SetImpliedSelection( lisCircleObjId.ToArray() );
   ///////////////////////////////////

   ///////////////////////////////////
   //// OPTION 6:
   ////     If CommandFlags.Session is used, the zoom command gets eInvalidInput error.
   ////     If CommandFlags.Session is not used, this can zoom, but cannot select.
   ed.SetImpliedSelection( lisCircleObjId.ToArray() );
   await ed.CommandAsync( "_.ZOOM", "Object" );
   ed.SetImpliedSelection( lisCircleObjId.ToArray() );
   ///////////////////////////////////

 

We can see from above that option-4 also works.  But it uses Autodesk.AutoCAD.Internal.Utils that I am not familiar with.  Some other options also work; but they require CommandFlags.Session to be turned ON or OFF.  That just complicates things a bit.

 

Again, thanks for your help in identifying where the problem was and recommending a good solution.  I appreciate this greatly.

 

JC_BL

0 Likes
Message 6 of 9

sambhaji_burungale
Participant
Participant

Thank you!

Autodesk.AutoCAD.Internal.Utils.SelectObjects and  Autodesk.AutoCAD.Internal.Utils.ZoomObjects methods seems to be working fine. However, SelectObjects method needs objectId. So, it is not working for nozzles. I checked the Id property of NozzleSubPart. It is Null. Is there any way to select nozzles programmatically?

0 Likes
Message 7 of 9

kerry_w_brown
Advisor
Advisor

@sambhaji_burungale 

 

What is a 'nozzle' in your drawing ??




// Called Kerry or kdub in my other life.

Everything will work just as you expect it to, unless your expectations are incorrect. ~ kdub
Sometimes the question is more important than the answer. ~ kdub

NZST UTC+12 : class keyThumper<T> : Lazy<T>;      another  Swamper
0 Likes
Message 8 of 9

GTVic
Advisor
Advisor

If this is Plant 3D then you may want to ask in the Plant 3D forum which contains VB.Net and LISP code specific to that product.

 

AutoCAD Plant 3D Forum - Autodesk Community

0 Likes
Message 9 of 9

sambhaji_burungale
Participant
Participant

Yes, It is for Plant3D. I will ask question there. Thank you.

0 Likes