3

スプラインに沿って 3D チューブを生成しようとしています。スプラインの座標 (x1、y1、z1 - x2、y2、z2 - など) が黄色で示されています。これらのポイントで円を生成する必要があり、その頂点は後のスタジアムで接続されます。円は、正しいチューブを形成するために、スプラインの 2 つの線分セグメントの「角」に対して垂直である必要があります。セグメントは、説明のために低く保たれていることに注意してください。

[どうやら画像の投稿は許可されていないので、このリンクで画像をご覧ください] http://img191.imageshack.us/img191/6863/18720019.jpg

スプラインの各点で各リングの頂点を計算できる限りですが、それらはすべて同じ平面上、つまり同じ角度になっています。「脚」に従って回転させる必要があります(たとえば、AとBはCです)。

私はこれを熟考し、次のことを考えました。

  • 2 つの線分は 2 つのベクトルとして見ることができます (図 A & B)
  • コーナー (図 C) は、頂点のリングを計算する必要がある場所です。
  • すべての頂点が存在する平面を見つける必要があります
  • 次に、この平面 (=ベクトル?) を使用して、C である中心点から新しいベクトルを計算できます。
  • 半径* sinとcosを使用してx、y、zを見つけます

しかし、私はこれの数学の部分で本当に混乱しています。内積について読みましたが、この場合の適用方法がわからないスカラーが返されます。

誰かが私を正しい方向に向けることができますか?

[編集] 状況についてもう少し情報を提供するには:

ポリゴンを形成するためのインデックスを持つ別のバッファを指定すると、3 つのグループで頂点位置を記述し、OpenGL ES によって接続されるフロートのバッファを作成する必要があります。

チューブに形を与えるために、最初に float の配列を作成しました。これは、3 次元空間のコントロール ポイントを 3 つのグループで表します。

次に、セグメント密度の変数とともに、これらのコントロール ポイントを関数に渡します。この関数は、これらのコントロール ポイントを使用して CatmullRom スプラインを作成し、これをフロートの別の配列の形式で返します。キャットマルロムスプライン.

これらの頂点のそれぞれで、密度が異なる頂点のリングを作成したいと考えています(滑らかさの量/リングごとの頂点)。

以前の頂点 (制御点と catmull rom スプラインを記述する頂点) はすべて破棄されます。

チューブ リングを形成する頂点のみが OpenGL に渡され、OpenGL はそれらを接続して最終的なチューブを形成します。

catmullrom スプラインを作成し、その頂点の位置にリングを作成することはできますが、それらはすべて、スプライン パスをたどるのではなく、同じ角度の平面上にあります。

[/編集]

ありがとう!

4

4 に答える 4

10

次のようなパラメトリック カーブがあるとします。

xx[t_] := Sin[t];
yy[t_] := Cos[t];
zz[t_] := t;  

これにより、次のことが得られます。 代替テキスト

曲線の接線ベクトルは、各方向の導関数によって形成されます。私たちの場合には

Tg[t_]:= {Cos[t], -Sin[t], 1}  

そのベクトルに直交する平面は、暗黙の方程式を解くことになります。

Tg[t].{x - xx[t], y - yy[t], z - zz[t]} == 0  

私たちの場合、これは次のとおりです。

-t + z + Cos[t] (x - Sin[t]) - (y - Cos[t]) Sin[t] == 0  

今度は、曲線を中心とするその平面内の円を見つけます。すなわち:

c[{x_, y_, z_, t_}] := (x - xx[t])^2 + (y - yy[t])^2 + (z - zz[t])^2 == r^2  

両方の方程式を解くと、円の方程式が得られます。

代替テキスト

チッ!

編集

また、たくさんの円を描くと、(効率的ではない) チューブが得られる場合があります。

代替テキスト

または、適切な Graphics 3D ライブラリを使用する場合:

代替テキスト

編集

あなたが主張するので:)ジャンクションで円を計算するプログラムを次に示します。

a = {1, 2, 3}; b = {3, 2, 1}; c = {2, 3, 4};
l1 = Line[{a, b}];
l2 = Line[{b, c}];

k = Cross[(b - a), (c - b)] + b; (*Cross Product*)
angle = -ArcCos[(a - b).(c - b)/(Norm[(a - b)] Norm[(c - b)])]/2;
q = RotationMatrix[angle, k - b].(a - b);
circle[t_] := (k - b)/Norm[k - b] Sin@t + (q)/Norm[q] Cos@t + b;

Show[{Graphics3D[{
    Red, l1,
    Blue, l2,
    Black, Line[{b, k}],
    Green, Line[{b, q + b}]}, Axes -> True],
  ParametricPlot3D[circle[t], {t, 0, 2 Pi}]}]

代替テキスト

編集

ここに、この方法で構築されたメッシュがあります。それはきれいではありません、私見:

代替テキスト

于 2010-12-22T02:23:54.300 に答える
1

微分幾何学の Fenet 公式を見る必要があります。らせんの例については、図 2.1 を参照してください。

サーフェスとカーブ

于 2010-12-22T02:30:37.313 に答える
1

あなたが何の言語を選んでいるかはわかりませんが、MatLab を話せば、すでにいくつかの実装が利用可能です。別の言語を使用している場合でも、一部のコードは再実装を刺激するほど明確である場合があります。

重要な点は、頂点を接続するときにチューブがねじれたくない場合は、基底をローカルに決定することはできず、曲線に沿って伝播する必要があるということです。jalexiou によって提案された Frenet フレームは 1 つのオプションですが、より単純なものでも問題なく動作します

私は私の形成期に呼び出された単純な MatLab 実装tubeplot.mを行いました (単純な非フレネット伝播に基づく)。それをグーグルで検索すると、kth.se の Anders Sandberg が同じ名前で (再?) 実装を行っていることがわかります。http://www.nada.kth.se/~asa/Ray/Tubeplot/tubeplot.htmlで。

TubePlot.m の図

編集: 以下は、 の単純な実装の擬似コードですtubeplot.m。かなり頑丈であることがわかりました。

計画は、2 つの法線ab曲線に沿って伝搬し、曲線上の各点と曲線ab接線が、前の点で使用された基底に「できるだけ近い」直交基底を形成するようにすることです。この基準を使用して、チューブの円周上の点を見つけることができます。

// *** Input/output ***
// v[0]..v[N-1]: Points on your curve as vectors
//               No neighbours should overlap
// nvert: Number of vertices around tube, integer.
// rtube: Radius of tube, float.
// xyz: (N, nvert)-array with vertices of the tube as vectors


// *** Initialization ***
// 1: Tangent vectors
for i=1 to N-2:
    dv[i]=v[i+1]-v[i-1]
dv[0]=v[1]-v[0], dv[N-1]=v[N-1]-v[N-2]

// 2: An initial value for a (must not be pararllel to dv[0]):
idx=<index of smallest component of abs(dv[0])>
a=[0,0,0], a[idx]=1.0

// *** Loop ***
for i = 0 to N-1:
    b=normalize(cross(a,dv[i]));
    a=normalize(cross(dv[i],b));
    for j = 0 to nvert-1:
        th=j*2*pi/nvert 
        xyz[i,j]=v[i] + cos(th)*rtube*a + sin(th)*rtube*b

cos実装の詳細:とを事前に計算することで、おそらく速度を上げることができますsin。また、堅牢なパフォーマンスを得るには、たとえば よりも近い入力ポイントを融合する0.1*rtubeか、少なくともすべてのdvベクトルが非ゼロであることをテストする必要があります。

HTH

于 2010-12-22T03:20:28.230 に答える
0

線分と上向きのベクトルの外積を取ると、両方に直角のベクトルが得られます(線分が正確に上向きまたは下向きでない限り)。これを水平と呼びます。水平線分と線分の外積をとると、線分と他の線分に対して直角の別のベクトルが得られます(これを垂直と呼びましょう)。次に、lineStart + costheta*水平+sintheta *垂直のシータ(0〜2Pi)で円の座標を取得できます。

編集:2つのセグメント間の中間点のポイントを取得するには、2つの線分のベクトルの合計を使用して平均を求めます。

于 2010-12-21T22:04:45.360 に答える