Inconsistent elevation marker rotation

I’m revisiting a previous issue about inconsistent rotation of elevation markers. If I create and rotate a single elevation marker it works.

However, when I create a list, the last elevation markers is rotated incorrectly (off by 180 degrees).

Between the two examples, the angle values are the same (210 degrees). I’ve tried adding in transactions after the elevation marker and view creation, but it still has issues. Using negative rotation values doesn’t solve it either.

I suspect the issue might have something to do with transactions or the axis but everything looks fine.

import clr
import math

clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

EleId = UnwrapElement(IN[0])
angle = UnwrapElement(IN[1])
axis = UnwrapElement(IN[2])

TransactionManager.Instance.EnsureInTransaction(doc)
element = []	
for EleId, axis, angle in zip(EleId, axis, angle):
	Autodesk.Revit.DB.ElementTransformUtils.RotateElement(doc, EleId.Id, axis.ToRevitType(), angle)
	element.append(EleId)
	
TransactionManager.Instance.TransactionTaskDone()

OUT = element

Any ideas what is going on?

Rotate elevation marke3r.dyn (61.7 KB)
Rotate elevation marker.rvt (1.5 MB)

One thing to note, if you try to manually rotate that marker from 0 to 210 degrees or even -150 degrees, it does exactly the same thing that it’s doing with dynamo. However, the other two markers will allow you to rotate from 0 to 210 or any other degrees with no issues. So with that being said, I wouldn’t think it’s a dynamo issue. So the million dollar question: what’s the difference between that one marker and the other two?

EDIT: more scramble for your brain…if you copy that third marker, you can rotate the copy to 210 degrees.

Haven’t faced this one yet as my toolkit sticks with the 4 way marker, limitations be damned.

Have you tried iteratively rotating it in increments of 90 degrees + excess over 90? I’m wondering if maybe the API over corrects for +180 degree angles.

So how is this for bizare.

I can manually rotate the elevation markers after they have been created by Dynamo. So therefore, the elevation markers should be identical.

However, if I try to rotate the elevation markers with Dynamo, the results are inconsistent. The top example has the problematic angle (210 degrees) last in the list and it ends up facing the wrong way.

If, however, I reverse the list and create with the problematic angle (210 degrees) first, it works.


So what is going on here?

  • The conversion to radians is the same in both examples so no issue there.
  • Unless the issue is that it is being converted in Dynamo instead of Python and somehow the conversion is different?
  • The python code is working as expected so I don’t think it is the issue.
  • It is being run on the same document with the same family type and document units so that can’t be the problem.
  • The rotation values are all consistent, in an anti-clockwise direction and the rotation axis is always positive Z-axis.
  • Transactions can’t be the issue as the graph is structured the same and works in one but not the other.
  • I’m wondering if there is a bug with the RotateElement Method. There are others who have had similar issues.

It is really baffling. @jacob.small @john_pierson @SeanP @awilliams have you come across this issue? Any suggestions?

Rotate elevation marker4.dyn (69.0 KB)
Rotate elevation marker.rvt (1.5 MB)

1 Like

It is truely bizare. If you enter a rotation value between 201-228 degrees at the END of the list, it fails. 200 degrees and 229 degrees work.

If you have a rotation value between 201-228 degrees at the START of the list, it works!?

I wonder if the the RotateElement Method is somehow making an adjustment to the radians based on the first value of the list? But even so, what is special about this range that would cause it to revert?

1 Like

Yep that’s weird… look forward to hearing from others. Makes me feel like it’s only setting aside enough memory for the first item of an array or something weird/under the hood like that. Wouldn’t surprise me if so. I’ll test the 90 degrees at a time theory shortly as I’m curious, will report back the results either way.

I don’t have the code in front of me, but a while back when I was working on our curtain wall elevation tool there was some definite issues with rotation based on walls and the original wall the elevation is drawn. It had to do with the normal of the wall, if the wall was flipped, and then also if it was between 180-360 (I think but can verify) then I ended up subtracting it from 180 I think vs just using it. It’s really a Revit coordinates thing vs dynamo because my issues were in c#.

I haven’t tested the code, and likely won’t be able to tomorrow, however when faced with something like I like to start by rotating the simplest element possible: a line from (0,0,0) to (0,1,0), and draw a ‘minutes of a clock face’ of sorts radially around the origin so you have a confirmation point at every 5 degrees radially around the origin.

Next generate a line from the internal origin to (0,0,1).

Finally set about rotating the line from it’s current position by 5 degrees. Do this repeatedly (add a useless input to the Python thread and wire a DateTime.Now node into it and set the run mode to periodic) and watch the clock hand spin. If this works correctly, we know the single instance works.

Next add your list setup (the zipped for loop), and make an elevation marker that would be intended to rotate with the line. If at any point the rotation of the view stops being aligned with the line we can confirm where the issue lay, which I believe will help shed some light on what is happening.

One thought that hasn’t been brought up is that the elevation and the marker are both being rotated. The order of operations likely matters as a result, as Revit might be reassigning the elevation to another marker after rotating the marker (ie it goes from marker index 0 to marker index 3 as index 3 is closer to the elevation at that point and your transaction still isn’t set in stone), and then you are further rotating the elevation so it’s pushing the elevation around the marker again… This would mean you’d need to rotate the marker by degrees % 90 instead of degrees, or rotate the elevation first, and the marker second. If this is correct then it likely needs to be added to the documentation for the TransformUtil method, as I am certain other elements have similar ‘intelligence’ baked into them via inheritance and intelligence.

@jacob.small this is effectively what I have done. But as I mentioned, the result differ depending on when the value is in the list. The problematic rotations between 201-228 degrees.

The strange thing is that you can rotate it by 90, 180, 270 no problem. But I agree, that the issue might be tied to the marker index and it is flipping for some reason.

Yep - my advice was to narrow it down by animation of one element that is ‘normal’ and one element that is the odd duck (elevation tags + elevations). Comparing two instances of the complex element side by side is less effective as you can’t as readily identify what varies and when. 201 to 228 is certainly odd values…

I need to do some more test, but I think I’ve solved it…

There is some complication with views being reversed/flipped by large rotational value when using the RotateElement Method. I don’t have an explination as to why the API fails, as it can be done manually within Revit.

The solution is not to use enable index 0 of the elevation marker for all views, but rather to calculate the one which requires the least rotation (positive or negative). This way the rotation angle is at most -90 to +90 degress. In a way this makes sense, but it also unnecessarily complicates the graph.

Rotate elevation marker9.dyn (47.6 KB)

Probably a better outcome so the pointer body is up the page anyway, pretty sure it goes upside down when the markers over 90 degrees either way.

Elevation markers require their views to be created first, then the rotation can be consistently applied second. If you attempt to rotate the marker first, then create the views, Revit takes the liberty of rotating the marker to the closest element it can align to making the first rotation redundant.

3 Likes

A little bit choppy, but here are the primary portions of the code (c#) that I have which works for creating aligned elevations

#the "item" is a curatin walll element
if(Exterior) #This is the Exterior side of the wall
{
	wallNormal = item.WallItem.Orientation.Negate();
	if(item.WallItem.Flipped)
	{
		wallNormal = item.WallItem.Orientation;
	}
}
else
{
	wallNormal = item.WallItem.Orientation;
	if(item.WallItem.Flipped)
	{
		wallNormal = item.WallItem.Orientation.Negate();
	}
}
LocationCurve wLocation = item.WallItem.Location as LocationCurve;
if(wLocation.Curve is Line sLine)
{
	wTransform = sLine.ComputeDerivatives(0.5, true);
	wCenter = wTransform.Origin;
	eCenter = wCenter.Add(wallNormal.Multiply(5));
	wLine = sLine;
}
else
{
	continue;
}
XYZ axis = new XYZ(eCenter.X, eCenter.Y, eCenter.Z + 10);
double rotation = wallNormal.AngleTo(XYZ.BasisX);

ElevationMarker elevMarker = ElevationMarker.CreateElevationMarker(Doc, SelectedViewFamilyTypeId.Id, eCenter, 96);
ViewSection elevView = elevMarker.CreateElevation(Doc, Doc.ActiveView.Id, 0);

#This is what I found worked to check to see where the elevation is in relation to the wall and then multiplied the rotation as shown.
if(eCenter.Y < wCenter.Y)
{
	ElementTransformUtils.RotateElement(Doc, elevMarker.Id, Line.CreateBound(eCenter, axis), rotation * -1);
}
else
{
	ElementTransformUtils.RotateElement(Doc, elevMarker.Id, Line.CreateBound(eCenter, axis), rotation);
}