I was working on a script to orient spotlights to a certain focus point. This requires the fixture to be rotated in 2 planes. The rotation angle I calculate by creating vectors between the light fixture and the focus point. See attached rhino file and python script.
Right now it works, but only trough iteration in ugly while loops. I want to know if there is a way I can determine the direction I need to rotate in.
This script is a continuation of a version posted here
Just a thought but as spotlights seem to be round and therefore do not care about any possible rotation in the plane perpendicular to their light vectors - can you not create two planes from normal using the ‘from’ and ‘to’ vectors and then do a transformation plane-to-plane?
This means the light fixture needs to be rotated in two axes, which is what I am doing in the script. But the point is that the calculated angle between 2 vectors can be positive or negative and not necessarily correspond to the direction it needs to be rotated in.
@Graham, I’ll look into it, thanks. Edit: I actually have no idea how I could use atan2 to solve this
I tried to implement this in the second while loop since this one uses a single angle from 2 vectors. But it doesn’t seem to work. Maybe you can have a look if I’m doing something wrong:
#calculate horizontal rotation
#get the plane of the spot_h_circle and calculate from there
for item in items:
if rs.ObjectName(item) == "spot_h_circle":
h_circle = rs.coercecurve(item)
rc, h_circle = h_circle.TryGetCircle()
if rs.ObjectName(item) == "spot_target":
target = rs.coerce3dpoint(item)
if rs.ObjectName(item) == "spot_source":
source = rs.coerce3dpoint(item)
plane = h_circle.Plane
h_cen = h_circle.Center
h_vec = rs.VectorCreate(pt_focus, h_cen)
angle = rs.VectorAngle(h_vec, f_vec)
if(a.X*b.Y - a.Y*b.X < 0):
if abs(angle)<0.1 or i>20:
print "went through second while loop %d times" %i
for item in items:
if rs.ObjectName(item)[:6]!="spot_v" and rs.ObjectName(item)!="slider":
rs.RotateObject(item, pivot, angle, plane.ZAxis)
@lando.schumpich thanks for the example code. I am sure I am still missing something, because when I use your signedVectorAngle definition, and pass my two vectors, it returns a different value than rs.VectorAngle. In fact it either returns 180 or 0, which leads me to think calculations are done in the wrong plane. But I don’t understand what your code is doing well enough to correct it for my situation. In my case the 2 vectors are in a plane that has its Z-axis always perpendicular to world Z-axis. Hope this gives you a clue.
@lando.schumpich , that doesn’t make sense to me because the vectors I’m testing are neither parallel or anti-parallel. What I do not understand in your code is why you need to remap the vectors first?
Actually the remapping was from the first iteration if the code that operated on the .X and .y properties of the vectors directly. This is probably not needed anymore you can try removing the remap and see what happens
@lando.schumpich, I don’t know what I am missing, but…
When I try to implement this script and the lines are NOT in WorldXY, then I always get 0 as a result.
When I go through the code, everything makes sense, though.