Locked Dimensioning

Here is a little exploration I embarked upon prompted by a

question

from

Pierre-Nelson Navarra
.
It starts off as a rather esoteric search for connections between objects that have no API-accessible data, but ends up with a surprising twist, the ability to unlock all dimensions through the API.

Question:
Is there a way to determine if a dimension element is locked or not, and is it possible to unlock it through the API?

Answer:
To make a short answer long, here is a description of the exploration this prompted me to undertake.

I had a quick look at a dimension element.
I made heavy use of

RvtMgdDbg
,
the most important tool for examining the Revit database, its elements, their properties and parameters, and the relationships between elements.
Another important tool that I use a lot is the

Revit API introduction labs

built-in parameter checker.
One thing I noted when examining the dimension element using the latter is the built-in parameter ELEMENT_LOCKED_PARAM, which is a read-write Boolean value and initially set to false.
Unfortunately, when I lock the dimension, it still remains false, so this does not give us the information we are looking for.
The ‘Revit 2009 API Developer Guide’ has nothing to say about this parameter either.

I then examined in detail what elements are added to the database by inserting a dimensioning element and locking it. Adding a dimension introduces one new element into the database:


diff RevitElementsBeforeDimension.txt RevitElementsAfterDimension.txt
2259a2260
> Id=130751; Class=Dimension; Category=Dimensions; Name=Linear - 3mm Arial

I use the Revit API intro Lab2_1_Elements to examine what elements are added, as described in

exploring element parameters
.

Locking the dimension adds another element:


diff RevitElementsAfterDimension.txt RevitElements.txt
2260a2261
> Id=130770; Class=Dimension; Category=Constraints; Name=Linear Dimension Style

So the locking information is stored in a separate element.
I thought it might be might be possible to find the connection between these two elements and use that to determine the locked status of the dimension element.
I also hoped that an analysis of the underlying geometry of the two elements would discover that one of them is a lock constraint for the other.

If I remove the lock again, the constraint element id remains in the file but is invalid.
Putting the lock back in again removes the invalid constraint element and adds a new one with a new element id:


diff RevitElementsAfterDimension.txt RevitElements.txt
2260a2261
> Id=130813; Class=Dimension; Category=Constraints; Name=Linear Dimension Style

The constraint element has almost no accessible data, but it does have a valid class, category and name.
It has a Location property, but we cannot access its internal data either.
As a Dimension instance, it also has a Curve property and a ReferenceArray.
I tried to use these to determine that this constraint matches the existing dimension and is locking it.

Here is the code for the Execute method of an external command that I used to explore this in a model with exactly one locked dimension in it, so that the dimension element ‘d’ and the constraint ‘c’ are both well defined:


Application app = commandData.Application;
CreationFilter cf = app.Create.Filter;
Document doc = app.ActiveDocument;
 
Filter f1 = cf.NewCategoryFilter(
  BuiltInCategory.OST_Dimensions );
 
Filter f2 = cf.NewTypeFilter(
  typeof( Dimension ) );
 
Filter f = cf.NewLogicAndFilter( f1, f2 );
 
ElementIterator iter = doc.get_Elements( f );
 
Dimension d = null;
 
while( iter.MoveNext() )
{
  d = iter.Current as Dimension;
 
  Debug.Assert( null != d,
    "expected to find a dimension element" );
 
  break;
}
 
f1 = cf.NewCategoryFilter(
  BuiltInCategory.OST_Constraints );
 
f = cf.NewLogicAndFilter( f1, f2 );
 
iter = doc.get_Elements( f );
 
Dimension c = null;
 
while( iter.MoveNext() )
{
  c = iter.Current as Dimension;
 
  Debug.Assert( null != c,
    "expected to find a constraint element" );
 
  break;
}
 
// both locations have no valid information:
Location locc = c.Location;
Location locd = d.Location;
 
// both lines have no valid information:
Line linc = c.Curve as Line;
Line lind = d.Curve as Line;
 
// this throws an exception:
//XYZ pc = linc.get_EndPoint( 0 ); 
//XYZ qc = linc.get_EndPoint( 1 );
//XYZ pd = lind.get_EndPoint( 0 );
//XYZ qd = lind.get_EndPoint( 1 );
 
// this cast returns null:
LocationCurve locc2 = c.Location as LocationCurve;
LocationCurve locd2 = d.Location as LocationCurve;
 
ReferenceArray rc = c.References;
ReferenceArray rd = d.References;
 
if( rc.Size == rd.Size )
{
  ReferenceArrayIterator ic = rc.ForwardIterator();
  ReferenceArrayIterator id = rd.ForwardIterator();
  while( ic.MoveNext() && id.MoveNext() )
  {
    Reference r1 = ic.Current as Reference;
    Reference r2 = id.Current as Reference;
    if( r1.Equals( r2 ) )
    {
      // this never happens:
      Debug.Print( "Equal" );
    }
  }
}
return CmdResult.Failed;

Unfortunately, none of the attempts to read some valid geometrical information return anything useful.
I also explored the parameters of both elements, and found no link there either.
The constraint has no official parameters at all, and the hidden ones provide no clue.

They both have a reference array with two elements each.
The elements in the reference arrays do not compare equal, and trying to explore their innards leads us to an undocumented Pick object which we cannot explore further.

Even if this exploration in Revit 2009 did not lead us anywhere useful, we still discovered some interesting background information on dimensioning and locking in Revit.

And here come two pieces of good news at the end:

First, in the Revit 2010 API, you can simply use the new properties Dimension.IsLocked and DimensionSegment.IsLocked.

How to Unlock all Dimensions

Later, Pierre followed up with a useful new result and an additional question:

I’ve got the code now to get all constraints.
When I delete them, the effect is that the dimensions are unlocked.
That’s good.

I’d like to store the original constraints before deleting them in order to relock the dimensions afterwards;
do you think that is possible?

I am glad that we at least discovered a possibility to unlock the locked dimensions.
Unfortunately, I cannot think of any way to store the constraints prior to deleting them, since we have no access to their internal data.
Maybe they could be copied into a different database beforehand?
But then it might be necessary to copy additional objects as well to preserve the associativity, and I cannot see a way to achieve this.
Or just move them away somewhere where they do no harm instead of deleting them to unlock, and then move them back again to the original position to lock again?


Comments

16 responses to “Locked Dimensioning”

  1. Thx again for this exellent post Jeremy.
    Copy or move objects before deleting is a good idea. We can also make a copy of the file before deleting all dimensions…
    Maybe you have seen that I’ve got a new problem with splitted faces area in Object….maybe a new post….
    Cheers.

  2. Hi Pierre,
    Thank you for your appreciation and feedback!
    Yes, I saw your email on the split faces. For completeness sake, I note here that you are asking about API access to the geometry and above all the area of split faces. Unfortunately, this is a topic that I have already had several questions about and explored in some depth but not been able to make any significant progress on yet. I explored what elements are added, similarly to the process descibed above. Briefly, adding a face split creates the following types of new elements: a sketch plane, a sketch, a split face element, model lines, and automatic sketch dimensions. I tried to find the relationship between these elements but was unable to determine or retrieve the links between them. I also asked the development team about this issue, and received the following answers:
    1. Is there a way to access information about materials painted on split faces using the existing API? No.
    2. If this information is not available through the API, could we use a schedule and export them manually, or an ODBC export, also exported manually, to access that information? No, because split face elements do not schedule and do not export to ODBC.
    So it seems as if this information really is hard to access.
    On the other hand, I can see in the image that you pointed me to that the area information of a split face is in fact accessible in a schedule table, so it can be calculated, displayed and viewed in the Revit user interface. Therefore, it should be possible to access and extract this information by creating the schedule and exporting it to Excel, shouldn’t it? And that process should be automatable using a tool like AutoHotKey, shouldn’t it?
    If anybody can find a way to access this information, I will be happy to post on that. I will also gladly present more detailed information on the elements created by adding a face split.
    Cheers, Jeremy.

  3. Hi Jeremy,
    I was reading the seconde answer by development team and I was really surprised to read that the development ignore that we can make a schedule wich got spitted faces are!…can believe!…
    Anyway, the solution might be that we have to schedule manually and export it in a text file. That’s a possibility and that’s no too bad. I’m gonna do it….
    Cheers!

  4. Hi Pierre,
    I can imagine that in that answer, they were thinking more about possibilities to access the detailed geometry, for instance the exact location of the model lines defining a split face, so I can understand their way of seeing it.
    I am very much looking forward to hearing about your experience making use of the schedule export to access this information!
    Good luck and best regards, Jeremy.

  5. Hi Jeremy,
    I got the Schedule in wich I have my areas grouped by materials. How to get all lines and fields?
    Have you already made this?

  6. Hi Pierre,
    No, I have never tried to automate schedule data exporting. Is it possible to manually export schedule data in spreadsheet format? In that case, it is hopefully possible to automate that process as well, c.f.
    http://thebuildingcoder.typepad.com/blog/2009/01/autohotkey.html
    Cheers, Jeremy.

  7. Hi Jeremy,
    I know that we can use AutoHotkey but, I’d like to write my schedule export in a specific format…mhh…
    I can use AutoHotKey to export schedule in txt and running my API script after but, that’s not very clean….
    Mhh, still surching…
    Cheers.

  8. Hi Pierre,
    The first challenge is to obtain access to the data at all, in any way whatsoever. Making use of tools like the Win32 API or AutoHotKey also introduces synchronisation issues and questions on how to coordinate the application with the simulated interaction through the Revit user interface and its results. Once the data is accessible, in whatever format that may be, converting to another format is no big issue.
    Cheers, Jeremy.

  9. debdas_paul@yahoo.com Avatar
    debdas_paul@yahoo.com

    Hi Jeremy,
    I am trying to make a family of pipe fitting with parameter with the help of “family Types” tab which is already load in the Revit MEP 2009.
    But I can not make sence the meaning of “Lookup Table name” in the Family types tab.
    Can you please help me with the proper making of family fitting with parameter.
    Thanks,
    Debdas

  10. Dear Debdas,
    Maybe you will find the families guide useful:
    http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=13376394
    Cheers, Jeremy.

  11. Saravanan Avatar
    Saravanan

    Hi Jeremy:
    I wonder whether it is possible to add a “prefix/suffix” ,”above/below text” to a dimension. Is it possible?
    Thanks,
    -Saravanan

  12. Dear Saravanan,
    As in many other Revit programming queries, the first question to ask before looking at the API possibilities is whether this is possible in the user interface. If not, then you can probably not do anything through the API either.
    Cheers, Jeremy.

  13. Saravanan Avatar
    Saravanan

    Hi Jeremy:
    Yes, it is possible by clicking the dimension text. A text box will appear and we can provide prefix ,suffix, above text & below text.
    But so far I am not able to figure out any ways in API.
    Please help me.
    Thanks in advance,
    -Saravanan

  14. Dear Saravanan,
    I just saw from a related developer support case that there is apparently no API access to these fields right now. Sorry for the bad news.
    Cheers, Jeremy.

  15. Dear sir,
    How can i lock pipes and connectors together through API in order to join pipes.
    Thanks & Regards,
    – Nitin

  16. Dear Nitin,
    Sorry, no idea. Looking forward to hearing from you if you find out anything useful.
    Cheers, Jeremy.

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading