.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Zoom to a group of ObjectIds

4 REPLIES 4
SOLVED
Reply
Message 1 of 5
AlexFielder
1112 Views, 4 Replies

Zoom to a group of ObjectIds

If I have an ObjectIdCollection, what's the fastest way of determining the bounding box for that group of ObjectIds?

 

I was figuring something like the following:

 

public static void ZoomToGroup(ObjectIdCollection Group)
{
 Document doc = AcadApp.DocumentManager.MdiActiveDocument;
 Database db = doc.Database;
 Editor ed = doc.Editor;
 Extentds3d ext;

 using(Transaction tr = db.TransactionManager.StartTransaction())
  {
   foreach(ObjectId oid in Group)
    {
     Entity ent = (Entity)tr.GetObject(oid,OpenMode.ForRead);
     ext = ent.GeometricExtents;
     //I guess I can add these values to an array and then sort them using the ext.Min & ext.Max values?
    }
  }
 //Extents3d object zoomgroupext doesn't exist in this routine yet; I need to figure out how to achieve it!
 //ZoomWindow(ed, zoomgroupext.MinPoint, zoomgroupext.MaxPoint);
} 

 

I've been using LINQ for some of my code, would that be an efficient method to achieve the desired results?

4 REPLIES 4
Message 2 of 5
Anonymous
in reply to: AlexFielder

You're most of the way there.

 

I wouldn't bother with an array. Just keep a record of the maximum and minimum values for those objects.

 

So (and this is just pseudo-code):

 

 

//set up initial conditions to be extremes

lowestxvaluefound = 999999999999

lowestyvaluefound = 999999999999

highestxvaluefound = -999999999999

highestyvaluefound = -999999999999

 

for each object in group {

  xmin, xmax, ymin, ymax = boundaries for object

  if xmin < lowestxvaluefound then lowestxvaluefound = xmin

  if ymin < lowestyvaluefound then lowestyvaluefound = ymin

  if xmax > highestxvaluefound then highestxvaluefound = xmax

  if ymax > highestyvaluefound then highestyvaluefound = ymax

}

 

This should find the highest and lowest values of the bound boxes. Things to beware of is some objects can return a bounding box that doesn't bound the object. You're fine with basic entities like lines, polylines, circles etc, but I've had problems with angular dimensions and blocks.

 

Hope this helps,

Message 3 of 5
norman.yuan
in reply to: AlexFielder

Simply use Extents3d.AddExtents() on each entity to eventaully get an Extens3d enclose all entities' extents:

 

Extents3d TheExt=new Extents3d(new Point3d(0,0,0),newPoint3d(1,1,0);

foreach(ObjectId oid in Group)
 {
     Entity ent = (Entity)tr.GetObject(oid,OpenMode.ForRead);

 

     //Expand the Extents3d (TheExt)
     TheExt.AddExtents(ent.GeometricExtents)

;
     //I guess I can add these values to an array and then sort them using the ext.Min & ext.Max values?
 }

 

//Now you get an Extents3d enclose all entities' extents, do a window zoom to its min/max points

 

Norman Yuan

Drive CAD With Code

EESignature

Message 4 of 5
_gile
in reply to: norman.yuan

Hi,

 

Here's a ZoomObjects sample

 

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Linq;

namespace ZoomObjectSample
{
    public class Zoom
    {
        [CommandMethod("ZO")]
        public void ZO()
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            PromptSelectionResult psr = ed.GetSelection();
            if (psr.Status != PromptStatus.OK)
                return;
            ObjectIdCollection idCol = new ObjectIdCollection(psr.Value.GetObjectIds());
            ZoomObjects(idCol);
        }

        private void ZoomObjects(ObjectIdCollection idCol)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            using (ViewTableRecord view = ed.GetCurrentView())
            {
                Matrix3d WCS2DCS = Matrix3d.PlaneToWorld(view.ViewDirection);
                WCS2DCS = Matrix3d.Displacement(view.Target - Point3d.Origin) * WCS2DCS;
                WCS2DCS = Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) * WCS2DCS;
                WCS2DCS = WCS2DCS.Inverse();
                Entity ent = (Entity)tr.GetObject(idCol[0], OpenMode.ForRead);
                Extents3d ext = ent.GeometricExtents;
                ext.TransformBy(WCS2DCS);
                for (int i = 1; i < idCol.Count; i++)
                {
                    ent = (Entity)tr.GetObject(idCol[i], OpenMode.ForRead);
                    Extents3d tmp = ent.GeometricExtents;
                    tmp.TransformBy(WCS2DCS);
                    ext.AddExtents(tmp);
                }
                double ratio = view.Width / view.Height;
                double width = ext.MaxPoint.X - ext.MinPoint.X;
                double height = ext.MaxPoint.Y - ext.MinPoint.Y;
                if (width > (height * ratio))
                    height = width / ratio;
                Point2d center =
                    new Point2d((ext.MaxPoint.X + ext.MinPoint.X) / 2.0, (ext.MaxPoint.Y + ext.MinPoint.Y) / 2.0);
                view.Height = height;
                view.Width = width;
                view.CenterPoint = center;
                ed.SetCurrentView(view);
                tr.Commit();
            }
        }
    }
}

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 5
AlexFielder
in reply to: _gile

Thanks Will, Norman & Gile;

 

I initially implemented Will's suggestion, but I think Norman's suggestion is the most elegant.

 

🙂

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost