この記事は【Kuin Advent Calendar 2016】の17日目の記事です。
【記事中で紹介しているコードについて】
コンパイルが通らない場合など、不具合があれば、@tatt61880まで連絡いただけると助かります。よろしくお願いいたします。
func main()
var depth: int :: 8
var size: int :: (1b64).shl(depth) $ int
do @drawDragon(size, depth * 2)
end func
const ww: int :: 512
var wh: int
var h: int
func drawDragon(leng: int, depth: int)
var d: int :: leng / 3 + 1
do @h :: leng + 3
do @w :: leng + d * 3 / 2 + 2
do @wh :: @ww * @h / @w
do @buf :: #[@h * @w]@Rgb
for i(0, ^@buf - 1)
do @buf[i] :: #@Rgb
end for
do @x :: d
do @y :: d
do @dx :: leng
do @dy :: 0
do @scale :: 1
do @clen :: 0
for(1, depth)
do @dy :: @dx + @dy
do @dx :: 2 * @dx - @dy
do @scale :* 2
do @x :* 2
do @y :* 2
end for
do @iter_string("FX", depth)
var maxv: float :: 0.0
for i(0, ^@buf - 1)
var b: @Rgb :: @buf[i]
for j(0, ^[b.r, b.g, b.b] - 1)
var c: float :: [b.r, b.g, b.b][j]
if(c > maxv)
do maxv :: c
end if
end for
end for
var rate: float :: 255.0 / maxv
for i(0, ^@buf - 1)
do @buf[i].r :* rate
do @buf[i].g :* rate
do @buf[i].b :* rate
end for
if(true)
{ 画面に出力する場合はこちら。 }
var wndMain: wnd@Wnd :: wnd@makeWnd(null, %aspect, @ww, @wh, "Dragon curve")
var drawMain: wnd@Draw :: wnd@makeDraw(wndMain, 0, 0, @ww, @wh, %scale, %scale, false)
do drawMain.onPaint :: onPaint
func onPaint(wnd: wnd@WndBase, width: int, height: int)
var pixSize: float :: @ww $ float / @w $ float
for i(0, @h * @w - 1)
do draw@rect(pixSize * (i % @w) $ float, pixSize * (i / @w) $ float, pixSize, pixSize,
| @buf[i].r $bit8 $int * 0x10000
| +@buf[i].g $bit8 $int * 0x100
| +@buf[i].b $bit8 $int
| +0xFF000000)
end for
do draw@render(0)
end func
while(wnd@act())
end while
else
{ ファイルに出力する場合はこちら。PNM形式(P6)で保存します。 }
var fs: file@Writer :: file@makeWriter("dragon_curve.pnm", false)
do fs.writeStr("P6\n\{@w} \{@h}\n255\n")
var fpix: []bit8 :: #[@h * @w * 3]bit8
for i(0, @h * @w - 1)
do fpix[3 * i ] :: @buf[i].r $ bit8
do fpix[3 * i + 1] :: @buf[i].g $ bit8
do fpix[3 * i + 2] :: @buf[i].b $ bit8
end for
do fs.write(fpix)
end if
end func
var x: int
var y: int
var w: int
var dx: int
var dy: int
var scale: int
var clen: int
class Rgb()
+var r: float
+var g: float
+var b: float
end class
var buf: []@Rgb
func h_rgb(x: int, y: int)
var VAL: float :: 1.0 - (lib@cos(lib@pi * 64.0 * @clen $ float / @scale $ float) - 1.0) / 4.0
const SAT: float :: 1.0
var h: float :: 6.0 * @clen $ float / @scale $ float
var c: float :: VAL * SAT
var X: float :: -c * (h % 2.0).abs()
var p: @Rgb :: @buf[y * @w + x]
switch(h $ int % 6)
case 0
do p.r :+ c
do p.g :+ X
case 1
do p.r :+ X
do p.g :+ c
case 2
do p.g :+ c
do p.b :+ X
case 3
do p.g :+ X
do p.b :+ c
case 4
do p.b :+ c
do p.r :+ X
case 5
do p.b :+ X
do p.r :+ c
default
end switch
end func
func iter_string(str: []char, d: int)
for i(0, ^str - 1)
var c: char :: str[i]
switch(c)
case 'X'
if(d <> 0)
do @iter_string("X+YF+", d - 1)
end if
case 'Y'
if(d <> 0)
do @iter_string("-FX-Y", d - 1)
end if
case '+'
do @dx :$ @dy
do @dy :: -@dy
case '-'
do @dx :$ @dy
do @dx :: -@dx
case 'F'
do @clen :+ 1
do @h_rgb(@x / @scale, @y / @scale)
do @x :+ @dx
do @y :+ @dy
default
assert false
end switch
end for
end func