rubyでBézierの計算をしようと思って、まずは雰囲気だけ書いた。(主に演算子の優先順位について。いちいち調べたくないから動かして観察する!)
演算子式 (Ruby 1.9.3)を見られるのは優秀なやつだけ!
排他的論理和(XOR)のために ^ が使われているから、冪乗の計算にハットを使えないのが不便だゎ~。
#! /usr/bin/ruby -Ku class Point attr_reader :x, :y def initialize(x, y) @x = x; @y = y end end class Bezier def initialize(p0, p1, p2, p3) @p0 = p0; @p1 = p1; @p2 = p2; @p3 = p3 end def pos(t) x = (1-t)**3 * @p0.x + 3 * (1-t)**2 * t * @p1.x + 3 * (1-t) * t**2 * @p2.x + t**3 * @p3.x y = (1-t)**3 * @p0.y + 3 * (1-t)**2 * t * @p1.y + 3 * (1-t) * t**2 * @p2.y + t**3 * @p3.y return x, y end end ################################################################################ b = Bezier.new(Point.new(1, -1), Point.new(1, 0), Point.new(1, 0), Point.new(1, 1)) 0.upto(10) do |i| p b.pos(0.1 * i) end
はぁ... しっかりと丸め誤差が出よるゎ...。
(1, -1)→(1, 1)のstraight curveのつもりだし、数式上はx成分は恒等的に1のはずなんだがね。
$ ruby bezier_test.rb [1.0, -1.0] [1.0, -0.7280000000000001] [1.0000000000000002, -0.5040000000000001] [1.0, -0.3159999999999999] [1.0, -0.15199999999999997] [1.0, 0.0] [0.9999999999999999, 0.15200000000000014] [1.0, 0.3160000000000001] [1.0, 0.5040000000000001] [1.0, 0.7280000000000001] [1.0, 1.0]
ま、
return x, y
のとこを
return x.round(10), y.round(10)
にでもすれば、上記の場合はなんか綺麗になるけど、丸め誤差を適当な決め打ちの桁で四捨五入するのもますます制御が難しくなりそうだね!ご利用は計画的に!だね!