0
0

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 1 year has passed since last update.

ico球の面を求める

Posted at

 
この記事はアドカレに参加しています。
 

ico球の面を求める

 球を疑似的に表現する方法はいくつかありますが、その一つにico球があります。サッカーボールみたいなやつです。
image.png
 

文献

ICO球の作り方(1)
Creating an icosphere mesh in code
 上記のリンク先が参考になりますが、今回は再帰処理を使って記述していきます。
 

アルゴリズム

 ico球の面を求めるアルゴリズムを考えていきます。
image.png

  1. まずは、各頂点の座標を求めます。1:(1+√5)/2 の比率の長方形を三枚思い浮かべたとき、各長方形の頂点をそのまま使います。

  2. 次に、この頂点をもとに三角形を作ります。
    このとき、三角形を任意の回数で分割していきます。

  3. 最後に、三角形の頂点と原点からの距離を調整します。

以下の動画のように進めていきます。twitterだとヌルヌル動いて分かり易いかもしれないですね。
交通モデル.gif

 

コード

 以下にaviutlで使用できるコードを示します。(注:以下のコードは古いものですので、バグがあります。完全なものを作成したい場合はこちらを参考にしてください。)

<?--こっちはテキストボックスとかに貼り付けておく
--変数
MR=100--半径
MS=1--[[再帰回数(0~5ぐらいが目安。大きすぎるとフリーズ)]]
MS=math.max(0,math.floor(MS))
MK=math.sqrt(MR*MR)/(2^MS)+1

--長さをもとめる関数
local function sn(x,y,z)
return math.sqrt(x*x+y*y+z*z)
end

--長さをMRにする関数
local function se(k)
local q=math.sqrt(k[1]*k[1]+k[2]*k[2]+k[3]*k[3])
k[1]=k[1]*MR/q
k[2]=k[2]*MR/q
k[3]=k[3]*MR/q
return k
end

--二地点の中点を求める関数
local function sl(w,e)
local d={}
d[1]=(w[1]+e[1])*0.5
d[2]=(w[2]+e[2])*0.5
d[3]=(w[3]+e[3])*0.5
return d
end

--描画関数
local function sd(a,b,c)
obj.load("figure","四角形",0xffffff,1)
obj.alpha=0.95
a,b,c=se(a),se(b),se(c)
obj.drawpoly(a[1],a[2],a[3],
         b[1],b[2],b[3],
         c[1],c[2],c[3],
         c[1],c[2],c[3])
end

--頂点をもとに描画
function sa(a,b,c)
local k=sn(a[1]-b[1],a[2]-b[2],a[3]-b[3])
if(k<MK)then
 sd(a,b,c)
else
 local ab,ac,bc=sl(a,b),sl(a,c),sl(b,c)
 sa(a,ab,ac)
 sa(b,ab,bc)
 sa(c,ac,bc)
 sa(ab,ac,bc)
end
end
?>
--こっちは図形(四角形)にスクリプト制御から貼り付け
local r,yr
r=MR/2
yr=(1+math.sqrt(5))/2*r

local p={}

--二十面体の頂点を求める
p[1]={r,yr,0}
p[2]={r,-yr,0}
p[3]={-r,yr,0}
p[4]={-r,-yr,0}

p[5]={yr,0,r}
p[6]={yr,0,-r}
p[7]={-yr,0,r}
p[8]={-yr,0,-r}

p[9]={0,r,yr}
p[10]={0,r,-yr}
p[11]={0,-r,yr}
p[12]={0,-r,-yr}

--頂点をもとに描画
sa(p[2],p[4],p[11])
sa(p[2],p[4],p[12])

sa(p[2],p[6],p[12])
sa(p[2],p[5],p[11])
sa(p[4],p[8],p[12])
sa(p[4],p[7],p[11])

sa(p[2],p[5],p[6])
sa(p[4],p[7],p[8])
sa(p[1],p[5],p[6])
sa(p[3],p[7],p[8])

sa(p[6],p[10],p[12])
sa(p[8],p[10],p[12])
sa(p[5],p[9],p[11])
sa(p[7],p[9],p[11])

sa(p[1],p[6],p[10])
sa(p[1],p[5],p[9])
sa(p[3],p[8],p[10])
sa(p[3],p[7],p[9])

sa(p[1],p[3],p[9])
sa(p[1],p[3],p[10])

バグの修正とか

 上に示したコードはバグがあるので、それを直す必要があります。
こちらにあるc言語で書かれたコードがバグ修正されています。変更点としては、
・描画時に頂点が時計回りになるようにした。
・再帰処理の終了判定が曖昧だったため、しっかりと変数でカウントするようにした。
…の二つです。
本当はluaもコードも直した方がいいけど、めんどいんや、、、
 

最後に

 本来は、重い処理を再帰処理で書くのは良くないことです。ですが、今回はたのしいので再帰処理で書きました。いつか機会があれば、再帰処理を使わない処理も書いてみたいですね。

twitter

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?