今回はなんちゃって離散ボロノイ図の描画(描画は完全にいつものやつ)です。全然厳密ではないので、実行結果を見て楽しむぐらいしかできません。
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | class Voronoi POINT_TYPE = { :nomal => 0 , :generator => 1 , :border => 2 } def initialize(i, j, generators) @i_size , @j_size = i, j @generators = generators @points = Array . new ( @i_size ) do Array . new ( @j_size ) { POINT_TYPE [ :nomal ] } end @generators . each do |i, j| @points [i][j] = POINT_TYPE [ :generator ] end end def exec @i_size .times.to_a.product( @j_size .times.to_a) do |i, j| @generators .map do |gi, gj| Math.sqrt( ((i-gi)** 2 ) + ((j-gj)** 2 ) ) end .sort.tap do |ary| if (ary[ 0 ] - ary[ 1 ]).abs < 0 . 9 @points [i][j] = POINT_TYPE [ :border ] puts self printf "\e[#{@i_size + 1}A" ; STDOUT .flush; #sleep 0 . 1 end end end puts self rescue Interrupt exit 0 end def to_s "\n" << @points .map do |line| " " << line.map do |point| case point when POINT_TYPE [ :nomal ] then "\e[47m \e[0m" when POINT_TYPE [ :generator ] then "\e[41m \e[0m" when POINT_TYPE [ :border ] then "\e[46m \e[0m" end end .join( "" ) end .join( "\n" ) end end generators = [ [ 8 , 2 ], [ 6 , 26 ], [ 30 , 20 ], [ 35 , 5 ], [ 20 , 10 ], [ 20 , 33 ] ] voronoi = Voronoi. new ( 40 , 40 , generators) voronoi.exec |
実行結果
赤が母点、青が境界を表しています。楽しい。
図1 voronoi.rb 実行結果
おわりに
今やりたいことでボロノイ図が必要だったのですが、正しい点が求められているか確認するため境界線だけわかればよかったので、そのようなコードを書いてみました。とは言え図1のようでは線が粗いので、全く同じ処理でマス目を10等分した版をgnuplotで出力してみました(図2)。ちゃんと線に見えるのでとりあえずこれでいいかなという感じです。(ちゃんとしたボロノイ図もいつかやってみたい)
図2 gnuplotの出力結果
0 件のコメント:
コメントを投稿