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?
Solved! Go to Solution.
Solved by _gile. Go to Solution.
Solved by norman.yuan. Go to Solution.
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,
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
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(); } } } }
Thanks Will, Norman & Gile;
I initially implemented Will's suggestion, but I think Norman's suggestion is the most elegant.
🙂