0
0

ベジェ曲線で描く円の面積

Posted at

ベジェ曲線で円弧を描く

コンピュータグラフィックスで滑らかな曲線を描くのに利用されるベジェ曲線(Bézier Curve)を用いて円(1/4円弧)を描きます。3次ベジェ曲線を用いるので制御点は4つになります。「ベジェ曲線の定義と4つの性質(高校数学の美しい物語)」 で紹介されている以下の2つを用いると4つの制御点は$[1,0],[1,v],[v,1],[0,1]$と表せることが分かるのでこの$v$を求めることを考えます。

  • ベジェ曲線の端点
  • ベジェ曲線の端点で進む向き

image.png

ベジェ曲線の式

ベジェ曲線は一般には以下のように表され、今回は$N=3$のケースです。

\vec{p}(t) = \sum_{k=0}^{N}\binom{N}{k}t^k(1-t)^{N-k}\vec{p_k}

これをそのままpythonのコードにします。bzr_xyは制御点のリストを渡すと$[x,y]$を$t$の式として返します。下の例では$v=0.5$として4点を渡して$[x,y]$の式を$t$を変数として得ています。この式を元にして$t=[0..1]$で描いたのが上の図の緑の曲線です。青の線で描かれた円弧より少し内側になっているのが分かります。

import sympy as sp
import numpy as np
t, v = sp.symbols('t v')
def bzr_xy(p):
  N = len(p)-1
  return sum([sp.binomial(N,i)*(1-t)**(N-i)*t**i*p[i] for i in range(N+1)])

p = np.array([[1,0],[1,0.5],[0.5,1],[0,1]])
print(bzr_xy(p))

# [0.5*t**2*(3 - 3*t) + 3.0*t*(1 - t)**2 + 1.0*(1 - t)**3
#  1.0*t**3 + 1.0*t**2*(3 - 3*t) + 1.5*t*(1 - t)**2]

45度の半径が1となるようにvを求める

45度の直線$y=x$と円弧の交点は$(\frac{\sqrt{2}}{2},\frac{\sqrt{2}}{2})$となるはずなのでこれを条件として$v$を求めます。$v = 0.552284749830793$が求まりました。

x, y = bzr_xy(np.array([[1,0],[1,v],[v,1],[0,1]]))
sol = sp.solve((x - sp.sqrt(2)/2, y - sp.sqrt(2)/2), (t,v))
v_value = sol[0][1].evalf()
print("v = ", v_value)
# v =  0.552284749830793

ベジェ曲線の円の面積

この時の円の面積を求めます。$1/4$円の面積$A$は以下のように表されます。

A = \int_{0}^{1} y \,dx = \int_{1}^{0} y \frac{dx}{dt} \,dt

これをそのままsympyで書くと以下のようになります。面積の誤差は0.028%となりほぼ等しいことが分かります。

A = sp.integrate(y*sp.diff(x,t), (t, 1, 0))
A_value = A.subs(v,v_value)
print("A = ", A_value, ((A_value*4-sp.pi)*100/sp.pi).evalf())
# A =  0.785618083164127 0.0280010543603986

円の面積と等しくなる時のvを求める

さらに円の面積と等しくなる時の$v$をsympyを使って求めてみます。$A-\pi/4$=0として$v$を求めます。$v = 0.551778477804468$が求まりました。

eq = A - sp.pi/4
vs = sp.solve(eq,v)
print(vs[0].evalf())
# 0.551778477804468

(開発環境:Google Colab)

この考え方はProject Euler、Problem 363: Bézier Curvesを解くのに役に立ちます。

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