Let's write β

プログラミング中にできたことか、思ったこととか

円形グラフプロット

角度と値を元にした円形のグラフを書く必要がある場面があったので、
とりあえずの出力結果を確認するためにlispbuilder-sdlをつかって書いてみました。

(ql:quickload :lispbuilder-sdl)
(ql:quickload :lispbuilder-sdl-gfx)

(defun read-plot-data (file-name)
  (with-open-file (in file-name :direction :input
                      :if-does-not-exist nil) 
    (loop for deg = (read in nil)
          for val = (read in nil)
          while (and deg val)
          collect (cons deg val))))

(defun deg->rad (deg)
  (* COMMON-LISP:PI (/ deg 180)))

(defun circle-graph (plot-data)
  (sdl:with-init ()
   (sdl:window 400 400)
   (sdl:clear-display sdl:*white*)
     (sdl:with-events ()
       (:quit-event () t)
        (:idle ()
         ;;目盛を書く
         (loop for radius from 10 upto 200 by 10
               do
               (sdl-gfx:draw-circle-* 200 200 radius :color sdl:*black*))
         (loop for deg from 0 upto 360 by 10
               do
               (sdl-gfx:draw-line-* 200 200 
                    (round 
                      (+ 200 (* 200 (cos (deg->rad deg)))))
                    (round 
                      (- 200 (* 200 (sin (deg->rad deg)))))
                    :color sdl:*black*))
         (loop for data in plot-data
               for deg = (car data)
               for val = (cdr data)
               for x = (round 
                         (+ 200 (* 10 val (cos (deg->rad deg)))))
               for y = (round
                         (- 200 (* 10 val (sin (deg->rad deg)))))
               do
                (sdl-gfx:draw-filled-circle-* x y 3 :color sdl:*red*))
         (sdl:update-display)))))

かなり適当に何も考慮していない実装になっているような気がします。

0 20
15 40
30 10
45 13
50 34

こんなデータにたいして

(circle-graph (read-plot-data "plot.data"))

こんな感じでよんでやると
f:id:Pocket7878_dev:20121028002328p:plain
こんな感じで表示されます。
Vectoで描画して画像にしたほうが綺麗に表示されるような気がするので、後ほどやってみます。

追記:
Vectoにしてみました。

(defun circle-graph-png (plot-data out-file)
  (vecto:with-canvas (:width 400 :height 400)
    (vecto:translate 200 200)
    ;;目盛を書く
    (vecto:move-to 0 0)
    (loop for radius from 10 upto 200 by 10
          do
          (vecto:centered-circle-path 0 0 radius))
    (vecto:stroke)
    (loop for deg from 0 upto 360 by 10
          do
          (vecto:move-to 0 0)
          (vecto:line-to 
            (* 200 (cos (deg->rad deg)))
            (* 200 (sin (deg->rad deg))))
          (vecto:stroke))
    ;;データを書く
    (vecto:set-rgb-fill 1.0 0.0 0.0)
    (loop for data in plot-data
          for deg = (car data)
          for val = (cdr data)
          do
          (vecto:centered-circle-path
            (* 10 val (cos (deg->rad deg)))
            (* 10 val (sin (deg->rad deg))) 3)
          (vecto:fill-path)
          (vecto:stroke))
    (vecto:save-png out-file)))

画像は、
f:id:Pocket7878_dev:20121028002130p:plain
こうなります。モワレェ...