Today, let's look at how to determine the size and location of a sheet and the views displayed by it.
This is part of the first and most Revit-related of the three enhancement goals for my simplified 2D BIM editor:
- Display selected BIM elements in their sheet and view context – in addition to pure model space room and family instance elements.
- Display and edit non-graphical parameters – in addition to the purely graphical family instance outlines.
- Implement more graphical editing using translation and rotation grip points – in addition to the simple rotation button.
In previous versions of Revit, determining the size and locations of views on a sheet was a pretty challenging undertaking.
Here are some related explorations:
- List all sheets and their views – CmdListViews
- Determine sheet size – CmdSheetSize
- Determine view location on sheet – using Viewport bounding box
- Exact viewport positioning – using Viewport Outline
Nowadays, the Viewport class provides an Outline property that considerably simplifies this task.
Here is a sheet 'A101 - Level 0, 1 and 3D' displaying three views:
My GeoSnoop utility dynamically generates this temporary form displaying the outlines of the sheet and the three views it contains:
The top level code in the CmdUploadSheets external command implementation retrieving the sheet and viewport loops and displaying them in a temporary modeless form basically just consists of two lines of code, calling the new GetSheetViewportLoops and the existing GeoSnoop.DisplayLoops methods:
foreach( ViewSheet sheet in sheets ) { JtLoops sheetViewportLoops = GetSheetViewportLoops( sheet ); string sheet_number = sheet.get_Parameter( BuiltInParameter.SHEET_NUMBER ) .AsString(); caption = string.Format( "Sheet and Viewport Loops - {0} - {1}", sheet_number, sheet.Name ); GeoSnoop.DisplayLoops( revit_window, caption, false, sheetViewportLoops ); }
The GeoSnoop.DisplayLoops method is pretty much unchanged from its last incarnation for displaying room and furniture loops using symbols, except that the family instances and symbol geometry arguments now are optional and default to null.
The interesting new code to retrieve the sheet and viewport rectangles is short and sweet, making use of a couple of extensions I added to the existing Point2dInt and JtLoop classes:
/// <summary> /// Return polygon loops representing the size /// and location of given sheet and the viewports /// it contains. /// </summary> static JtLoops GetSheetViewportLoops( ViewSheet sheet ) { Document doc = sheet.Document; List<Viewport> viewports = sheet .GetAllViewports() .Select<ElementId,Viewport>( id => doc.GetElement( id ) as Viewport ) .ToList<Viewport>(); int n = viewports.Count; JtLoops sheetViewportLoops = new JtLoops( n + 1 ); BoundingBoxUV bb = sheet.Outline; // (0,0), (2.76,1.95) JtBoundingBox2dInt ibb = new JtBoundingBox2dInt(); // (0,0),(840,...) ibb.ExpandToContain( new Point2dInt( bb.Min ) ); ibb.ExpandToContain( new Point2dInt( bb.Max ) ); JtLoop loop = new JtLoop( 4 ); loop.Add( ibb.Corners ); sheetViewportLoops.Add( loop ); foreach( Viewport vp in viewports ) { XYZ center = vp.GetBoxCenter(); Outline outline = vp.GetBoxOutline(); ibb.Init(); ibb.ExpandToContain( new Point2dInt( outline.MinimumPoint ) ); ibb.ExpandToContain( new Point2dInt( outline.MaximumPoint ) ); loop = new JtLoop( 4 ); loop.Add( ibb.Corners ); sheetViewportLoops.Add( loop ); } return sheetViewportLoops; }
The updated RoomEditorApp source code, Visual Studio solution and add-in manifest live in the RoomEditorApp GitHub repository.
The version discussed above is release 2015.0.2.8.