Here is another method for achieving a rotational effect, based on having only distances, not angles:

                 ,.onOK|||||HQme., (x,y) 
            ,.szF'``           ``'Tux.,
    (u,v) ,z'``       ____,..---*''/``'c,
        ,x'`_,..---*'`            /    `'w,
      .u'\,            d         /       `'n.
     dy`  `\,                   /          `qb
    /7      `\,                /             VA
   4y         `\,             /               KD,
  ,I'           `\,          /                `VA
  dp              `\,       /                  qb
 ,j'                `\,    /                   `t,
 AV                   `\, /          r          VA
 69                      O----------------------96
 VA                    (w,z)                    AV
 `t,                                           ,j'
  qb                                           dp
  `I,                                         ,U'
   \D                                         4y'
    VA                                       /7'
     qb,                                   ,dy
      `'n.                               .u'`
        `'w,                           ,x'`
          `'c,,                     ,,z'`
            `'Tux.,,           ,,.szF'`
                 `'TTOKQQQQQH@TT'`

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)
             (consp p2)
             (> (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))))))))