Author Topic: Trouble shooting ZoomAndCenter  (Read 126 times)

0 Members and 1 Guest are viewing this topic.

Atook

  • Swamp Rat
  • Posts: 834
Trouble shooting ZoomAndCenter
« on: August 03, 2017, 07:26:40 pm »
I've got a method that zooms and centers the view on an object, based on Gile's contribution here.

My version of the code is as follows:
Code - C#: [Select]
  1. /// <summary>
  2. /// Zooms to and highlight the entity in question.
  3. /// </summary>
  4. /// <param name="id">The ObjectID of the entity to zoom to.</param>
  5. /// <param name="scale">factor to zoom out by, higher number is a wider zoom</param>
  6. public static void ZoomToAndHighlight(ObjectId id, double scale)
  7. {
  8.  using (LockedTransaction lTr = Active.Document.TransactionManager.StartLockedTransaction())
  9.  {
  10.    Entity ent = lTr.GetObject(id, OpenMode.ForRead, false) as Entity;
  11.    if (ent!=null)
  12.    {
  13.      using (ViewTableRecord view = Active.Editor.GetCurrentView())
  14.      {
  15.        Active.WriteMessage($"Starting view centered on {view.CenterPoint}, height:{view.Height}, width:{view.Width}");
  16.  
  17.        // get the extents
  18.        Extents3d ext = ent.GeometricExtents;
  19.        // transform extents
  20.        Matrix3d WCS2DCS = Matrix3d.PlaneToWorld(view.ViewDirection);
  21.        WCS2DCS = Matrix3d.Displacement(view.Target - Point3d.Origin)*WCS2DCS;
  22.        WCS2DCS = Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target);
  23.        WCS2DCS = WCS2DCS.Inverse();
  24.        ext.TransformBy(WCS2DCS);
  25.        double width = ext.MaxPoint.X - ext.MinPoint.X;
  26.        double height = ext.MaxPoint.Y - ext.MinPoint.Y;
  27.        // calculate center, width and height
  28.        Point2d center = new Point2d((ext.MaxPoint.X + ext.MinPoint.X)/2, (ext.MaxPoint.Y + ext.MinPoint.Y)/2);
  29.        view.Width = scale * width;
  30.        view.Height = scale * height;
  31.        view.CenterPoint = center;
  32.        Active.WriteMessage($"New view to be centered at {center}, height:{height}, width:{width}, WCS2DCS:{WCS2DCS}");
  33.        Active.Editor.SetCurrentView(view);
  34.  
  35.        // this isn't working, this just verifies what the current view is
  36.        ViewTableRecord nView = Active.Editor.GetCurrentView();
  37.        Active.WriteMessage($"Moved view centered on {nView.CenterPoint}, height:{nView.Height}, width:{nView.Width}");
  38.        // TODO highlight the given entity...
  39.      }
  40.    }
  41.    lTr.Commit();
  42.  }
  43. }
  44.  

You can see that I'm writing the coordinates to the command line for troubleshooting purposes. The view in question should be centered on (3183274.93594949,1432379.113886) and is called out as so on the command line, but is instead centered on approximately (6365835,2864340) as shown in the cursor location. It's almost like the coordinates are getting doubled when the view is being set in SetCurrentView(view).

I double check the currentview after the move with the nView variable and it's showing the values as they were set, not whats shown on the screen.

Anyone got any ideas as to what I'm missing? UCS is set to world, but that shouldn't matter with the transformation.

gile

  • Water Moccasin
  • Posts: 2089
  • Marseille, France
Re: Trouble shooting ZoomAndCenter
« Reply #1 on: August 04, 2017, 12:00:58 am »
Hi,

It seems to me there's something wrong with the WCS2DCS matrix construction.
Speaking English as a French Frog

Atook

  • Swamp Rat
  • Posts: 834
Re: Trouble shooting ZoomAndCenter
« Reply #2 on: August 04, 2017, 02:49:25 am »
Hmm.. seems there may have been a problem re-using the view variable.

If I instantiate a new ViewTableRecord (nView), the method works as expected.

The code currently looks like this:

Code - C#: [Select]
  1. /// <summary>
  2. /// Zooms to and highlight the entity in question.
  3. /// </summary>
  4. /// <param name="id">The ObjectID of the entity to zoom to.</param>
  5. /// <param name="scale">factor to zoom out by, higher number is a wider zoom</param>
  6. public static void ZoomToAndHighlight(ObjectId id, double scale)
  7. {
  8.  using (LockedTransaction lTr = Active.Document.TransactionManager.StartLockedTransaction())
  9.  {
  10.    Entity ent = lTr.GetObject(id, OpenMode.ForRead, false) as Entity;
  11.    if (ent!=null)
  12.    {
  13.      using (ViewTableRecord view = Active.Editor.GetCurrentView())
  14.      {
  15.        // get the extents
  16.        Extents3d ext = ent.GeometricExtents;
  17.        // transform extents
  18.        Matrix3d WCS2DCS = Matrix3d.PlaneToWorld(view.ViewDirection);
  19.        WCS2DCS = Matrix3d.Displacement(view.Target - Point3d.Origin)*WCS2DCS;
  20.        WCS2DCS = Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target);
  21.        WCS2DCS = WCS2DCS.Inverse();
  22.        ext.TransformBy(WCS2DCS);
  23.        // calculate center, width and height
  24.        double width = ext.MaxPoint.X - ext.MinPoint.X;
  25.        double height = ext.MaxPoint.Y - ext.MinPoint.Y;
  26.        Point2d center = new Point2d((ext.MaxPoint.X + ext.MinPoint.X)/2, (ext.MaxPoint.Y + ext.MinPoint.Y)/2);
  27.        // Create a new ViewTableRecord to use
  28.        ViewTableRecord nView = new ViewTableRecord();
  29.        nView.Width = scale * width;
  30.        nView.Height = scale * height;
  31.        nView.CenterPoint = center;
  32.        Active.Editor.SetCurrentView(nView);
  33.        nView.Dispose();
  34.        // highlight the given entity
  35.        Autodesk.AutoCAD.Internal.Utils.SelectObjects(new ObjectId[]{id});
  36.      }
  37.    }
  38.    lTr.Commit();
  39.  }
  40. }
  41.  

Gile, thank you so much for posting the framework of this method!

gile

  • Water Moccasin
  • Posts: 2089
  • Marseille, France
Re: Trouble shooting ZoomAndCenter
« Reply #3 on: August 04, 2017, 12:45:29 pm »
Here're the extension methods I use:

Code - C#: [Select]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.Geometry;
  4. using Autodesk.AutoCAD.Runtime;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8.  
  9. namespace Autodesk.AutoCAD.EditorInput
  10. {
  11.    public static class ExtensionMethods
  12.    {
  13.        public static Matrix3d EyeToWorld(this ViewTableRecord view)
  14.        {
  15.            if (view == null)
  16.                throw new ArgumentNullException("view");
  17.  
  18.            return
  19.                Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) *
  20.                Matrix3d.Displacement(view.Target - Point3d.Origin) *
  21.                Matrix3d.PlaneToWorld(view.ViewDirection);
  22.        }
  23.  
  24.        public static Matrix3d WorldToEye(this ViewTableRecord view)
  25.        {
  26.            return view.EyeToWorld().Inverse();
  27.        }
  28.  
  29.        public static void Zoom(this Editor ed, Extents3d ext)
  30.        {
  31.            if (ed == null)
  32.                throw new ArgumentNullException("ed");
  33.  
  34.            using (ViewTableRecord view = ed.GetCurrentView())
  35.            {
  36.                ext.TransformBy(view.WorldToEye());
  37.                view.Width = ext.MaxPoint.X - ext.MinPoint.X;
  38.                view.Height = ext.MaxPoint.Y - ext.MinPoint.Y;
  39.                view.CenterPoint = new Point2d(
  40.                    (ext.MaxPoint.X + ext.MinPoint.X) / 2.0,
  41.                    (ext.MaxPoint.Y + ext.MinPoint.Y) / 2.0);
  42.                ed.SetCurrentView(view);
  43.            }
  44.        }
  45.  
  46.        public static void ZoomCenter(this Editor ed, Point3d center, double scale = 1.0)
  47.        {
  48.            if (ed == null)
  49.                throw new ArgumentNullException("ed");
  50.  
  51.            using (ViewTableRecord view = ed.GetCurrentView())
  52.            {
  53.                center = center.TransformBy(view.WorldToEye());
  54.                view.Height /= scale;
  55.                view.Width /= scale;
  56.                view.CenterPoint = new Point2d(center.X, center.Y);
  57.                ed.SetCurrentView(view);
  58.            }
  59.        }
  60.  
  61.        public static void ZoomExtents(this Editor ed)
  62.        {
  63.            if (ed == null)
  64.                throw new ArgumentNullException("ed");
  65.  
  66.            Database db = ed.Document.Database;
  67.            db.UpdateExt(false);
  68.            Extents3d ext = (short)Application.GetSystemVariable("cvport") == 1 ?
  69.                new Extents3d(db.Pextmin, db.Pextmax) :
  70.                new Extents3d(db.Extmin, db.Extmax);
  71.            ed.Zoom(ext);
  72.        }
  73.  
  74.        public static void ZoomObjects(this Editor ed, IEnumerable<ObjectId> ids)
  75.        {
  76.            if (ed == null)
  77.                throw new ArgumentNullException("ed");
  78.  
  79.            using (Transaction tr = ed.Document.TransactionManager.StartTransaction())
  80.            {
  81.                Extents3d ext = ids
  82.                    .Where(id => id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Entity))))
  83.                    .Select(id => ((Entity)tr.GetObject(id, OpenMode.ForRead)).GeometricExtents)
  84.                    .Aggregate((e1, e2) => { e1.AddExtents(e2); return e1; });
  85.                ed.Zoom(ext);
  86.                tr.Commit();
  87.            }
  88.        }
  89.  
  90.        public static void ZoomScale(this Editor ed, double scale)
  91.        {
  92.            if (ed == null)
  93.                throw new ArgumentNullException("ed");
  94.  
  95.            using (ViewTableRecord view = ed.GetCurrentView())
  96.            {
  97.                view.Width /= scale;
  98.                view.Height /= scale;
  99.                ed.SetCurrentView(view);
  100.            }
  101.        }
  102.  
  103.        public static void ZoomWindow(this Editor ed, Point3d p1, Point3d p2)
  104.        {
  105.            using (Line line = new Line(p1, p2))
  106.            {
  107.                ed.Zoom(line.GeometricExtents);
  108.            }
  109.        }
  110.    }
  111. }
Speaking English as a French Frog