Thursday, February 28, 2008

Revit 2009 API: Parameter Improvements

As I've mentioned elsewhere, you can't overstate the importance of Parameters in the Revit API... It probably represents 40% of everything you can do, and it's integral in every application I can think of. So it's nice to see Autodesk continuing to try to improve it.

Background
In Revit, there are three kinds of parameters:

  • Built-In Parameters (there are some 2,272 of these in Revit 2009 - and you'd mostly recognize them from the properties dialogs for each element - but not all of them).
  • Project Parameters (created by the user, in the model).
  • Shared Parameters (created by the user, often by importing them from a shared parameter file - which can work across models)

From the API perspective, however, I'd say that there are only two - Built-in and not built-in parameters (there are some slight differences from the API between Project and Shared - but I'd call them minor for most usual purposes).

Parameter Access

If you were trying to get the value of a built-in parameter, it was pretty easy:

Parameter myWallHeight =
wallElement.get_Parameter( BuiltInParameters.WALL_USER_HEIGHT_PARAM );

Easy for built-in parameters. For non-built-in parameters, it's a different story. The only way to find the parameter was to iterate through the list of parameters in Element.Parameters and try to match on a Parameter.Definition.Name. It was noticeably slow if you were doing it across a whole model.

In 2009, two different improvements were introduced, with I believe the intent of improving the performance of parameter access:

The ParametersMap member of the element class has an array of all the "visible"** parameters on an element - and you're able to index one parameter out by name, for example:

Parameter myFireRating =
wallElement.ParametersMap.get_Item("MyFireRating");

conversely, you can get the same now by:

Parameter myFireRating =
wallElement.get_Parameter( "MyFireRating" );

I haven't wrapped my head around the advantages of the ParametersMap method - but I can tell you one of the advantages of the Element.get_Parameter( String paramName ) approach:

While all of the approaches are case-sensitive on the parameter name (so be careful), the Element.get_Parameter approach returns a NULL if there's no match - whereas the ParametersMap approach throws an Exception if there's no match.

TypeOfStorage

One tricky thing when you're trying to write something generic is anticipating what "data type" one of the 2,272 BuiltIn Parameters will be. You can't actually figure it out until you can find an element which HAS that parameter assigned to it. In 2009, Autodesk has added:

Document.TypeOfStorage( BuiltInParameter );

So you can just ask what the data type is for STAIRS_ATTR_BALUSTER_SPACING_TYPE (or any other obscure parameter) without needing to track down an actual usage of it.

It's forward progress.

One Last Little GUID...

One other small thing (although for a certain small number of you - this is absolutely critical). When you use a Shared Parameter File and create a parameter from it, it creates what is called a GUID for the parameter. For the un-initiated among you - that's programmer-speak for Globally-Unique-IDentifier - a random mix of letters and numbers which are statistically guaranteed to pretty much never ever happen again. It looks something like this:

{3F2504E0-4F89-11D3-9A0C-0305E82C3301}

the trick is, that the GUID lived in the shared parameter file, and when you imported the shared parameter file into the NEXT Revit model, your "MyFireRating" parameter would have the same GUID in both models. This is important - if you lost your Shared Parameter file, or if you just arbitrarily created another "MyFireRating" parameter in a second model - it was not the same parameter... It was a different parameter that happened to have the same name, but some bad things happened if you tried to schedule things, etc (this is extremely common in Revit Family Development - if you want the same parameter in all your families, it has to have the same GUID).

Sorry for all the backstory - here's the payoff. Prior to 2009, once you imported the parameter - the original GUID was hidden forever... If you lost your original file, you were done.

But thanks to a quiet little enhancement in 2009, you can now go into the ExternalDefinition of any shared parameter, and see the GUID property. So take heart! those of you who thought you'd have to remodel half your content because you lost your shared parameter file (because you didn't know you needed it) - you may still be saved!

-Matt

P.S. Speaking of Visible Parameters... That's a good post for another day. First, because it is possible to have "Invisible" shared parameters... but I was actually referring to another aspect. All the Parameters that are listed in the Parameters (or ParametersMap) collection - that's not really all of them, you know? There's more...........

Revit 2009 API: VSTA: Here Comes the Neighborhood

Historical Commentary (skip unless you're bored!)


It's strange to see, looking back, how the API grows in tandem with each product.


In the AutoCAD world, there was LISP pretty darn close to the beginning (I wasn't there - so I can't rattle off the exact version number it appeared like some of my compatriots can). And look AutoCAD now - there's LISP, VBA, ARX and AutoCAD.NET (and that's an over simplification as well as leaving out some of the more obscure APIs).


In Autodesk Inventor, the API (C++ and COM/VBA) came out around Inventor 5.0 (roughly?) - and has gone from under-powered to very powerful (dropping the C++ support along the way).


Revit went from no API to a Microsoft.NET API... A sort of "walled-garden" which somehow still seemed to exclude the masses of people who might be interested in automation.



Changes Ahead?


Well - all that is about it change - sort of. Revit 2009 introduces Microsoft VSTA - that's Visual Studio Tools for Applications - the next generation follow-on to VBA (Visual Basic for Applications).




Autodesk talks a lot about "democratizing technology" - and nothing has democratized programming like VBA (and LISP). It really enabled technically savvy people to experiment with programming in a friendly environment, which was tightly tied to the CAD system. VSTA should do the same thing - although it's got its differences.


But weren't there already free ways to...?


For a while, there was a price obstacle - if you wanted to develop for Revit, most people thought you needed to fork out $800-$1200 USD for Microsoft Visual Studio. While there were technically other low-cost options, it was a conceptual barrier as much as anything.


In 2005, Microsoft introduced the free "Express Edition" of Visual Studio, which enabled users to develop software without the upfront costs (with some limitations - like limited or no ability to debug things at runtime - an invaluable capability).


I would still argue, however, that there were significant hurdles there - whether it was getting Visual Studio loaded, or the arcane way that Revit external applications are included into Revit via a REVIT.INI file. VSTA will remove many of the logistical obstacles.


It's Like VBA!


VSTA (once installed - it's one of the "Additional Products" available on the Revit DVD) - enables you to write and run "Macros". You develop inside of the VSTA IDE (Integrated Development Environment) - a nice, light version of Visual Studio which provides Intellisense (where you just need to type the first letter or two and it offers you all the choices for what you were trying to do). Like VBA, you're able to step through or set breakpoints in your projects to debug them.


Also like VBA, the macros can be stored either externally or within a document. The document approach lets the code travel with your Revit model! There are some neat things that you can do with that (so long as you're not worried about your code getting away from you).




It's Not Like VBA!



Here's where things get different...


The language is not exactly like Visual Basic / VBA. You write your macros using your choice of either Visual Basic.NET or C# (pronounced C-Sharp).


While Visual Basic.NET is incrementally more challenging than VBA - the good news is that there are many books, courses, and online content to help you. The great part about including C# as well is that there is also a wealth of online content (as well as Revit SDK samples) in C# - and these samples can typically be pasted in with only minor modifications - so VSTA is not a "second-class citizen" as VBA sometimes was.


The Content is the Same...


One key thing to understand - it's all the same Revit API. With only minor differences, the API that is available in VSTA is exactly what is available to traditional Microsoft.NET developers for Revit applications - so there's very little holding you back.


Here Comes the Neighborhood


When anything gets "democratized" like this - there's an occasional sense of unease amongst the previous members of the exclusive club - that it's not quite as special now that everyone can do it. I personally am fighting this off - on the theory that this will accelerate the Revit API development going forward. The more users who are interested and aware of what the Revit API can do, the more attention Autodesk will pay to extending their capabilities.


Where to Get Started?


There are several areas to learn about to begin your quest:


- VSTA itself


- Visual Basic.NET or C# Language


- Revit API development (general)


VSTA - there have been some AU sessions on VSTA in the past, which you can access at AU Online if you attended those AUs. You can also visit the Microsoft VSTA developer center (although take note that Revit 2009 ships with VSTA 1.0 (which corresponds to Visual Studio 2005) - Microsoft is currently touting the forthcoming VSTA 2.0 / Visual Studio 2008).


Visual Basic.NET - There are probably hundreds of books and tens of thousands of online articles and other content... You have to pick what works for you.


Revit API development - You can download the Revit SDK from here. (although the 2009 link is not posted as of this writing). This will include samples (both traditional, as well as some VSTA). Finally, Autodesk Developer Network has published one of its DeveloperTV episodes on the same site to give you a brief overview of Revit development.


Online/In-Person classes - Avatech Solutions (who I work for) is considering providing online and in-person classes for people who want to learn to program Revit using VSTA. If you're interested in something like this, contact us at ( devfeedback (at) avat.com ).


In closing


To all you VBA developers or otherwise talented tinkerers - welcome to the world of Revit development!


-Matt







Revit 2009 API: New Creationism

In the beginning, there was the API - and you could create virtually nothing. Then came the basic elements, then the structural elements... Release by release, Autodesk is slowly making progress to the point where you can make a wide variety of elements through the API.

Every year people want to know - "what new element types can I create that I couldn't create in the past?".



What's Newly Possible to Create in 2009?


  • Area

  • AreaViewPlan

  • AreaTag

  • AreaBoundaryLine

  • Space (MEP)

  • SpaceTag

  • SpaceBoundaryLine

  • RoomBoundaryLine

  • CurtainSystem

  • ExtrusionRoof

  • FootPrintRoof

  • Gutter

  • Fascia

  • FoundationWall

  • Electrical System (MEP)

  • SlabEdge

  • SpotCoordinate

  • SpotElevation

  • Truss

  • Zone (MEP)

  • Wire (MEP)

So that's a good set of new elements, right?

While it's not necessarily enough to generate an entire design from scratch, I've always been of the opinion that with a system like Revit you're better off with the "template" approach for "end-to-end" automation anyway.

There's definitely enough there to make some intelligent tools to automate specific aspects of the design.


Batch Creation


If you tried creating a large number of elements in 2008 or before, you may have noticed that it was rather, well, slow. Avatech once tried to automate a point cloud into Revit 2008 - and I think the application is still running many months later :). Autodesk improved on this during 2008 with the introduction of a SuspendUpdate object, which addressed part of the problem (the problem that Autodesk was fully updating the Revit model after each element was created). This was improved again in 2008 SP2.


In 2009, Autodesk has gone down a different path to help with performance. They have introduced a number of new methods which can batch create a variety of specific types of elements.
  • Family Instances

  • Rooms

  • Spaces

  • Text Notes

  • Walls (Profiled or Rectangular).

The new methods take a List of data to create each element.


For example, the NewRooms() method looks like this:


List<Autodesk.Revit.Creation.RoomCreationData> roomData =
new List<Autodesk.Revit.Creation.RoomCreationData>();

// get the current view's level
Level myLevel = doc.ActiveView.GenLevel;

// create arbitrary rooms at 10 foot intervals
// (I hope there are walls there to separate!).


for (int i=0; i < color="#3366ff">Autodesk.Revit.Creation.RoomCreationData
(myLevel, new UV(i * 10.0, 0))
);
}


ElementSet rooms = doc.Create.NewRooms( roomData );


//////////////////////////


All in all, there's some good additions to Revit's creation-ability.


-Matt


Revit 2009 API: Rooms for Improvement

Whether you're working in pure architectural development, or particularly if you're involved in doing energy analysis work - Room objects are VERY, VERY important.


The 2009 API provides a variety of modest enhancements to rooms which improve what you can do with rooms and their related objects:


Room.ClosedShell



If you've ever wanted to get a better handle on the analytical geometry of a room than you could get with just the room boundaries (sloped ceilings, anyone?).




The 2009 API adds support for getting the ClosedShell geometry of a room. This geometry is much like getting the solid geometry of an element - it returns something that behaves like an Autodesk.Geometry.Solid - it has faces and edges that you can traverse.



PlanCircuits are Working...




2008 added support for a concept that it took me a long time to get my arms around (thanks to limited documentation, nudge, nudge). A document has a collection of "PlanTopologies" - one for every combination of Level and Phase (i.e. "Level 1, New Construction"). For each PlanTopology there are a number of openings defined by the walls where rooms might exist. Each opening is called a "PlanCircuit" - while you can't find out as much as you might like about a PlanCircuit (the area, the number of sides, etc).


Anyway - there was a property for 2008 called PlanCircuit.IsRoomLocated - which could tell you if a room existed... That said, from the time I tried it in mid 2008 until the 2009 alpha - it never worked. In fact, it threw an exception if you even tried to touch it.


Now it's working - and you can use it for a variety of things - mostly determining if there are rooms placed in all of the openings that there should be. There's even a NewRoom() method which takes a PlanCircuit as an input.


Tagging Is Improved



When room tagging was added in 2008 - it worked great - as long as you only had one view of a given Level/Phase. This was remedied in 2008 SP3 with a NewRoomTag() method where you can specify which view the tag should reside in - that said, bad things happened if you tried to build with SP3 and try that method in 2008 SP2 or lower - so it's nicer now that it's in a General Availability version of the Revit Software.


From Room / To Room



I've heard a variety of people complaining to me about the nature of the From Room / To Room in 2009. If you're not familiar with it - when a door (or window for that matter) is placed it immediately gets a From Room and To Room designation. This is usually based upon its initial orientation (which room it opens into) - however, it never appears to change (even if you flip the door direction).


One of the Revit Product Managers told me that it has historical roots in the lockset and which side that goes to - but I'm sure that was cold comfort to people who just wanted it to be based on the direction that it opens.


While the underlying behavior has not changed - it is now possible to programmatically change the From/To Room. We'll probably add this to our "Door Mark Update" utility in 2009.



Room.UnPlace()

It's now possible to "unplace" a room - which moves the room into an unplaced state (similar to adding new rooms via the schedule which have not been placed yet). The Rooms can be placed into another spot based on X,Y location or PlanCircuit.


Interactive Change


While this isn't an API change - it is something I very much appreciate. If you wanted to understand the room height, the best trick was usually to create a Section view - then turn on visibility of Rooms, as well as Room -> Interior Fills and References. The problem in 2008 was that while you could see them perfectly - you couldn't pick or otherwise change them.


In 2009, you can not only pick the rooms in Section View, you can take an drag the height of the room to a new level.


Base Level Offset

This is both an interactive aspect and an API aspect - in the past there was only a height offset from the "upper level". Now there is both an "upper level" offset and "lower level offset".


Calculation Settings


Another nice thing if you're doing Energy or MEP calculations - you can now programmatically set the Room Volume Calculation Settings (Areas or Volumes, as well as the wall boundary option). This is identical to the Settings -> Room and Area Calculations dialog box.


Whew!


While there are few earth-shaking things in here - there's a lot of incremental progress... and for people in the right functional areas, it's huge.


-Matt

Revit 2009 API: Searching Improves

One of the areas which is nice to see Autodesk's continuing investments in is Searching within a Revit model.

Searching is a fundamental activity - almost every Revit application that exists, whether it's just to look up a symbol or whether it's a full-blown analysis application needs to scan the model looking for specific elements.

There were already a few different methods of searching within the model - GuyR and I had a spirited discussion about them recently on the AUGI board.... and Guy developed a test application to perform a speed test of the three ways...

The test involves scanning an aribitary Revit model looking for either Walls or Walls and Rooms, using all the different methods available.

In Revit 2008, these were the results:



































Case 1Case 2










  • Bad: Iterating through each element - testing for the category to match
  • Better: Testing the .NET Type of each element, looking for the right ones.

  • MyBest: (Guy's Best): The same as better - but don't even cast down to a Revit Element to save some cycles.

  • ElementFilterIterator: Use the get_Elements( type ) method to get all the elements in one call.

While I have historically preferred the ElementFilterIterator approach, Guy's method is faster - particularly if you're looking for more than one type. If you are looking for more than one type (as shown in case #2 - in Guy's method you only have to iterate through once - whereas ElementFilterIterator is almost twice as slow). ElementFilterIterator also has another quirk - it does not handle subclass types - so if you ask for "View", you're not going to get "View3D" or "ViewSheet"...

Important Note: As a side note on a pure "Category" approach - remember that asking for Walls will give you both "Walls" and "Wall Styles"... So I think it's likely that you'll almost always need to screen by "Type", not just by "Category".

2009 Rolls in...

So when 2009 came across my desk, I was curious to see what had changed. Autodesk had promised some performance enhancements to searching - what form would they take? I modified Guy's application to support the two new searching mechanisms - and I figured that we'd re-test the others, because it was said that they could improve as well.

The new Filtering mechanisms

Revit 2009 introduces the concept of "filters" which can be used to define the criteria for finding elements - this includes searching by:

  • Category
  • Type
  • Family
  • InstanceUsage
  • Material
  • Parameter Value
  • Structural Type
  • Symbol
  • Wall Usage

What's more, you can combine filters using the LogicAND, LogicNOT, and LogicOR filters. So you could, with one call, look for Doors made of a particular material (OK, Material is a tricky one - perhaps that's a bad example).

What does it look like?

// get the categories

Category _wallCat = _doc.Settings.Categories.get_Item( BuiltInCategory.OST_Walls );
Category _roomCat = _doc.Settings.Categories.get_Item( BuiltInCategory.OST_Rooms );


//make the filter
CategoryFilter wallFilter = _app.Create.Filter.NewCategoryFilter(_wallCat);
CategoryFilter roomFilter = _app.Create.Filter.NewCategoryFilter(_roomCat);

// put the filters together
Filter myFilter =
_app.Create.Filter.NewLogicOrFilter(wallFilter, roomFilter);

ElementIterator esi = _document.get_Elements(myFilter);

So how did things turn out in 2009?

































Case 1Case 2







So what has changed?

Strangely - Guy's best approach consistently comes up slightly slower than his "better" approach - that I can't explain. The ElementFilterIterator approach performs about the same - even though it has been significantly changed - it now uses an ElementIterator instead, and it supports SubTypes.

The most interesting changes are for the new mechanisms - Filter Criteria based searching. While we didn't explore all of them - we can see that:


  • Type-based searching was roughtly the same as the ElementFilterIterator approach

  • The Category search absolutely SMOKED everything else - particularly when looking for two categorys (walls and rooms).

Summary

All in all, there are some mechanism that are still fast - but if performance is a concern, you'll definitely want to check out the new Filter approach to getting elements.

I'll try to post the updated sourcecode for this shortly so that you can try it out for yourself.


WARNING:


Your mileage may vary. There seemed to be a great deal of variations in the runs each time they were run.

Revit 2009 API: What's New?

Welcome to another fun episode of discovering what's new in the Revit API. The 2009 edition presents us with a long, long list of enhancements - and while most of people's long-standing complaints have not been addressed - there's certainly something in there that will make you happy individually.

This is the first of a variety of postings I'll write on the API and what's new in 2009. In the other articles, I'll go into further detail... in this one, I'll summarize the highlights - as well as cover some of the features that don't fall neatly into one of the other articles.

Some of the topics we'll cover are:

Beyond those in-depth topics, you can look forward to:

Printer/Paper Settings


The 2008 API introduced printing capabilities, which was great - however, they didn't have time to get the printer settings/paper settings in - so you could only print to whatever the default settings were... making this not so useful in practice.

2009 adds full support for Printers and Paper Sizes - almost every option on the Print Dialog is supported - and special support is offered for virtual printers (like DWF and PDF).

Exporting


While 2008 introduced DWF and DWG export support, 2009 introduces support for export of GBXML (for Green Building Studio, and others) and FBX (for 3DSMax - and others)- both with a good list of options available during export.

IsModified


You can now determine if a given document has been modified since it was last saved (useful if you're writing a Data Management system, or if you just want to know if you need to save before you exit).

External Applications


It is now possible to see, from the application level, all of the registered applications inside of Revit. While it's hard for me to imagine what you can use it for beyond writing an "Add-In Manager" - I'm sure there's something...

Selection StatusPrompt

If you tried adding selection to one of your applications - well, let's just say it wasn't very "smooth" as User Interfaces go. A good step in the right direction is the new Document.Selection.StatusBarTip property, which lets you put text which appears in the status bar (as well as a tooltip on the mouse - just like regular Revit!). This makes it a little easier to tell people what you want them to select (or how they "get out of it" - hint: click on Nothing).

Summary


All in all, there's a lot to wrap your head around - Come back for more details as the months progress...


-Matt

Let the floodgates open...

I have received clearance to start talking about the Revit API in 2009 - my wait is over!

I'll start posting the pieces that I've got queued up now, and there's a few more to finish - there's a lot to talk about.

-Matt

Thursday, February 21, 2008

Argh. I don't understand the rules!

Todd wrote:
"Time to get another post up there buddy. I'm waiting to hear exciting news about customizing Revit 2009. "

This is my favorite time of year. The new product release season is when I have the most interesting stuff to say about what's coming in the next release - and what it means for you.

That said - there is an aspect of this which always drives me bananas - timing. Depending on what you read and who you ask, I am allowed to start talking about the 2009 products somewhere between February 12th and April 2nd - with potential penalties if I talk too early.

February 12th - Autodesk's World Press Day, where they publicize the products.
March 25th - Marketing Launch Day (where resellers and ISVs are supposed to be able to do outbound marketing communication about 2009 - prior to that, you're only supposed to be responding to inbound queries...)

Autodesk Developer Network publishes one set of guidelines - the beta testing agreement says something else entirely about the dates where you can discuss it, and when I ping Product Managers directly on the topic - it all seems different.

It's obvious that the world has changed though - people started blogging about all the new features instantly... Maybe that's OK? Maybe that's just how the world works today in the blog-centric world... But as someone who would prefer not to be shut out of future beta testing - it's frustrating to be told "wait until April 2nd"... At the same time, no one that I talk to seems sure - so it's all still being worked out.

So anyway - I've got a raft of posts all queued up and ready to go - but I'm waiting for the go ahead to be able to post them...

-Matt