

(defun random-float (&optional (x 1.0))
  (random (coerce x 'float)))


(defun random-float* (&optional (x 1.0))
  (- x (* 2.0 (random (coerce x 'float)))))



; geometry


(defun l-on-spiral (i itt rad &key (x 0.0) (y 0.0) (rot 1.0))
  (ladd
    (list x y)
    (lscale
      (cos-sin (* i (/ (* PI rot) itt)))
      (* (/ i itt) rad))))


(defun l-on-circle (i itt rad &key (x 0.0) (y 0.0))
  (ladd
    (list x y)
    (lscale
      (cos-sin (/ (* i PI 2.0) itt))
      rad)))


(defun l-on-line (i itt x1 x2)
  (ladd
    x1
    (lscale
      (lsub x2 x1)
      (/ i itt))))


(defun l-rand-on-circle (rad &key (x 0.0) (y 0.0))
  (ladd
    (list x y)
    (lscale
      (cos-sin (random (* PI 2.0)))
      rad)))


(defun l-rand-in-circle (rad &key (x 0.0) (y 0.0))
  (let ((ab (sort (list (random 1.0) (random 1.0)) #'<)))
    (ladd
      (list x y)
      (lscale
        (cos-sin (* 2 pi (apply #'/ ab)))
        (* (second ab) rad)))))


(defun l-rand-in-box (sx sy &key (x 0.0) (y 0.0))
  (ladd
    (list (random-float* sx) (random-float* sy))
    (list x y)))


(defun l-rand-on-line (x1 x2)
  (ladd
    x1
    (lscale (lsub x2 x1) (random 1.0))))


(defun l-rand-on-spiral (rad &key (x 0.0) (y 0.0) (rot 1.0))
  (let ((i (random 1.0)))
    (ladd
      (list x y)
        (lscale
          (cos-sin (* i (* PI rot)))
          (* i rad)))))


(defun l-polygon (n rad &key (x 0.0) (y 0.0) (rot 0.0))
  (loop for i from 0 to n
    collect
      (ladd
        (list x y)
        (lscale
          (cos-sin (+ rot (* (/ i n) 2 pi)))
          rad))))


(defun path-rel-lengths (points)
  (destructuring-bind
    (steps total)
    (loop
      with l
      for i from 0 to (2- (length points))
      do
        (setf l (ldst (nth i points) (nth (1+ i) points)))
      sum l into total
      collect l into steps
      finally
        (return (list steps total)))

      (append
        (list 0)
        (loop for s in steps
          sum (/ s total) into summed
          collect
            summed))))


(defun -diff-scale (a b s) (/ (- b a) s))

(defun path-transform (p points lengths)
  (let ((ind 0))
    ; TODO use return instead
    (loop
      for n in lengths
      for i from 0
      do
        (setf ind i)
      until (< p n))

    (let ((s (-diff-scale
               (nth (1- ind) lengths)
               p
               (- (nth ind lengths) (nth (1- ind) lengths))))
          (pb (nth ind points))
          (pa (nth (1- ind) points)))
      (ladd
        pa
        (lscale
          (lsub pb pa)
          s)))))

