Если бы мы знали, что прямоугольник будет квадратом с центром вокруг начала координат, тогда было бы компактное решение. Для более общего случая, о котором вы просите, вот возможное решение:
(defn rect-edges
"Construct the four edges of the rect"
[x y width height]
[[1 0 x]
[1 0 (+ x width)]
[0 1 y]
[0 1 (+ y height)]])
(def min-vec (completing (comp first sort vector)))
(defn intersect-dir
"Intersect a ray from the origin with a line"
[[dx dy] [nx ny k]]
(let [dot (+ (* nx dx) (* ny dy))]
(if (not (zero? dot))
(let [lambda (/ k dot)]
(if (<= 0 lambda)
[lambda (* lambda dx) (* lambda dy)])))))
(defn boundary-intersection
"Find the point that intersects the boundary of a polygon"
[dir boundary-edges]
(rest (transduce
(comp (map (partial intersect-dir dir))
(filter some?))
min-vec
[Double/POSITIVE_INFINITY 0 0]
boundary-edges)))
(defn polar-to-cartesian-rect [alpha rho edges]
(boundary-intersection [(* rho (Math/cos alpha))
(* rho (Math/sin alpha))]
edges))
Пример его вызова:
(let [rho 1
rect (rect-edges -2 -3 5 4)]
(doseq [alpha-deg [0 30 60 90 120 150 180 210 -90]]
(println "Intersection at angle alpha =" alpha-deg "is"
(polar-to-cartesian-rect (Math/toRadians alpha-deg)
rho rect))))
и мы получаем
Intersection at angle alpha = 0 is (3.0 0.0)
Intersection at angle alpha = 30 is (1.7320508075688779 1.0)
Intersection at angle alpha = 60 is (0.577350269189626 1.0)
Intersection at angle alpha = 90 is (6.123233995736766E-17 1.0)
Intersection at angle alpha = 120 is (-0.5773502691896255 1.0)
Intersection at angle alpha = 150 is (-1.7320508075688779 1.0)
Intersection at angle alpha = 180 is (-2.0 2.4492935982947064E-16)
Intersection at angle alpha = 210 is (-2.0 -1.154700538379252)
Intersection at angle alpha = -90 is (1.8369701987210297E-16 -3.0)