TextNote Rotation

Although the Document and FamilyItemFactory classes provide a NewTextNote method which allows us to freely specify the rotation angle when creating new text note instances, there is currently no access to read the rotation of an existing TextNote element in the Revit API.
Exploring this issue in a little bit more depth discovered a possibility for a workaround, though, which I think worth while presenting.
It also prompted me to update The Building Coder sample command

CmdBoundingBox
,
which displays the values of a selected building element bounding box.
Here is the question that prompted this update:

Question: I would like to transfer all text elements from a backup version of a project to a newer updated version.
It seems the using the clipboard to copy and paste aligned works nicely view by view, but there is no way to access this UI functions from the API. Since there are over a thousand views to process, doing it manually is not an option for us.
I am able to extract all the views and text notes in it programmatically, but I do not see how to obtain the rotational value of an existing text note. Is there any accessible property providing this data?

Answer: Unfortunately not, although we have registered a wish list item for this functionality. Here is a suggestion for a workaround, though:

From the TextNote element, you can access the following graphical properties:

  • BoundingBox
  • Coord
  • Width

I created a sample model with the following text note:

Rotated text note

Extracting those three properties and creating a couple of simple geometric drawing primitives to represent them, I obtain the following:

Text note graphical properties

In this drawing,

  • BoundingBox is displayed as a box.
  • Coord is displayed as a circle.
  • Width is represented by the length of the line.

From this you can see that you can calculate an approximate rotation angle plus minus π from these three values, by determining the angle required to rotate the line around the Coord position to fit it inside the bounding box.

CmdBoundingBox Update

In preparing the images above, I noticed that my original implementation of The Building Coder sample command

CmdBoundingBox
examining
the bounding box of a Revit element was rather limited in functionality.

Querying the bounding box of a text note without specifying a view returns null.
In that case, the command would throw an exception.
Although it included a debugging assertion to check that a non-null value was returned, there was no runtime check to react to the null value and avoid dereferencing it.

Also, in this case, the null value returned when no view is specified should cause the command to try again with a valid view, which will return a valid bounding box in the case of a text note.

I therefore updated command in the following ways:

  • If a null value is returned for the bounding box without a view specified, try again using the current view.
  • If a null value is still returned, print an error message in both release and debug mode.
  • List the results in a message box, not just in the Visual Studio debug output console.
  • Since the command makes no modifications to the database, change the transaction mode to read-only.

Here is the updated source code for the bounding box command:


[Transaction( TransactionMode.ReadOnly )]
[Regeneration( RegenerationOption.Manual )]
class CmdBoundingBox : IExternalCommand
{
  public Result Execute(
    ExternalCommandData commandData,
    ref string message,
    ElementSet elements )
  {
    UIApplication app = commandData.Application;
    UIDocument uidoc = app.ActiveUIDocument;
    Document doc = uidoc.Document;
 
    Element e = Util.SelectSingleElement(
      uidoc, "an element" );
 
    if( null == e )
    {
      message = "No element selected";
      return Result.Failed;
    }
 
    View v = null;
 
    BoundingBoxXYZ b = e.get_BoundingBox( v );
 
    if( null == b )
    {
      v = commandData.View;
      b = e.get_BoundingBox( v );
    }
 
    if( null == b )
    {
      Util.InfoMsg(
        Util.ElementDescription( e )
        + " has no bounding box." );
    }
    else
    {
      Debug.Assert( b.Transform.IsIdentity,
        "expected identity bounding box transform" );
 
      string in_view = ( null == v )
        ? "model space"
        : "view " + v.Name;
 
      Util.InfoMsg( string.Format(
        "Element bounding box of {0} in "
        + "{1} extends from {2} to {3}.",
        Util.ElementDescription( e ),
        in_view,
        Util.PointString( b.Min ),
        Util.PointString( b.Max ) ) );
    }
    return Result.Succeeded;
  }
}

It now displays the following message when running it and selecting the text note shown above:

Text note bounding box coordinates

Here is

version 2011.0.72.2
of The Building Coder samples including the complete source code and Visual Studio solution and the updated version of the command.


Comments

4 responses to “TextNote Rotation”

  1. Hi Jeremy,
    The problem I’m having lead me to this page, it is not with your code however I believe you may be able to help. I have rotated some text objects with the API and the TextNote bounding box appears as a parallelogram and not a rectangle until i attempt to rotate it. Do you have any idea what I could be doing wrong?
    I love the blog and I attended a class of yours at AU2010! Thanks in advance,

  2. Hi Jeremy,
    I took a break from the code and it turns out all the frustrations i was having were caused by an incorrect normal vector. Instead of (0,0,1) i was using (1,1,0) yuck…
    Thanks again for such an informative site!

  3. Dear Mike,
    Thank you very much for your appreciation!
    Yes, a break is a very good idea when you run into a mysterious problem. Many times a problem will solve itself as soon as you leave your PC and cubicle, won’t it? Congratulations on that.
    I must admit I was mystified by your query as well, because I didn’t understand how the bounding box can ever be distorted into a parallelogram. I would have thought that by its very definition, it remains an orthogonal box under all circumstances.
    Normal vectors that are not normal are really nasty, aren’t they? :-)
    Cheers, Jeremy.

  4. Steven Avatar
    Steven

    Just in case anyone comes across this post, there is a better method now. As of at least Revit 2015, the API for TextElement has properties BaseDirection and UpDirection that can be used to determine the rotation of text.

Leave a Reply

Discover more from Autodesk Developer Blog

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

Continue reading