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?

陰関数でベジェ曲線の交点を求める ~ その6:2次以下への対応の検討

0
Last updated at Posted at 2025-10-17

一方の曲線の次数が2以下の場合、陰伏方程式の左辺がゼロ(すべての項の係数が$0$)となって根を求められないことがわかり、対応方法を検討しました。

一方の曲線が2次の場合

inter_quadratic.png

この例で、曲線0(オレンジ色)は2次です。
つまり $(x,y)=(f_0(t),g_0(t))=(a_0t^3+a_1t^2+a_2t+a_3,b_0t^3+b_1t^2+b_2t+b_3)$ において $a_0=0$ かつ $b_0=0$ です。この場合、曲線0についての陰関数 $F_0(x,y)=0$ の$x$と$y$に、曲線1(青色)の$f_1(u)$と$g_1(u)$を代入した$u$についての陰伏方程式 $F_0(u)=0$ の左辺が$0$になり、根(曲線1の交点の候補)を求めることができません。
この場合でも$t$についての陰伏方程式 $F_1(t)=0$ の左辺は6次になり、曲線0の交点の候補は求めることができます。しかし、それら候補が曲線1の範囲内であるかわからないので、交点であるか判定することができません。

対策

2次曲線については2次曲線の陰関数を用いることにします。
2次曲線の陰関数をWolfram Alphaで求める方法は、以下に書かれている通りです。

係数と根を求めるためのSage Mathのコードに反映して、F0を2次曲線の陰関数に置き換えました。F1は3次曲線用のままです。

p0x=12; p1x=13; p2x=14; p3x=15
p0y=21; p1y=1; p2y=1; p3y=21
p4x=11; p5x=26; p6x=1; p7x=16
p4y=18; p5y=14; p6y=12; p7y=11
var('t u')
a0=-p0x+3*p1x-3*p2x+p3x
a1=3*p0x-6*p1x+3*p2x
a2=-3*p0x+3*p1x
a3=p0x
b0=-p0y+3*p1y-3*p2y+p3y
b1=3*p0y-6*p1y+3*p2y
b2=-3*p0y+3*p1y
b3=p0y
c0=-p4x+3*p5x-3*p6x+p7x
c1=3*p4x-6*p5x+3*p6x
c2=-3*p4x+3*p5x
c3=p4x
d0=-p4y+3*p5y-3*p6y+p7y
d1=3*p4y-6*p5y+3*p6y
d2=-3*p4y+3*p5y
d3=p4y
x=c0*u^3+c1*u^2+c2*u+c3
y=d0*u^3+d1*u^2+d2*u+d3
F0=a3^2*b1^2-a2*a3*b1*b2+a1*a3*b2^2+a2^2*b1*b3-2*a1*a3*b1*b3-a1*a2*b2*b3+a1^2*b3^2+(-2*a3*b1^2+a2*b1*b2-a1*b2^2+2*a1*b1*b3)*x+(-a2^2*b1+2*a1*a3*b1+a1*a2*b2-2*a1^2*b3)*y+b1^2*x^2-2*a1*b1*x*y+a1^2*y^2
x=a0*t^3+a1*t^2+a2*t+a3
y=b0*t^3+b1*t^2+b2*t+b3
F1=c3^3*d0^3-c2*c3^2*d0^2*d1+c1*c3^2*d0*d1^2-c0*c3^2*d1^3+c2^2*c3*d0^2*d2-2*c1*c3^2*d0^2*d2-c1*c2*c3*d0*d1*d2+3*c0*c3^2*d0*d1*d2+c0*c2*c3*d1^2*d2+c1^2*c3*d0*d2^2-2*c0*c2*c3*d0*d2^2-c0*c1*c3*d1*d2^2+c0^2*c3*d2^3-c2^3*d0^2*d3+3*c1*c2*c3*d0^2*d3-3*c0*c3^2*d0^2*d3+c1*c2^2*d0*d1*d3-2*c1^2*c3*d0*d1*d3-c0*c2*c3*d0*d1*d3-c0*c2^2*d1^2*d3+2*c0*c1*c3*d1^2*d3-c1^2*c2*d0*d2*d3+2*c0*c2^2*d0*d2*d3+c0*c1*c3*d0*d2*d3+c0*c1*c2*d1*d2*d3-3*c0^2*c3*d1*d2*d3-c0^2*c2*d2^2*d3+c1^3*d0*d3^2-3*c0*c1*c2*d0*d3^2+3*c0^2*c3*d0*d3^2-c0*c1^2*d1*d3^2+2*c0^2*c2*d1*d3^2+c0^2*c1*d2*d3^2-c0^3*d3^3+(-3*c3^2*d0^3+2*c2*c3*d0^2*d1-2*c1*c3*d0*d1^2+2*c0*c3*d1^3-c2^2*d0^2*d2+4*c1*c3*d0^2*d2+c1*c2*d0*d1*d2-6*c0*c3*d0*d1*d2-c0*c2*d1^2*d2-c1^2*d0*d2^2+2*c0*c2*d0*d2^2+c0*c1*d1*d2^2-c0^2*d2^3-3*c1*c2*d0^2*d3+6*c0*c3*d0^2*d3+2*c1^2*d0*d1*d3+c0*c2*d0*d1*d3-2*c0*c1*d1^2*d3-c0*c1*d0*d2*d3+3*c0^2*d1*d2*d3-3*c0^2*d0*d3^2)*x+(c2^3*d0^2-3*c1*c2*c3*d0^2+3*c0*c3^2*d0^2-c1*c2^2*d0*d1+2*c1^2*c3*d0*d1+c0*c2*c3*d0*d1+c0*c2^2*d1^2-2*c0*c1*c3*d1^2+c1^2*c2*d0*d2-2*c0*c2^2*d0*d2-c0*c1*c3*d0*d2-c0*c1*c2*d1*d2+3*c0^2*c3*d1*d2+c0^2*c2*d2^2-2*c1^3*d0*d3+6*c0*c1*c2*d0*d3-6*c0^2*c3*d0*d3+2*c0*c1^2*d1*d3-4*c0^2*c2*d1*d3-2*c0^2*c1*d2*d3+3*c0^3*d3^2)*y+(3*c3*d0^3-c2*d0^2*d1+c1*d0*d1^2-c0*d1^3-2*c1*d0^2*d2+3*c0*d0*d1*d2-3*c0*d0^2*d3)*x^2+(3*c1*c2*d0^2-6*c0*c3*d0^2-2*c1^2*d0*d1-c0*c2*d0*d1+2*c0*c1*d1^2+c0*c1*d0*d2-3*c0^2*d1*d2+6*c0^2*d0*d3)*x*y+(c1^3*d0-3*c0*c1*c2*d0+3*c0^2*c3*d0-c0*c1^2*d1+2*c0^2*c2*d1+c0^2*c1*d2-3*c0^3*d3)*y^2-d0^3*x^3+3*c0*d0^2*x^2*y-3*c0^2*d0*x*y^2+c0^3*y^3
F0.coefficients(u)
F1.coefficients(t)
F0.roots(u,ring=CC)
F1.roots(t,ring=CC)

実行結果は以下の通りです。

$F_0(u)$ と $F_1(t)$ の係数
[[16020, 0],
 [-803520, 1],
 [9446760, 2],
 [-40319460, 3],
 [77760000, 4],
 [-69120000, 5],
 [23040000, 6]]
[[133144966, 0],
 [-4211711451, 1],
 [43026564537, 2],
 [-188126431173, 3],
 [370310529600, 4],
 [-331568640000, 5],
 [110592000000, 6]]
$F_0(u)$ と $F_1(t)$ の根
[(0.0282470675121436, 1),
 (0.117724483151864, 1),
 (0.425166800579757, 1),
 (0.569759971247380, 1),
 (0.899382209067053, 1),
 (0.959719468441802, 1)]
[(0.0590578263054768, 1),
 (0.160253041427257, 1),
 (0.201860104402341, 1),
 (0.792283381736507, 1),
 (0.862990890551262, 1),
 (0.921679755577156, 1)]

曲線0と曲線1それぞれについて実根(交点の候補)が6個ずつ求まりました。
上のグラフの赤丸は、これらから座標を求めてプロットしたものです。

一方の曲線が1次の場合

3次ベジェ曲線の制御点が直線上に等間隔で並んでいる場合、1次の直線になります。
(等間隔でない場合も直線になるが、1次にはならない)

inter_linear.png

この例で、曲線0の係数 $a_0,a_1,b_0,b_1$ はいずれも$0$です。
陰伏方程式 $F_0(u)=0$ の左辺は3次用、2次用とも$0$になります。

対策

このケースについては、直線の公式から3次方程式を立て公式(カルダノの公式など)を用いて解くアプローチが一般的だと思いますが、ここでは他と共通のアプローチ、すなわち直線のパラメトリック関数表現から陰関数を求めて差し替えることで解けるか試してみます。

Wolfram Alphaへの入力
Collect[Expand[Eliminate[{a0*t+a1==x,b0*t+b1==y},t]],{x,y}]
結果
a0 b1 - a0 y + b0 x = a1 b0

係数と根を求めるためのSage Mathのコードに反映し、F0を置き換えたものは以下の通りです。

p0x=12; p1x=13; p2x=14; p3x=15
p0y=21; p1y=1; p2y=1; p3y=21
p4x=11; p5x=26; p6x=1; p7x=16
p4y=18; p5y=14; p6y=12; p7y=11
var('t u')
a0=-p0x+3*p1x-3*p2x+p3x
a1=3*p0x-6*p1x+3*p2x
a2=-3*p0x+3*p1x
a3=p0x
b0=-p0y+3*p1y-3*p2y+p3y
b1=3*p0y-6*p1y+3*p2y
b2=-3*p0y+3*p1y
b3=p0y
c0=-p4x+3*p5x-3*p6x+p7x
c1=3*p4x-6*p5x+3*p6x
c2=-3*p4x+3*p5x
c3=p4x
d0=-p4y+3*p5y-3*p6y+p7y
d1=3*p4y-6*p5y+3*p6y
d2=-3*p4y+3*p5y
d3=p4y
x=c0*u^3+c1*u^2+c2*u+c3
y=d0*u^3+d1*u^2+d2*u+d3
F0=-a3*b2+a2*b3+b2*x-a2*y
x=a0*t^3+a1*t^2+a2*t+a3
y=b0*t^3+b1*t^2+b2*t+b3
F1=c3^3*d0^3-c2*c3^2*d0^2*d1+c1*c3^2*d0*d1^2-c0*c3^2*d1^3+c2^2*c3*d0^2*d2-2*c1*c3^2*d0^2*d2-c1*c2*c3*d0*d1*d2+3*c0*c3^2*d0*d1*d2+c0*c2*c3*d1^2*d2+c1^2*c3*d0*d2^2-2*c0*c2*c3*d0*d2^2-c0*c1*c3*d1*d2^2+c0^2*c3*d2^3-c2^3*d0^2*d3+3*c1*c2*c3*d0^2*d3-3*c0*c3^2*d0^2*d3+c1*c2^2*d0*d1*d3-2*c1^2*c3*d0*d1*d3-c0*c2*c3*d0*d1*d3-c0*c2^2*d1^2*d3+2*c0*c1*c3*d1^2*d3-c1^2*c2*d0*d2*d3+2*c0*c2^2*d0*d2*d3+c0*c1*c3*d0*d2*d3+c0*c1*c2*d1*d2*d3-3*c0^2*c3*d1*d2*d3-c0^2*c2*d2^2*d3+c1^3*d0*d3^2-3*c0*c1*c2*d0*d3^2+3*c0^2*c3*d0*d3^2-c0*c1^2*d1*d3^2+2*c0^2*c2*d1*d3^2+c0^2*c1*d2*d3^2-c0^3*d3^3+(-3*c3^2*d0^3+2*c2*c3*d0^2*d1-2*c1*c3*d0*d1^2+2*c0*c3*d1^3-c2^2*d0^2*d2+4*c1*c3*d0^2*d2+c1*c2*d0*d1*d2-6*c0*c3*d0*d1*d2-c0*c2*d1^2*d2-c1^2*d0*d2^2+2*c0*c2*d0*d2^2+c0*c1*d1*d2^2-c0^2*d2^3-3*c1*c2*d0^2*d3+6*c0*c3*d0^2*d3+2*c1^2*d0*d1*d3+c0*c2*d0*d1*d3-2*c0*c1*d1^2*d3-c0*c1*d0*d2*d3+3*c0^2*d1*d2*d3-3*c0^2*d0*d3^2)*x+(c2^3*d0^2-3*c1*c2*c3*d0^2+3*c0*c3^2*d0^2-c1*c2^2*d0*d1+2*c1^2*c3*d0*d1+c0*c2*c3*d0*d1+c0*c2^2*d1^2-2*c0*c1*c3*d1^2+c1^2*c2*d0*d2-2*c0*c2^2*d0*d2-c0*c1*c3*d0*d2-c0*c1*c2*d1*d2+3*c0^2*c3*d1*d2+c0^2*c2*d2^2-2*c1^3*d0*d3+6*c0*c1*c2*d0*d3-6*c0^2*c3*d0*d3+2*c0*c1^2*d1*d3-4*c0^2*c2*d1*d3-2*c0^2*c1*d2*d3+3*c0^3*d3^2)*y+(3*c3*d0^3-c2*d0^2*d1+c1*d0*d1^2-c0*d1^3-2*c1*d0^2*d2+3*c0*d0*d1*d2-3*c0*d0^2*d3)*x^2+(3*c1*c2*d0^2-6*c0*c3*d0^2-2*c1^2*d0*d1-c0*c2*d0*d1+2*c0*c1*d1^2+c0*c1*d0*d2-3*c0^2*d1*d2+6*c0^2*d0*d3)*x*y+(c1^3*d0-3*c0*c1*c2*d0+3*c0^2*c3*d0-c0*c1^2*d1+2*c0^2*c2*d1+c0^2*c1*d2-3*c0^3*d3)*y^2-d0^3*x^3+3*c0*d0^2*x^2*y-3*c0^2*d0*x*y^2+c0^3*y^3
F0.coefficients(u)
F1.coefficients(t)
F0.roots(u,ring=CC)
F1.roots(t,ring=CC)

実行結果は以下の通りです。

$F_0(u)$ と $F_1(t)$ の係数
[[-72, 0], [1116, 1], [-2898, 2], [1923, 3]]
[[-813700369, 0], [5127900849, 1], [-10568048643, 2], [7111117467, 3]]
$F_0(u)$ と $F_1(t)$ の根
[(0.0804106466180081, 1), (0.505518504935201, 1), (0.921091129258023, 1)]
[(0.385662407359399, 1), (0.472411956923444, 1), (0.628056147840225, 1)]

曲線0と曲線1それぞれについて実根(交点の候補)が3個ずつ求まりました。

関連記事

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?