Hello everyone,
Always when i find myself stuck for many days, i come here and i find the solution, thanks to you in advance for helping.
Actually i am creating a Revit dynamo Script to create 3D camera views for each CCTV security camera in the model.
The camera object/family has some parameters like pan/tilt/zoom and i succeeded to extract these values in dynamo for each object and create a 3D perspective camera view and rotate these views left/right and up/down depending on the parameter value for each camera family in my model.
The problem i am facing that i have some families where the camera object is rotating around its own axis, (not only left/right & up/down) as per the below 1st photo, so i need to rotate the 3D Camera perspective view after it is created, around its own axis (align it with the camera object view rotation), i am able to do it manually in Revit so i am sure there is a way in dynamo but i am struggling to find it.
What i have done manually, that i open the 3D camera view and i set the current working plan to the family object reference plane (as per 2nd photo below), then i rotate the view and it is rotated easily.
the idea that i need a dynamo node to rotate the 3D camera perspective view around a certain reference plane, where i already detect this plane in dynamo for each family (in the project environment) with the node âFamilyInstance Referencesâ, but still searching to rotate the view with a certain angle with reference to certain plane.
Thanks for any help you can give to me.
I found something but it is not working
i can create a line by start end point, the start point is the 3D camera view eye (x,y,z) and the end point is the 3D camera view target (x,y,z) which is the considered the axis of rotation, and use the ViewPlan.Rotate node from ryhthm package but it is giving me errors that it is not working as per the below photo, any ideas?
The rhythm node requires a viewPlan - so a perspective view will not work
I think one way to handle this to use API ViewOrientation3D
class and python
Adding roll to a view is not a trivial task
This will take a view and change the âcameraâ view
import sys, clr
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
perspective = UnwrapElement(IN[0])
EyePosition = IN[1].ToXyz()
UpDirection = IN[2]
ForwardDirection = IN[3]
TransactionManager.Instance.EnsureInTransaction(doc)
NewVO = ViewOrientation3D(EyePosition, UpDirection, ForwardDirection)
perspective.SetOrientation(NewVO)
uidoc.RefreshActiveView() # Comment out if not using active view
TransactionManager.Instance.TransactionTaskDone()
OUT = perspective
You already have the camera position (Dynamo Point â Revit XYZ
class)
Now the issue is how to get the up and forward vectors - your line is the forward vector so create this with Vector.ByTwoPoints (might need to be normalised) and then the up could be obtained by getting the BasisZ of the forward vector and then doing a transform rotate on the X Axis (I think).
Alternately if you know the roll and calcuate the pan and tilt from your vector you could create up and froward with the following
import math
import clr
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import XYZ, Transform
pan = math.radians(IN[0]) # Pan
tilt = math.radians(IN[1]) # Tilt
roll = math.radians(IN[2]) # Roll
X = XYZ(1, 0, 0) # Roll
Y = XYZ(0, 1, 0) # Tilt
Z = XYZ(0, 0, 1) # Pan
transform_roll = Transform.CreateRotation(X, roll)
transform_tilt = Transform.CreateRotation(Y, tilt)
transform_pan = Transform.CreateRotation(Z, pan)
up = transform_pan.OfVector(transform_tilt.OfVector(transform_roll.OfVector(Z)))
forward = transform_pan.OfVector(transform_tilt.OfVector(transform_roll.OfVector(X)))
OUT = up, forward
Not sure if this is the correct way to do a transform of 3 axes
Hope this helps
Thank you Mike for your reply.
i tried your python script, as per shown in below photo, i understand that the 1st input will be the 3D camera perspective view, 2nd input will be the vector created from the eye position point, 3rd input i do not know how to get it, i cannot find something to give me the basisZ of the forward vector, 4th as you said vector by 2 points of my line (starting point = eye, ending point= target).
in addition, i have an error in the python, âAttributeError : 'Vectorâ object has no attribute âToXyzâ[â File ââ, line 16, in\nâ], i even try to put IN[1] directly withount being in a list but it give the same error.
for the second python you wrote, i see only 3 inputs (pan, tilt, roll) but i do not see the main input that need to be rotated by these 3 parameters, what exactly i have to insert, is it the 3D view or the vector of my line or what?
Apologies, I should have done a screenshot of my graph to give you context.
You can use a Dynamo Point for IN[1]
. .ToXyz()
in the script should convert the Vector.
Perhaps add this to the imports
clr.AddReference("ProtoGeometry")
from Autodesk.DesignScript.Geometry import *
Looking into this I think there is an easier way to get the vectors. If the forward vector is F(x,y,z) we can define the ârightâ vector as R(-y,x,0) which is a 90 degree rotation in the xy plane of the F vector. Then the up vector is the cross product - if we have roll we can rotate with F as the axis
Main python script - I have added a helper function so that the script can accept Dynamo Point
or Vector
or a Revit XYZ
import sys, clr
clr.AddReference("ProtoGeometry")
from Autodesk.DesignScript.Geometry import Vector, Point
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import ViewOrientation3D
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
def check_vec(vec):
if isinstance(vec, (Vector, Point)):
return vec.ToXyz()
return vec
perspective = UnwrapElement(IN[0]) if IN[0] else doc.ActiveView
EyePosition = check_vec(IN[1])
UpDirection = check_vec(IN[2])
ForwardDirection = check_vec(IN[3])
TransactionManager.Instance.EnsureInTransaction(doc)
NewVO = ViewOrientation3D(EyePosition, UpDirection, ForwardDirection)
perspective.SetOrientation(NewVO)
uidoc.RefreshActiveView() # Comment out if not using active view
TransactionManager.Instance.TransactionTaskDone()
OUT = perspective
Rotation of the âUpâ vector by the roll angle using the âForwardâ vector as the axis
import clr
import math
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import XYZ, Transform
f = IN[0].ToXyz()
u = IN[1].ToXyz()
roll = math.radians(IN[2]) if IN[2] else 0
OUT = Transform.CreateRotation(f, roll).OfVector(u)
Sorry for my late reply, Really Thank you so much Mike for your reply and support.
It works
In addition, after some times i was exploring in dynamo, i have found a node that is doing exactly the same function from the Package âGeniusiLociâ
it has python inside same as what you proposed.
I really want to thank you again.
Have a nice day.
1 Like