As I pointed out in the discussion of the new Revit 2013 API features, the add-in integration enhancements include a new View API, and it provides a new UIView class.
The UIView class represents a view window, enables you to pan, zoom and determine its size for tiling etc., and may be useful for switchback functionality from other visualization environments, for example.
I am very surprised that I have not heard anything more from the developer community about this class yet, nor received any cases querying it and its behaviour.
Maybe the entire humanity falls into just one of two classes: those who missed it entirely, and those who noticed and made use of it without any problem whatsoever.
Anyway, after waiting for a couple of months now and still hearing nothing about it from anyone else, I decided to try it out myself, and I must say I belong to the second group.
The UIView class provides only three methods of interest to us:
- GetWindowRectangle returning the rectangle containing the coordinates of the view's drawing area, in Windows coordinates.
- GetZoomCorners returning the corners of the view's rectangle, in Revit model coordinates.
- ZoomAndCenterRectangle, which zooms and centres the view to a specified rectangle.
The reason I find this so utterly exciting is that this is the first time in the history of mankind that we have any official possibility at all to correlate between Windows and Revit coordinates, opening unlimited new interaction possibilities. For instance, how about displaying your own tooltip during the Idling event?
I created a little external command WinCoords which exercises all three of these methods.
By the way, the only way that I saw to access a UIView instance was using the UIDocument GetOpenUIViews method, which returns a list of all of them.
Since each UIView has a property ViewId, we can easily pick the one corresponding to the document active view.
Here is my command implementation, which
- Gets the active view.
- Gets all UIView instances.
- Determines the UIView for the active view.
- Queries and reports its Windows and Revit coordinates.
- Calculates new Revit coordinates to zoom in by 10%.
- Calls ZoomAndCenterRectangle to do so.
Short and sweet, and a read-only command, of course:
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements ) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Document doc = uidoc.Document; View view = doc.ActiveView; UIView uiview = null; IList<UIView> uiviews = uidoc.GetOpenUIViews(); foreach( UIView uv in uiviews ) { if( uv.ViewId.Equals( view.Id ) ) { uiview = uv; break; } } Rectangle rect = uiview.GetWindowRectangle(); IList<XYZ> corners = uiview.GetZoomCorners(); XYZ p = corners[0]; XYZ q = corners[1]; string msg = string.Format( "UIView Windows rectangle: {0}; " + "zoom corners: {1}-{2}; " + "click Close to zoom in by 10%.", RectangleString( rect ), PointString( p ), PointString( q ) ); TaskDialog.Show( "WinCoords", msg ); // Calculate new zoom corners to // zoom in by 10%, i.e. the two corners // end up at 0.45 of their previous // distance to the centre point. XYZ v = q - p; XYZ center = p + 0.5 * v; v *= 0.45; p = center - v; q = center + v; uiview.ZoomAndCenterRectangle( p, q ); return Result.Succeeded; }
This is the task dialogue reporting the results in the 3D view of the rac_basic_sample_project.rvt:
After clicking 'Close', the view is zoomed in by 10 percent, as expected.
Since Windows coordinates have the Y direction reversed to normal systems, the rectangle display string is generated like this:
/// <summary> /// Return a string representing the /// given Rectangle instance size, in /// the order left+top, right+bottom. /// Windows coordinates reverse the Y /// direction! /// </summary> static string RectangleString( Rectangle r ) { return string.Format( "({0},{1})-({2},{3})", r.Left, r.Top, r.Right, r.Bottom ); }
Here is my little WinCoords sample including the entire source code, Visual Studio solution and add-in manifest for this command.
I hope you find this useful and am excited to see what you come up with making use of this.
Hi Jeremy,
some other view stuff:
When using UIDocument.ShowElement(...), Revit will search for a "good" view.
Imagine you want to show a chair in inside a building, residing on level 1.
There may be an opened viewplan, but it is showing level 0, not 1.
When invoking UIDoc.ShowElement(chair), Revit knows that there is no vaild view opened for this chair.
If there is also the {3D} view opened, Revit may switch to that view because our chair may be visible in that view.
Depending on the view angle, there may be some walls that hide the chair in the 3D view, so Revit's chosen view isn't a "good" view at all.
Is there a way to avoid Revit to open such a *false* view ?
Cheers,
Rudi
Posted by: Rudolf Honke | June 18, 2012 at 07:49
Hi Jeremy, This is very helpful, and timely, thanks. I have been struggling to simply Zoom Fit a view, and I am not sure this will help. Am I missing something obvious? Regards, Dale
Posted by: Dale Bartlett | June 19, 2012 at 01:27
Dear Dale,
Thank you for your appreciation, and I am glad you find it useful.
If you know the extents of the zoom fit this should suit your bill.
I would assume that the standard Revit zoom fit functionality just zooms to a region including all the element bounding boxes, and you can determine those yourself as well.
So it should work as far as I can tell.
Cheers, Jeremy.
Posted by: Jeremy Tammik | June 19, 2012 at 02:06
Dear Rudi,
I am not aware of any solution to that, sorry.
Cheers, Jeremy.
Posted by: Jeremy Tammik | June 19, 2012 at 02:08
Hi Jeremy,
thanks for this great post.
We are currently developing a gesture control app with kinect and were thinking about orbiting and panning.
But in 3D-View it is kind of difficult to manage these operations by modifing the Coords.
Do you have a good hint for a solution for us?
Cheers,
Alex
Posted by: Alex | October 28, 2012 at 09:25
Hi Alex,
Thank you for your appreciation. Glad you like it.
Great, your project sounds obercool.
No, I'm afraid I do not have any particularly good hints for you. I would have to do the same research as you. The view manipulation is a bit fiddly.
The best I can provide is all published:
http://thebuildingcoder.typepad.com/blog/view
I am very interested in hearing what you find out and how you solve this!
Cheers, Jeremy.
Posted by: Jeremy Tammik | October 29, 2012 at 13:33
UIView.ZoomToFit() was added to the API in 2014
Posted by: Harry Mattison | March 01, 2015 at 19:32