660 likes | 929 Views
CP204-3: Deep Dive on the Revit API: Advanced Topics. Matt Mason Director, Software Development, Avatech Solutions. Who Am I?. Director, Software Development for Avatech Solutions Veteran of over 60 small Revit Automation projects, 5 larger automation projects
E N D
CP204-3: Deep Dive on the Revit API:Advanced Topics Matt Mason Director, Software Development, Avatech Solutions
Who Am I? • Director, Software Development for Avatech Solutions • Veteran of over 60 small Revit Automation projects, 5 larger automation projects • Avatech BIMreview – now Autodesk Revit Model Review • Avatech Utilities at: http://www.avatech.com/web/revitutilities • Room Renumber, Door Mark Update, Revit Google Earth Connector, Content Browser, Change Case, GridSelect, Room Phase Copy, Space Matches Room • Revit API Blogger, at: http://cadappdev.blogspot.com
Goal of the Presentation • Cover Deep Topics in the Revit API • Explore API issues with Real-World Revit Models Housekeeping: • Q&A • Source Code • Prizes!
Revit Knowledge – Why? • I used to scoff. • Then I tried it for real. • Now I understand everything I didn’t know…
Agenda • What can you do with the Revit API in 2009? • Elements, Parameters and Snooping. • Filters (Quick) • Building Analysis / Extracting Geometry • Transactions • Real-World Revit Issues • And more…
The Revit API is… Good For… Not Good For… Interactive Applications Larger-scale Design Automation Advanced Costing • Data Extraction / Data Import • Geometry Extraction • Parameter Manipulation • Building Analysis • Basic Design Automation / Configuration • Automated Export/Printing • Revit Family Creation/Manipulation *
Elements and Parameters • Element => Parameters • There are 2277 Built-in Parameters • Simple – but represent incredible power • Not really documented • MgdRvtDbg: The Snoop Tool
Code: Reading Parameter // simple parameter reading Parameterparam= myWall.get_Parameter( BuiltInParameter.WALL_USER_HEIGHT_PARAM); double height = param.AsDouble();
Code: Setting Parameter Values Parameterparam= myWall.get_Parameter( BuiltInParameter.WALL_USER_HEIGHT_PARAM); // setting the parameter by internal value param.Set( 20.5 ); // setting the parameter by the Display Value param.SetValueString( "20' 6\"" );
Filters: Querying for Model Elements • Historical How To? • Concept • Samples • Performance
The Old Way… // retrieving rooms List<Element> roomList = new List<Element>(); // the original way ElementIteratoriter = myDocument.Elements; while (iter.MoveNext()) { if (iter.Current is Room) roomList.Add(iter.Currentas Room); }
The 2008 Way: List<Element> roomList = new List<Element>(); // the 2008 way ElementIteratoriter = myDocument.get_Elements( typeof(Room) ); while (iter.MoveNext()) { roomList.Add(iter.Currentas Room); }
Filters: Concept Category Filter i.e. ‘Rooms’ Elements Category Filter i.e. ‘Doors’ Logical AND Elements Type Filter ‘FamilyInstance’
Filters: The New Way // the 2009/2010 way Filter rcFilter = myApp.Create.Filter.NewCategoryFilter( BuiltInCategory.OST_Rooms); // OR Filter rtFilter = myApp.Create.Filter.NewTypeFilter(typeof(Room)); int count = myDocument.get_Elements(rcFilter, roomList);
Filters: Building Complex Filters with Logic //NOTE: can’t ask for just Door Category Filter dcFilter = myApp.Create.Filter.NewCategoryFilter(BuiltInCategory.OST_Doors); Filter fiFilter = myApp.Create.Filter.NewTypeFilter(typeof(FamilyInstance)); Filter combined = myApp.Create.Filter.NewLogicAndFilter(dcFilter, fiFilter); List<Element> doors = new List<Element>(); intnumDoors = myDocument.get_Elements(combined, doors);
Filters: Performance Searching 5000 elements for Walls and Rooms. • Old “Bad” Way: 3500 ms • Old “Good” Way: 120 ms • New “Filters” Way: 40 ms
Filters: Types of Filters • Category Filter • Type Filter • Family Name Filter • Instance Usage Filter (structural analysis) • Material Filter • Parameter Value Filter • Structural Type Filter (structural analysis) • Symbol Name Filter • Wall Usage Filter (structural analysis)
Filters: Key Points • Filters are more elegant/readable than the old way • Category Filters are substantially faster than checking the category of each element. • Type Filters are slower than Category Filters • When combining filters, think about the order of operations.
Building Analysis: What’s New? Revit 2010 Adds: • Shoot Rays – What do you hit? • Get Room at Point / Get Space at Point What can you do with this? • Determine the true ceiling height in a room • Get the room finishes for surrounding walls • Determine which rooms a pipe network flows through • Find Exterior Walls • And more…
Building Analysis: Shooting Rays Inputs: • An origin point • A direction vector • A View3D element Outputs: • A list of References
Building Analysis: What is a Reference? Reference Objects Contain: • Element: The element that was hit • ElementReferenceType: Mesh, Surface, Instance, Linear, etc • GeometryObject: The face, edge, or other geometry that was hit • GlobalPoint: The X,Y,Z location of the hit • ProximityParameter: The distance from the original point • UVPoint: The U,V point on a face (if applicable) – good for computing the normal angle
Shooting Rays: Code public List<Reference> ShootRay(XYZ origin, XYZ vector, View3D v3D ) { ReferenceArray refs = _doc.FindReferencesByDirection(origin, vector, v3D); if (refs == null) return null; List<Reference> refList = new List<Reference>(); foreach (Reference refer in refs) refList.Add(refer); return refList; }
Extracting Geometry: View-Based Getting Geometry: Element.get_Geometry(options) Option 1: Specific View Option 2: View=NULL
Extracting Geometry: Options Options options = new Options(); options.ComputeReferences = true; // we want references to work with options.View = null; // get a 3D view options.DetailLevel = Options.DetailLevels.Fine;
Extracting Geometry: Options Element geo = myWall.get_Geometry(options); if (geo != null) { foreach (GeometryObjectgObjectin geo.Objects) { if (gObject is Autodesk.Revit.Geometry.Solid) { Solid mySolid = gObjectas Solid; // do something specific here } } }
Geometry Quirks Solid -> Faces -> EdgeLoops ->Edges • Circulation • Inner/Outer Domains
Commands/Applications that work in the Family Editor Batch create families Wizard Family Creation Maintenance of family parameters/etc Family analysis for modeling consistency/standards Extracting Families from Projects Detecting if a family has been changed from its “approved” state Changing categories or templates Determining authoritatively that a consistent shared parameter was used Family API: New in 2010 • Now you can… • Still hard/impossible..
Family API: Key Concepts • Document object covers both projects and families • Key Document members: • Document.IsAFamilyDocument() • Document.EditFamily( fam ) • Document.OwnerFamily • Document.FamilyCreate
Family API: Code // given a document _doc that you have created from the plumbing family template: // lookup the view for plan View planView = lookupViewByName( "Ref. Level", ViewType.FloorPlan ); // initialize the options DWGImportOptionsoptions = new DWGImportOptions() { OrientToView = false, View = planView };
Family API: Code // put it in a transaction _doc.BeginTransaction(); Element planImport = null; _doc.Import(@"C:\temp\basin_plan4.dwg", options, out planImport); //change the option for elevation View elevation = lookupViewByName( "Front",ViewType.Elevation); options.View = elevation; Element elevImport = null; _doc.Import(@"C:\temp\basin_elevation10.dwg", options, out elevImport);
Family API: Code // set the visibilities (need to cast the elements to instances) ImportInstanceelev = elevImportas ImportInstance; elev.SetVisibility(new FamilyElementVisibility(FamilyElementVisibilityType.Model) { IsShownInLeftRight = false, IsShownInTopBottom = false }); ImportInstance plan = planImportas ImportInstance; plan.SetVisibility(new FamilyElementVisibility(FamilyElementVisibilityType.Model) { IsShownInLeftRight = false, IsShownInFrontBack = false }); // set the type info for the current (single) type _doc.FamilyManager.NewType("BBR18-12F");// no default type FamilyParameter manufacturer = lookupParameter("Manufacturer"); FamilyParameterpartNumber = lookupParameter("Model"); _doc.FamilyManager.Set(manufacturer, "ABC Basins, Inc"); _doc.FamilyManager.Set(partNumber, "BBR18-12F"); _doc.EndTransaction(); // force Revit to show it... _doc.ShowElements(planImport);
Quick Tip: Showing Your Work Document.ShowElements() • To show a single element: Document.ShowElements( theElement ); • To (try to) open a specific view:Document.ShowElements( theView.Elements ); • After loading a model programmatically – do a “ShowElements()” on something to force Revit to show it.
Transaction: Concepts Begin Transaction Do Work Abort Transaction End Transaction
Transaction: Explicit // start a transaction try { myDocument.BeginTransaction(); // make a change to the model here myDocument.EndTransaction(); } catch { myDocument.AbortTransaction(); }
Transaction: Effects • Visualization • Updated Data
Transactions: ExternalCommands • You are already IN a transaction public IExternalCommand.Result Execute(ExternalCommandDatacommandData, ref string message, ElementSet elements) { try { // Your command details here… return IExternalCommand.Result.Succeeded; // NOTE: THIS MODIFIES THE MODEL!!!!!!! } catch { return IExternalCommand.Result.Failed; } }