Rotating a Plan View

Here is a query from the Autodesk Revit API discussion forum dealing with the

rotation of a plan view
:

Question: I am trying to create rotated duplicates of existing views using the Revit 2013 API.

I managed to create the view, both as dependent and not.
After this I activate the view crop box and make it visible.

I then create a rotation transformation.
When I debug it, I can see that the transformation and rotation of the bounding box is ok.

I try to set the rotated bounding box as the crop box.
However, this does not work, and all I get is the standard identity matrix.

I have a right handed rotation, and use basis Z as the rotation axis.
I have a reference to a transaction inside the method, but have also tried to encapsulate the specific part into a sub transaction.

This way of doing things is according to the Revit 2013 API documentation.
It states that the bounding box can be rotated, then used as section box/crop box, and provides to following example code for this:


private void RotateBoundingBox( View3D view3d )
{
  BoundingBoxXYZ box = view3d.SectionBox;
 
  if( !box.Enabled )
  {
    TaskDialog.Show( "Revit",
      "The View3D section box is not enabled." );
    return;
  }
 
  // Create a rotation transform
 
  Transform rotate = Transform.get_Rotation(
    XYZ.Zero, XYZ.BasisZ, 2 );
 
  // Transform the SectionBox 
  // with the rotation transfrom
 
  box.Transform = box.Transform.Multiply( rotate );
  view3d.SectionBox = box;
}

I tried to use it like this:


  ViewPlan rotatedView = doc.GetElement(
    viewToDuplicate.Duplicate(
      ViewDuplicateOption.AsDependent ) )
        as ViewPlan;
 
  rotatedView.CropBoxActive = true;
  rotatedView.CropBoxVisible = true;
 
  BoundingBoxXYZ box = rotatedView.CropBox;
 
  XYZ originOfRotation = 0.5 * (box.Max - box.Min);
  XYZ axizOfRotation = XYZ.BasisZ;
 
  Transform rotate = Transform.get_Rotation(
    originOfRotation, axizOfRotation, Math.PI );
 
  box.Transform = box.Transform.Multiply( rotate );
 
  rotatedView.CropBox = box;

I also tried using the ElementTransformUtils.RotateElement method.

Both approaches yield no result.

Manually I make sure the plan is situated to ‘Project north’, show the crop box, select it, rotate it and the view is rotated accordingly.

<!–
http://wikihelp.autodesk.com/Revit/enu/2012/Help/Revit_User’s_Guide/1394-Document1394/1549-Use_and_1549/1594-Rotating1594/1597-Rotating1597

Do you have any suggestions to what to do?

–>

The desired result is a dependent view rotated at the point of creation.
I need to create several views at once, e.g. 4-8 differently rotated ones of the same plan, to create evacuation plans.

<!–

I created a sample model and code that can be downloaded from here:

https://dl.dropboxusercontent.com/u/21688890/RotateViewPlanSample.rar

This contains sample visual studio code, Revit project and a Word file with explanations.

/a/j/adn/case/sfdc/08259677/attach/Rotating_of_view_plan.docx
In the sample file, I have created the evacuation plans for three rooms.
I am hoping to do some further development on these to do the steps described over. (some of them).

The sample is 2014, and I am using the 2014 API.

In the Revit sample file. Try to duplicate the firstfloor. I have created the solution I want as ‘Evacuation plan – first floor’ This shows what I am looking to get.

In my current sample code I create the transformation and try to apply it to the duplicated view.
I then rotate the symbols placed in the view according to the specified angle.

It is only the rotation of the view that is tricky.

–>

Let me reiterate my requirement and manual solution:

Issue – Rotating view plans

For creating evacuation plans for a floor, I need to create rotated dependent views so that the person looking at the plan on the inside of a door sees the situation the same way as the corridor outside.

I can achieve it manually like this:

  • Create the floor, i.e. when modelling the building.
  • Apply all the required fire symbols.
  • Create three duplicates as dependent views.
  • Apply the crop region to each.
  • Rotate each plan individually by rotating the crop box.
  • Create filled regions to show which room the current plan applies to.
  • Hide the ‘you are here’ symbols in all other rooms.
  • Optionally rotate the symbols as well.
  • Place these views on corresponding sheets.

This is obviously a very time consuming operation.

I have already implemented methods to create the fire and evacuation plans.

The issue I am now dealing with is the rotation of the crop region.

I do get the transformation, but I am not able to apply it to the crop region.
Something fails and the transformation remains unchanged.

How can I fix this, please?

Answer: Yes,

rotating a view
in
the user interface is perfectly straightforward, just as you say:

<!–

First, a couple of comments on your sample add-in code:

You have an interesting mix of Revit API assembly references in your MinimumRevitAddin.csproj sample project. It includes two HintPath tags, and they refer to a mix of Revit API assemblies:

  • C:Program FilesAutodeskRevit 2014RevitAPI.dll
  • C:Program FilesAutodeskRevit 2013ProgramRevitAPIUI.dll

I updated these to both refer to the Revit 2014 assemblies.

Also the reference to RevitAPI.dll had its copy local flag set to true. You should avoid that, as you probably know:

http://thebuildingcoder.typepad.com/blog/2011/08/set-copy-local-to-false.html

The RegenerationOption is completely superfluous, everywhere.

The TransactionMode makes no sense on an external application.

The Autodesk.Revit namespace is empty, since all it contains are other namespaces, so it never ever makes sense to include it in a using statement.

I cleaned it up and started debugging your add-in.

The updated code is attached to this message in RotateViewPlanSampleJt.zip.

–>

In the API, the issue is also clear: The element to rotate is not the view, but rather the crop box element associated to it.

If it is visible, it can be found using a filtered element collector taking document and view element id arguments.

Here is a macro that works based on your sample code:


  public void CreateDuplicatedRotatedCroppedView(
    Document doc )
  {
    View activeView = doc.ActiveView;
    View duplicated = null;
 
    using( Transaction t = new Transaction( doc ) )
    {
      t.Start( "Duplicate View" );
 
      duplicated = doc.GetElement(
        activeView.Duplicate(
          ViewDuplicateOption.WithDetailing ) )
            as View;
 
      t.Commit();
    }
 
    Element cropBoxElement = null;
 
    using( TransactionGroup tGroup
      = new TransactionGroup( doc ) )
    {
      tGroup.Start( "Temp to find crop box element" );
 
      using( Transaction t2 = new Transaction(
        doc, "Temp to find crop box element" ) )
      {
        // Deactivate crop box
 
        t2.Start();
        duplicated.CropBoxVisible = false;
        t2.Commit();
 
        // Get all visible elements;
        // this excludes hidden crop box
 
        FilteredElementCollector collector
          = new FilteredElementCollector(
            doc, duplicated.Id );
 
        ICollection<ElementId> shownElems
          = collector.ToElementIds();
 
        // Activate crop box
 
        t2.Start();
        duplicated.CropBoxVisible = true;
        t2.Commit();
 
        // Get all visible elements excluding
        // everything except the crop box
 
        collector = new FilteredElementCollector(
          doc, duplicated.Id );
        collector.Excluding( shownElems );
        cropBoxElement = collector.FirstElement();
      }
      tGroup.RollBack();
    }
 
    using( Transaction t3 = new Transaction( doc ) )
    {
      BoundingBoxXYZ bbox = duplicated.CropBox;
 
      XYZ center = 0.5 * ( bbox.Max + bbox.Min );
 
      Line axis = Line.CreateBound(
        center, center + XYZ.BasisZ );
 
      t3.Start( "Rotate crop box element" );
 
      ElementTransformUtils.RotateElement( doc,
        cropBoxElement.Id, axis, Math.PI / 6.0 );
 
      t3.Commit();
    }
  }

There are several noteworthy points in here.

All the transactions could be assimilated into one group, if desired.

The crop box element is retrieved using a clever trick: first hide it, retrieve the set V of all visible elements, unhide it and again retrieve all visible elements, this time excluding the set V.
Clever, huh?


Comments

3 responses to “Rotating a Plan View”

  1. RevitArkitek Avatar
    RevitArkitek

    Jeremy,
    I tried out this macro, thank you. The view gets duplicated and rotates, but the actual crop box does not “rotate”. For example if the view crop is rectangular in a landscape position, the macro should rotate this to be in a portrait position. Is there a way to accomplish this? I’ve tried looking into the Transform utilities to get the new coordinates of a rotated rectangle but I’m not quite understanding it. Thanks.

  2. peter kompolschek Avatar
    peter kompolschek

    Jeremy, thank you for this interesting discussion.
    as comming from the dynamo side of life things are not very easy, especially limited coding skills and worst of all having to translate to python!
    but after little thinking most of your examples are running inside dynamo.
    as right now i am haunted by rotated room plans i tried to transpose your example.
    actually i am failing to get a cropBoxElement.Id
    what am i missing?
    – in python shells at the moment transactiongroups are not supported (obviously) as the internal TransactionManager keeps control.
    tx peter

  3. Dear Peter,
    Thank you for your appreciation. Glad you like it!
    Have you had a look at the possibilities to generate IronPython code from Reflector or JustDecompile?
    http://stackoverflow.com/questions/19632265/emitting-ironpython-code-in-c-sharp
    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