Task

Draw a sphere.

The sphere can be represented graphically, or in ASCII art, depending on the language capabilities.

Either static or rotational projection is acceptable for this task.



Related tasks

 draw a cuboid
 draw a rotating cube
 write language name in 3D ASCII
 draw a Deathstar


; Draw a sphere
 
(defun normalize (v)
  "Normalize a vector."
  (setq invlen (/ 1.0 (sqrt (dot v v))))
  (mapcar (lambda (x) (* invlen x)) v))
 
(defun dot (v1 v2)
  "Dot product of two vectors."
  (+ (* (car v1) (car v2))
     (* (cadr v1) (cadr v2))
     (* (caddr v1) (caddr v2))))
 
(defun make-array (size)
  "Create an empty array with size*size elements."
  (setq m-array (make-vector size nil))
  (dotimes (i size)
    (setf (aref m-array i) (make-vector size 0)))
  m-array)
 
(defun pic-lines (arr size)
  "Turn array into a string."
  (setq all "")
  (dotimes (y size)
    (setq line "")
    (dotimes (x size)
      (setq line (concat line (format "%i \n" (elt (elt arr y) x)))))
    (setq all (concat all line "\n")))
  all)
 
(defun pic-show (arr size)
  "Convert size*size array to grayscale PBM image and show it."
  (insert-image (create-image (concat (format "P2
%i %i 255\n" size size) (pic-lines arr size)) 'pbm t)))
 
(defun sphere (size k amb dir)
  "Draw a sphere."
  (let ((arr (make-array size))
        (ndir (normalize dir))
        (r (/ size 2)))
    (dotimes (yp size)
      (dotimes (xp size)
        (setq x (- xp r))
        (setq y (- yp r))
        (setq z (- (* r r) (* x x) (* y y)))
        (if (>= z 0)
          (let* ((vec (normalize (list x y (sqrt z))))
                 (s (max 0 (dot vec ndir)))
                 (lum (max 0 (min 255 (* 255 (+ amb (expt s k))
                                                    (/ (1+ amb)))))))
            (setf (elt (elt arr yp) xp) lum)))))
    (pic-show arr size)))
 
(sphere 200 1.5 0.2 '(-30 -30 50))