The below Python script first get’s the AssemblyOrigin of an AssemblyInstance. GetTransform
Next step is the rotation of this AssemblyOrigin. CreateRotationAtPoint
This is the part that doesn’t work properly. The AssemblyOrigin is rotated, but it seems to take a random basepoint for this rotation. It is my goal that it rotates around its own (z)axis.
I understand what the code does, but i’m not a programmer so i don’t know how to edit the (or add) code.
I hope someone is willing to help me out.
import clr
import math
clr.AddReference("ProtoGeometry")
from Autodesk.DesignScript.Geometry import *
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
app = DocumentManager.Instance.CurrentUIApplication.Application
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
def tolist(obj1):
if hasattr(obj1,"__iter__"): return obj1
else: return [obj1]
elems = tolist(UnwrapElement(IN[0]))
axis = tolist(IN[1])
rot = tolist(IN[2])
outList = []
for e, a, r in zip(elems, axis, rot):
trans = e.GetTransform()
transRot = trans.CreateRotationAtPoint(a.ToXyz(),math.radians(r), trans.Origin)
try:
TransactionManager.Instance.EnsureInTransaction(doc)
e.SetTransform(transRot)
TransactionManager.Instance.TransactionTaskDone()
outList.append(e)
except Exception, e:
outList.append(e.message)
OUT = outList
This is just a guess but using the Vector.ZAxis is essentially a vector(0,0,1) and which works in Dynamo but when used in Revit, you convert it to a point (0,0,1) and you would be rotating using this as the center point, right? So you are rotating the element around basically the origin of the project. Instead, you want the center point of element. I’m not good enough at API to know how to get that but I think that would be where you start?
I made an attempt to create an axis(line) at the Origin of the Assembly.
I added two lines of code (bp and axis).
In the next line of code i replaced “a.ToXyz()” by “axis”.
for e, a, r in zip(elems, axis, rot):
trans = e.GetTransform()
bp = trans.Origin
axis = Line.CreateBound(bp, XYZ(bp.X, bp.Y, bp.Z+1.0))
transRot = trans.CreateRotationAtPoint(axis, math.radians(r), bp)
try:
I did another attempt to modify the above Python code.
It works now the way i would like it to, but only for one element.
If i feed it with a list of elements only the last one is modified
Can anyone tell me why the code doesn’t work for multiple elements ?
import clr
import math
clr.AddReference("ProtoGeometry")
from Autodesk.DesignScript.Geometry import *
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
app = DocumentManager.Instance.CurrentUIApplication.Application
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
def tolist(obj1):
if hasattr(obj1,"__iter__"): return obj1
else: return [obj1]
run = tolist(IN[0])[0]
elems = tolist(UnwrapElement(IN[1]))
Xvector = tolist(IN[2])
Yvector = tolist(IN[3])
Zvector = tolist(IN[4])
outList = []
if run:
for e, xv, yv, zv in zip(elems, Xvector, Yvector, Zvector):
trans = e.GetTransform()
trans.BasisX = xv.ToXyz()
trans.BasisY = yv.ToXyz()
trans.BasisZ = zv.ToXyz()
try:
TransactionManager.Instance.EnsureInTransaction(doc)
e.SetTransform(trans)
TransactionManager.Instance.TransactionTaskDone()
outList.append(e)
except Exception, e:
outList.append(e.message)
OUT = outList
else:
OUT = "Please set Run to True"
Coming in late to the conversation but you can see awilliams code here. It works with just one element (my scripting is not quite there to get it to a list). It seams to be the same problem you are having but figured I wouls share since they are similar.
Hard to tell what is wrong here without access to the Revit project or script. I am assuming you have the same number for all of the python inputs (8 of each input, except IN[0]). I don’t know if the unwrapping makes a difference as I always unwrap each element individually, not as a list. Try this script if it makes any difference:
import clr
import math
clr.AddReference("ProtoGeometry")
from Autodesk.DesignScript.Geometry import *
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
app = DocumentManager.Instance.CurrentUIApplication.Application
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
def tolist(obj1):
if hasattr(obj1,"__iter__"): return obj1
else: return [obj1]
run = tolist(IN[0])[0]
elem = []
for i in IN[1]:
elem.append(UnwrapElement[i])
elems = tolist(elem)
Xvector = tolist(IN[2])
Yvector = tolist(IN[3])
Zvector = tolist(IN[4])
outList = []
if run:
for e, xv, yv, zv in zip(elems, Xvector, Yvector, Zvector):
trans = e.GetTransform()
trans.BasisX = xv.ToXyz()
trans.BasisY = yv.ToXyz()
trans.BasisZ = zv.ToXyz()
try:
TransactionManager.Instance.EnsureInTransaction(doc)
e.SetTransform(trans)
TransactionManager.Instance.TransactionTaskDone()
outList.append(e)
except Exception, e:
outList.append(e.message)
OUT = outList
else:
OUT = "Please set Run to True"
In your file, what should I be expecting when I run the script? There are no errors but it doesn’t seem like there is any change within the Revit project.
It seems like you set their transform to itself, effectively doing nothing. Unless I am missing something here.
When I tried your script, it didn’t change any of their positions, not even the last one. Is it possible that the node LocalCoordinateSystem gets the vectors based off of the transform of the object? If it does, then it would explain what was happening to me, where the script was successful but didn’t change anything. Try supplying it with the bounding box center’s vectors, or using different vectors to see if they all move or not.
You could even shuffle the vectors you get from the LocalCoordinateSystem node and see if each assembly’s transform moves to another to confirm my suspicions.
I used a “List.GetItemAtIndex” node and run the script on one element at a time.
All 8 elements gave the disired result, so there is no problem with the input of the vectors.
The only thing i can think of is that the Python (for loop), doesn’t handle the lists correctly.
Python is saying that the element’s transform was changed to the vectors that were inputted. For reference, a list in the watch node consists of this structure:
0 - Element
1 - List of original transform BasisX, Y, and Z
2 - Vectors inputted from BIM4Struc package
3 - List of transform Basis X, Y, and Z after the python script
Honestly I am as stumped as you are. You are right that it works one at a time and I have had the problem before where if I edit many revit elements within a single dynamo script, only the last one will show the changes until I update the model, which might be what is happening here but even when checking and moving the object, it doesn’t update.
Hopefully someone with more knowledge can shed some light. Try asking @Kulkul or @Dimitar_Venkov about this.
Thank you very much for your time and effort to help me
You definitely pointed me in the right direction, and i think i found a solution…
I used “ForceCloseTransaction” in stead of “TransactionTaskDone”.
I looks like the script needs a hard break after each run.
I have to do some cleanup first, but i will post my solution for anyone who is interested.
Assemblies_ModifyOrigin_v04.dyn (5.7 KB)
I wrapped the Python script and “Element.LocalCoordinateSystem node” inside a custom node (local package). Assemblies.ModifyOrigin.dyf (26.0 KB)
The script reads out the orientation of the (assembly) source elements, and uses that to rotate the origin of the assemblies. If you create assembly views (after running the script) these views are aligned with the element, regardless of the rotation of the element in the project. Without running the script assembly views are always aligned with the X, and Y-axis.
I’ve been reading through your posts, I am facing a similar task. Inside your custom node, do you know what package “element.HandOrientation” belongs to?