F(u,v)=0 をベジエクリッピング法で解く
— ベジエ曲面上の条件曲線を抽出する統一フレームワーク —

1.問題の型

曲面上の条件を1つのスカラー2変数ベジエ関数 F(u,v) に表し、その零集合 F(u,v)=0 を UV 領域の再分割によって追い込み、線分列として出力する。

曲面の輪郭線、平面による断面、金型の抜き勾配の限界線、球との交線 ——一見ばらばらに見えるこれらの問題は、すべてこの1つの型に収まります。異なるのは F の中身と次数だけで、解く仕組みは完全に共通です。

なぜ解が「曲線」になるかは、自由度を数えれば分かります。未知数は u,v の2つ、条件式は1本なので、自由度は 2−1=1、すなわち解集合は1次元の曲線です。条件式が2本になれば自由度0、解は孤立した点になります。

条件式の本数解の次元出力
1本1次元線分列輪郭線、断面線、交線、限界線、等値線
2本0次元点列最近点、臍点、輪郭線の特異点

2.F(u,v) の作り方

条件式が S(u,v) の多項式(あるいは有理式の分子)として書ければ、F の制御係数は厳密に組み立てられます。必要な道具は次の4つだけです。

(a) 積

( Σ aiBip )( Σ bkBkr ) = Σm [ Σi+k=m pCi·rCk / p+rCm · aibk ] Bmp+r

次数は加算されます。2変数の場合は u 方向と v 方向で独立に同じ重みを掛けます。重み pCi·rCk/p+rCm は次数の組ごとに一度だけ表にしておけば、実行時は積和だけで済みます。

(b) 微分

d/du ( Σ aiBip ) = Σ p( ai+1 − ai ) Bip−1

u について微分すると u の次数が1つ下がります。曲面の接ベクトル Su, Sv はこれで得られ、法線 N = Su×Sv は外積=積の差なので (a) で計算できます。

(c) 定数の加減

バーンスタイン基底は総和が1(1の分割)なので、定数 c を足すことは全係数に c を足すことと同じです。S − E や −r² のような項はこれで処理できます。

(d) 次数上げ

次数の異なる項を足すときは、低い方を次数上げしてから加算します。

具体例と次数

双3次パッチ(S は 3×3 次、Su は 2×3 次、Sv は 3×2 次、N は 5×5 次)を前提とした一覧です。

問題条件関数 F(u,v)次数
平面による断面・等高線n·S − d3×3
曲面上のスカラー場の等値線Σ fijBiBj − c3×3
輪郭線(平行投影)D·N5×5
明暗境界線(ターミネータ)L·N5×5
パーティングラインD·N5×5
球との交線|S−C|² − r²6×6
円柱・円錐など二次曲面との交線g(S)(g は陰関数の2次式)6×6
点からの等距離線(S−P)·(S−P) − d²6×6
輪郭線(透視投影)(S−E)·N8×8
退化点(法線が消える点)の集合N·N10×10
抜き勾配の限界線(D·N)² − sin²α (N·N)10×10
等傾斜線・等勾配線(N·D)² − cos²θ (N·N)10×10
ガウス曲率 K=0(放物線)(Suu·N)(Svv·N) − (Suv·N)²14×14

次数が 14×14 まで上がっても、係数が 15×15=225 個になるだけで、アルゴリズムの構造は何も変わりません。凸包判定は符号を見るだけ、凸包クリップは行・列の最小最大を取るだけです。次数が上がると破綻する代数的手法との決定的な違いがここにあります。

注意:制御点に値を代入しただけでは係数にならない
平面による断面 F = n·S − d は F が点について線形なので、制御点 Pij に n·Pij − d を当てはめればそれがそのまま F の係数になります。しかし輪郭線や抜き勾配のように N を含む条件は制御点について3次以上であり、この近道は使えません。制御点での値を並べただけのものは F の係数ではないため、凸包性が成立せず、「全部同符号だから解なし」という判定が誤ったものになります。必ず積の公式で係数を組み立ててください。

3.解法のアルゴリズム

解が点ではなく曲線なので、「1点に追い込む」のではなく「解が通り得ない領域を確実に削り落とし、解の周囲だけを細かくする」という使い方になります。

  1. 凸包による棄却 F の制御係数がすべて正、またはすべて負なら、凸包性よりそのパッチ上で F は決して 0 になりません。よって解なしと断定して打ち切れます。符号を見るだけの判定で、実際のモデルでは大半の領域がこれで捨てられます。
  2. 凸包クリップによる UV 範囲の収縮 符号が混在する場合、u を固定すると F は各 u 列の係数の凸結合になります。したがって、列ごとの最小係数を制御点とするベジエ関数 L(u) と、最大係数によるベジエ関数 U(u) が F の安全な下限・上限を与えます。
    L(u) ≤ F(u,v) ≤ U(u)  →  L(u)≤0 になり得る u 範囲 ∩ U(u)≥0 になり得る u 範囲
    この共通範囲の外では F=0 は絶対に起こらないので、そこまで一気に u 範囲を縮められます。v 方向も同様です。1変数のベジエ関数に対する通常のベジエクリッピング(FAT Line によるクリップ)を、2変数に持ち上げたものにあたります。
  3. 分割と再帰 範囲が十分縮まれば、その部分パッチを de Casteljau で切り出して再帰します。縮まらない場合(零集合がパッチを大きく横切る場合など)は4分割して各象限に再帰します。この切り替えがないと、縮まらないまま再帰が空回りします。
  4. 末端で零集合を線分化 十分小さくなったパッチの内部を細かい格子で評価し、マーチングスクエア法で F=0 の等値線を線分として取り出します。より高い精度が必要なら、セル境界上に限れば F は1変数のベジエ関数になるので、ここも通常のベジエクリッピングで厳密に交点を求められます。
u →v ↓凸包で棄却 9 / クリップで収縮 15 / 末端 22 (緑=f=0 の零集合)
UVパラメータ空間で見た処理の様子。赤=凸包で棄却された領域、橙=凸包クリップで収縮した範囲、青=末端パッチ、濃緑=実際の零集合 F=0。末端パッチが零集合のまわりだけに集中している。

取りこぼしが起こらないこと

この手法の要は、①②で捨てる領域が「F が 0 になり得ないことが数学的に保証された領域」だけである点です。したがって、どんなに細い枝や小さな閉ループであっても見落としません。一様サンプリングでは格子の目を細かくしても「たまたま格子点の間をすり抜けた」解を排除できず、数値追跡法では開始点が見つからない独立したループを丸ごと落としますが、この方法にはその心配がありません。

収束の判定

解が曲線である以上、「1点に収束した」という判定はできません。代わりに解を含む帯の幅で測ります。

判定基準内容と特徴
パラメータ区間部分パッチの u,v 幅が ε 未満で停止。実装は最も簡単だが、パラメータと実長の対応が曲面上で一定でないため精度がばらつく。
幾何的サイズ制御点の凸包の直径が ε 未満で停止。誤差の意味が明確で、得られた線分は真の解から高々 ε しか離れていないと言える。
画面上の大きさ投影して1画素未満なら停止。描画が目的なら最も効率的で、視点が遠いときに自動的に浅くなる。
平坦性部分パッチが十分平坦で F がほぼ線形なら、マーチングスクエアの線形補間が正当化される。

再帰深度の上限は暴走防止の保険として残し、幾何的サイズまたは画面上の大きさを主たる停止条件にするのが実用的です。なお境界上の1次元問題に落とせば、区間幅による通常の収束判定が使え、単根なら2次収束します。

4.実行例

同一のティーポット(32パッチ)に対し、条件関数 F だけを差し替えた結果です。棄却・収縮・再帰・線分化の処理はまったく共通で、プログラム上は係数を作る関数の中身を入れ替えているだけです。

輪郭線 F=(S−E)·N(8×8次)
判定750ノード・線分1344本
抜き勾配の限界線 F=(D·N)²−sin²α(N·N)(10×10次, α=5°, D=+Y)
判定856ノード・線分1480本
球との交線 F=|S−C|²−r²(6×6次)
判定184ノード・線分318本

球との交線は法線 N を必要としないため最も低次で、判定ノード数も輪郭線の1/4です。また輪郭線が視点に依存するのに対し、抜き勾配と球との交線は視点に依存しないので、視点を回しても再計算が不要という違いもあります。

▶ 実演プログラム 条件関数をプルダウンで切り替えながら、抽出の様子・判定ノード数・凸包による棄却率・計算時間を確認できます。凸包クリップの ON / OFF による判定ノード数の違い(ティーポットで約5.7倍)も比較できます。
bezier_surface_field.html を開く

5.出力の形式

末端のマーチングスクエアはセルごとに独立して線分を吐き出すため、得られるのは順序を持たない線分の集合です。描画するだけならこれで十分ですが、次のような用途では端点を照合して連結し、順序づけられた点列(ポリライン)に組み直す必要があります。

連結の際、端点の一致を浮動小数の比較で行うと不安定なので、座標を量子化するか、分割構造からセルの隣接関係を辿るほうが堅実です。

6.条件式が2本の場合(解が点になる問題)

同じ機械をそのまま使えます。2つの係数配列それぞれで凸包判定を行い、どちらか一方でも棄却できればその領域を捨てるという形になります。解が0次元なので絞り込みは曲線の場合より速く進みます。

問題条件式
点と曲面の最近点・最遠点∂h/∂u = 0 かつ ∂h/∂v = 0(h は距離の2乗)
平面と曲面の最近点∂H/∂u = 0 かつ ∂H/∂v = 0
輪郭線の特異点(自己交差・尖点)∂F/∂u = 0 かつ ∂F/∂v = 0
臍点(アンビリック)主曲率が一致する条件の2式

輪郭線の特異点は、隠線消去で可視性の切り替わりを正しく追うために必要になります。曲線の位相を構成する前に求めておくと処理が安定します。

7.実装上の注意点

重根に注意

F が解の位置で符号を変えない形になっていると、マーチングスクエアは何も出力しません。典型例が抜き勾配の限界線で、α=0 とすると F=(D·N)² が重根になり、パーティングライン上で符号が変わりません。この場合は F=D·N(1次の形)に切り替える必要があります。実演プログラムでは α が十分小さいとき自動的に式を切り替え、次数表示も 10×10 から 5×5 に変わるようにしてあります。

退化パッチ

1辺の制御点がすべて同一点に縮退したパッチ(ティーポットの蓋の頂点など)では、その辺上で N=0 となるため、N を含む F も 0 になり、解でない線が現れます。実用上は |N| が十分小さい箇所を除外するか、退化辺をあらかじめ登録しておく処理が必要です。

末端セル内に収まる小さな閉ループ

棄却されなかったセルでも、その内部に小さな閉ループが完全に収まっている場合、4隅の符号がすべて同じになるためマーチングスクエアは何も出力せず、そのループは消えます。凸包判定が保証するのは「捨てた領域に解が無いこと」であって、「残した領域で解を正しく再構成できること」ではありません。末端セルでも係数の符号が混在していれば格子をさらに細かくする、といった追加条件で対処します。

次数と計算量

係数の個数は (次数+1)² で増えますが、増えるのは1ノードあたりの係数計算の手間だけで、探索の構造は変わりません。実測ではティーポット32パッチ・深度5で、6×6次の球との交線が約3ms、8×8次の輪郭線が約22ms、10×10次の抜き勾配が約35msでした。

8.まとめ

ベジエ曲面上の多くの幾何問題は、「スカラー2変数ベジエ関数 F(u,v) の零集合を求める問題」という単一の型に還元できます。F の作り方は積・微分・定数加算・次数上げの4つの操作だけで尽き、解法は凸包による棄却、凸包クリップによる収縮、再帰分割、線分化という4段階の共通処理です。

この統一性により、新しい問題に対しては条件式を1つ書き下すだけで、取りこぼしのない頑健な解法が即座に得られます。これがベジエクリッピング法の最大の実用的価値だと考えています。