Here is another method for achieving a rotational effect, based on having only distances, not angles:
(u,v) ,z'`` ____,..---*''/``'c,
,x'`_,..---*'` / `'w,
.u'\, d / `'n.
dy` `\, / `qb
/7 `\, / VA
4y `\, / KD,
,I' `\, / `VA
dp `\, / qb
,j' `\, / `t,
AV `\, / r VA
VA (w,z) AV
From the above points, let (x,y) be the starting point, (w,z) the center of rotation, and d the distance to the new point. In other words, the rotation is counterclockwise from (x,y) to a point d in distance from (x,y) about (w,z).
Let r be the distance from (x,y) to (w,z) (i.e., the radius of rotation) and define c=sqrt(r2-(d/2)2) (a helpful constant). Since r is a distance, r=sqrt((x-w)2+(y-z)2).
From this we get:
u = w+((x-w)⋅(c2-(d/2)2)-(y-z)⋅d⋅c)/r2
v = z+((y-z)⋅(c2-(d/2)2)+(x-w)⋅d⋅c)/r2
Thanks to jrn for noticing that supplying a negative number for d will cause a clockwise rotation.
Below is my LISP code to achieve such a rotation. Note that the rotation function will return
nil if abs(d) is more than twice as big as the distance from the starting point to the center of rotation (i.e., c is not a real number).
(defun distance (p1 p2)
"Takes two points and finds the distance between them."
(when (and (consp p1)
(> (length p1) 1)
(> (length p2) 1)
(every 'numberp p1)
(every 'numberp p2))
(sqrt (+ (expt (- (first p1) (first p2)) 2)
(expt (- (second p1) (second p2)) 2)))))
(defun distance-rotate (p c d)
"Takes a point p, a center of rotation c, and a distance d.
Rotates counter-clockwise about c to a point d away from p.
Use a negative number for d to get a clockwise rotation."
(when (and (numberp d) (distance p c))
(let* ((r (distance p c))
(k (sqrt (- (expt r 2) (expt (/ d 2) 2))))
(dx (- (first p) (first c)))
(dy (- (second p) (second c))))
(when (< (abs d) (* 2 r))
`(,(+ (first c)
(/ (- (* dx (- (expt k 2) (expt (/ d 2) 2)))
(* dy k d)) (* r r)))
,(+ (second c)
(/ (+ (* dy (- (expt k 2) (expt (/ d 2) 2)))
(* dx k d)) (* r r))))))))