common/plane.ss
```#lang scheme
;; plane.ss
;; (Geometric) plane-related operations

(require "../utils.ss")
(require "point.ss")
(require "vector.ss")
(require "scheme-functions.ss")

(provide (struct-out plane))
(define-struct plane
(p n)
#:transparent)

(provide make-plane*)
(define make-plane*
(case-lambda
[(p1 p2 p3)
(make-plane p1 (cross-product (p->q p1 p2)
(p->q p2 p3)))]
[(p n) (make-plane p n)]))

(provide plane->4pts)
(define (plane->4pts plane)
(define n (plane-n plane))
(define p (plane-p plane))
(define d (- (+ (* (vx n) (cx p))
(* (vy n) (cy p))
(* (vz n) (cz p)))))
(define (plane-point-z x y)
(xyz x y
(/ (- 0 (* (vx n) (cx p)) (* (vy n) (cy p))) (vz n))))
(define (plane-point-y x z)
(xyz x
(/ (- 0 (* (vx n) (cx p)) (* (vz n) (cz p))) (vy n))
z))
(define (plane-point-x y z)
(xyz (/ (- 0 (* (vz n) (cz p)) (* (vy n) (cy p))) (vx n))
y z))
(define (three-non-colinear a b c d)
(if (v-colinear (p->q a b) (p->q a c))
(list a b d)
(list a b c)))
(let ((l (append
(three-non-colinear p
(plane-point-x (add1 (cy p)) (cz p))
(plane-point-y (add1 (cx p)) (cz p))
(plane-point-z (add1 (cx p)) (cy p)))
;; This last point helps us define the slicing stuff...
(list (p+v p n)))))
(display* "4pts: " l)l))

(provide plane-xy+ plane-xy-
plane-xz+ plane-xz-
plane-yz+ plane-yz-)
(define plane-xy+
(make-plane origin (vxyz 0 0  1)))
(define plane-xy-
(make-plane origin (vxyz 0 0 -1)))

(define plane-xz+
(make-plane origin (vxyz 0  1 0)))
(define plane-xz-
(make-plane origin (vxyz 0 -1 0)))

(define plane-yz+
(make-plane origin (vxyz  1 0 0)))
(define plane-yz-
(make-plane origin (vxyz -1 0 0)))

;;;; AXIS
(provide (struct-out axis)
axis-pp axis-pv
axis-plane)

(define-struct axis
(p v))

(define (axis-pp p1 p2)
(axis-pv p1 (p->q p1 p2)))
(define axis-pv make-axis)
(define axis-plane
(case-lambda
[(p)
(axis-pv (plane-p p) (plane-n p))]
[(p pt)
(axis-pv pt (plane-n p))]))

(provide x-axis y-axis z-axis)
(define x-axis (axis-pp origin (xyz 1 0 0)))
(define y-axis (axis-pp origin (xyz 0 1 0)))
(define z-axis (axis-pp origin (xyz 0 0 1)))

(provide rotate-by)
(define rotate-by
(case-lambda
[(axis angle)
(lambda (p) (rotate-by p axis angle))]
[(p axis angle)
;;TODOOOOOOOOOOO     ;; Taken from apache commons math.geometry.Rotation
;; http://commons.apache.org/math/apidocs/org/apache/commons/math/geometry/Rotation.html#Rotation(org.apache.commons.math.geometry.Vector3D,%20double)
(let* ([point  (if (axis? axis) (axis-p axis) origin)]
[vector (if (axis? axis) (axis-v axis) axis)]
[norm (vlength vector)]
[half-angle (* 0.5 angle)]
[coeff (/ (sin half-angle) norm)]
[q0 (cos half-angle)]
[q1 (* coeff (vx vector))]
[q2 (* coeff (vy vector))]
[q3 (* coeff (vz vector))]

;; Translate 'point to the origin
[p* (+ p (p->q point origin))]
;; Rotate it around the origin
[x (cx p*)]
[y (cy p*)]
[z (cz p*)]
[s (+ (* x q1) (* y q2) (* z q3))]
[p**
(xyz
(- (* 2 (+ (* q0 (- (* x q0) (- (* z q2) (* y q3)))) (* s q1))) x)
(- (* 2 (+ (* q0 (- (* y q0) (- (* x q3) (* z q1)))) (* s q2))) y)
(- (* 2 (+ (* q0 (- (* z q0) (- (* y q1) (* x q2)))) (* s q3))) z))]
;; Translate to 'point again
[p*** (+ p** (p->q origin point))])
p***)]))
```