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...........

2 comments:

Mel Binks said...

Hi,

I have a question which sort of relates to your post...I'm using software that links information to certain parameters in Revit families, but needs the built in parameter definition such as "ALL_MODEL_TYPE_MARK". Do you know any way to compile a list of these codes?

Thanks,
Melanie

Matt Mason said...

Mel,
Yes - if you have access to the Revit SDK, all 3000 parameters are all inside the BuiltInParameter enumerated type.

Does that answer your question?

Best Regards,
Matt