10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Incanterで3D円グラフを描く & マルチメソッドの拡張

Posted at

3D円グラフは、使うと死が待っています。

範囲を選択_015.png

その錯視が、どんなものか分からないと殺せるものも殺せないので、3D円グラフを描いてみることにします。

IncanterはClojureの統計解析ライブラリですが、肝心の3D円グラフは描けません。
ですが、中で使われているJFreeChartは、3D円グラフReadyです。(サイトのロゴが3D円グラフなのは皮肉なものです)

これを拡張します。通常の円グラフは以下のように書けます。

(view (pie-chart ["a" "b" "c"] [10 20 30]))

なので同じ感じで、pie-chart-3d関数を追加します。

ソースはpie-chartをまるっとコピーし、ChartFactoryでChartオブジェクトを作るところだけ、createPieChartからcreatePieChart3Dに書き換えます。

https://github.com/kawasima/incanter-charts-3d/blob/v1.5.4/src/incanter/charts_3d.clj#L66
(ChartFactory/createPieChart3D
                  title
                  dataset
                  legend?
                  false
                  false)

これで3D円グラフのチャートが生成されます。

(view (pie-chart-3d ["a" "b" "c"] [10 20 30]))

IncanterではSwingを使ってグラフを表示するのにview関数を、画像ファイルに出力するのにsave関数をそれぞれ使います。せっかくの3D円グラフなので、錯視が如何ほどのものか、その3Dの視点をグリグリ動かしてみたいですよね!
そこで、view関数を再定義してみます。

https://github.com/liebke/incanter/blob/master/modules/incanter-charts/src/incanter/charts.clj#L3349
(defmethod view org.jfree.chart.JFreeChart
  ([chart & options]
    (let [opts (when options (apply assoc {} options))
          window-title (or (:window-title opts) "Incanter Plot")
          width (or (:width opts) 500)
          height (or (:height opts) 400)
          frame (ChartFrame. window-title chart)]
      (doto frame
        (.setSize width height)
        (.setVisible true))
      frame)))

viewの定義はマルチメソッドになっていて、JFreeChartクラスのインスタンスだったらこのview関数で処理されます。JFreeChartのオブジェクト構成は、グラフの種類はJFreeChartのオブジェクトがもつPlotで区別されます。グラフの種類によらずChartFactoryで生成されるオブジェクトは、すべてJFreeChartクラスのインスタンスになります。したがって、このようにJFreeChartクラスでディスパッチされると"3D円グラフだけ特別な処理をする"ということができないのです。

この挙動を変えるには、次のようにします。

https://github.com/kawasima/incanter-charts-3d/blob/v1.5.4/src/incanter/charts_3d.clj#L136
(when-let [original-view-fn (get-method view org.jfree.chart.JFreeChart)]
  (defmethod view org.jfree.chart.JFreeChart [chart & options]
    (let [view (apply original-view-fn chart options)]
      (when (= (type (.getPlot chart)) org.jfree.chart.plot.PiePlot3D)
        (pie-slider view))
      view)))

基本的にはdefmethodで再定義するのですが、元のメソッドをget-method関数で取り出しておくのがポイントです。そしてPlotがPiePlot3Dのときだけ、右側にスライダーをつけるようにしています。

スライダー付き3D円グラフ

同様にsaveも再定義して、3D円グラフでファイル拡張子がGIFのときだけ、アニメーションGIFを出力するようにしました。ぜひお使いください。

3D円グラフアニメ


incanter-charts-3d
https://github.com/kawasima/incanter-charts-3d

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?