[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
過去ログ
投稿順に表示
スレッドごとに表示
キーワード
タイトル
投稿者
編集パスワード
コメント
添付
ロープ形状作成スクリプトのための ウンチク( その2 )
2007年01月31日 (水) 21時23分
加藤俊明
返信
【1. Bezier 曲線をN分割する 】

1)曲線の全長 tatalL を求める
2)n分割した長さ targetL = tatalL/n を求める
3)曲線の始端から targetL の長さを与える bezier parameter を順次求める。
4)得られた bezier parameter に従って、N分割する anchor point を追加する。


《 1.1 bezier parameter の扱いについて 》

bezier 曲線は anchor point と anchor point に挟まれた一つの区間毎に bezier parameter t( 0 <= t <= 1 )によって定義される。

プログラム上での bezier parameter の扱い方には、次の二通りを混在させる。
この方がプログラム上のデータハンドリグが楽になるため。

・当該の曲線区間のみで有効な parameter t( 0 <= t <= 1 )
・全曲線( = 複数の区間で与えられる曲線の集合体 )
 に対して定義される bezier parameter t*

  曲線の始端の区間( 区間 No. 0 )では t* = t
  次の区間( 区間 No. 1 )では t* = t + 1
  次の区間( 区間 No. 2 )では t* = t + 2
   ‥‥‥‥‥‥‥‥‥‥‥‥
  区間 No. k では t* = k + t


《 1.2 曲線の全長を求める 》

anchor point と anchor point に挟まれた一つの bezier 曲線の区間毎に長さを求めることができる。
曲線の全長を求めるには各区間毎に曲線長を求めてその和を求める。

一つの区間の bezier 曲線長を求めるのには次の四つの制御点座標が必要。

  p(0)〜p(3):Bezier 制御点座標
  p(0):anchor point i
  p(1):out handle i
  p(2):in handle i + 1
  p(3):anchor point i + 1

一つの区間の全長ではなく、bezier parameter t1 〜 t2( 0 <= t1, t2 <= 1 )で与えられる区間の長さを求めるには、次のように考える。

区間:t1 〜 t2 の長さ = ( 区間: 0 〜 t2 の長さ )-( 区間: 0 〜 t1 の長さ )

method BL_Length(p, t) ( 後日詳述 )によって、bezier parameter 0 〜 t で与えられる区間の bezier 曲線長が得られる。


《 1.3 N分割する点の bezier parameter を求める 》

///////////////////////////////////////////////////
曲線の始端から targetL = tatalL/n の長さを与える
bezier parameter t() を順次求める擬似コード
///////////////////////////////////////////////////

method BL_Param(p0, p1, p2, p3, lineLength, targetLength) ( 後日詳述 )によって、bezier 制御点座標 p0〜p3 で与える区間( 区間長 lineLength )内で、始端から trargrtLength の長さを与える bezier parameter t が返される

dim n as integer // 分割数
dim nk as integer // 区間数( 0 基数 )
           開いた曲線:nk = アンカーポイント数 - 2
           閉じた曲線:nk = アンカーポイント数 - 1
dim k as integer // 区間 No. を与える index( 0 基数 )

dim blockL(nk) as float // 区間 0〜nk の曲線長を格納
dim totalL as float // 曲線全長 totalL = Sum( blockL )
dim targetL as float // N分割長 targetL = totalL/n
dim trgtL as float // 当該区間で N分割点を与える当該区間内での長さ
dim p(nk, 3) as vec3 // 区間 k におけるbezier 制御点座標?を p(k, 0) 〜 p(k, 3) の二次元配列に格納
dim tt as float // 当該区間内で N分割点を与える bezier parameter t
dim t(n - 2) as float // N分割を与える bezier parameter t* を格納

k = 0
trgtL = targetL
for i = 0 to n - 2
        if trgtL > blockL(k) then
                do
                        trgtL = trgtL - blockL(k)
                        k = k + 1
                Loop until trgtL <= blockL(k)        
        end if
        tt = BL_Param(p(k, 0), p(k, 1), p(k, 2), p(k, 3), blockL(k), trgtL)
        t(i) = k + tt
        trgtL = trgtL + targetL
next

《 1.4 bezier parameter t() に従ってアンカーポイントを追加 》

Shade の script では bezier paramert t* を与えてアンカーポイントを追加することができる。
apple script の場合
  insert control point at 2.3
によって、区間 2 の bezier parameter 0.3 の位置にアンカーポイントが追加される。

複数のコントロールポイントを順次追加する場合、1.3 で求めた bezier parameter 配列 t() の値をそのまま使用することができないことに注意されたい。

例えば、t(0) = 2.3, t(1) = 2.6 である場合、
  insert control point at 2.3
  insert control point at 3 + (2.6 - 2.3)/(1 - 0.3)
あるいは
  insert control point at 2.6
  insert control point at 2 + 0.3/0.6
としなければならない

後者のケースのように、bezier parameter の大きな方から順番にアンカーポイントを追加する方が式が簡単になる。

method Reset_T(t() as float) as float() ( 後述 )によって、1.3 で求めた bezier parameter 配列 t() の順番を逆順に並び替え、スクリプトで直接使用できる値に変換する。

  t = Reset_T(t)

これによって得られた?t() を用いて script command でアンカーポイントを追加する
apple script の場合

  repeat with tt in t
   insert control point at tt
  end repeat


///////////////////////////////////////////////////
Reset _T(t() as float) as float() の擬似コード
///////////////////////////////////////////////////

dim nt as integer // t() の配列サイズ( 0基数 )
dim k as integer // アンカーポイントが追加される区間?No.

nt = Ubound(t) // 配列 t() のサイズを求める

dim tt(nt) as float // 返り値

k = t(nt) + 1
for i = nt downto 0
 if Floor(t(i)) = k then // Floor() は切り捨てを与える関数
  tt(i) = k + (t(i) - k)/(t(i + 1) - k)
 else
  tt(i) = t(i)
  k = Floor(t(i))
 end if
next

return tt
 

《 1.5 BL_Length(p, t) の擬似コード 》
 
     later

《 1.6 BL_Param(p0, p1, p2, p3, lineLength, targetLength) の擬似コード 》
 
     later
確認 - その2
2007年01月31日 (水) 20時37分
加藤俊明
返信
python の計算で分母が 0 になってオーバーフローしてしまった場合、エラーとなってストップしますか ?
それとも、INF のような形でオーバーフローしたまま計算は続行されてしまいますか ?
Re[486][485][484]: osamu さんのロープ作成スクリプト
2007年01月30日 (火) 20時14分
でった☆
返信
おおお、なんとありがたい。
楽しみにしております。

で、複数の返り血(´Д`;)
返り値を持たせるには、リスタやタプルで戻すのが一般的かと。

#vec_a,vec_bは座標リスト
#関数部分
det test(vec_a, vec_b):
vec_new_a = [ vec_a[0] + vec_b[0], vec_a[1] + vec_b[1], vec_a[2] + vec_b[2] ]
vec_new_b = [ vec_a[0] - vec_b[0], vec_a[1] - vec_b[1], vec_a[2] - vec_b[2] ]
return [vec_new_a, vec_new_b]

#呼び出し側
v_list = test(vec_a, vec_b)
v_a = v_list[0]
v_b = v_list[1]

こんな感じでしょーか。
Re[485][484]: osamu さんのロープ作成スクリプト
2007年01月30日 (火) 18時01分
加藤俊明
返信
で、その前に、確認というか、質問というか、Python で 返り値のある function / method / subroutine( 正確な呼び方はしりませんが )において、複数の返り値のあるものを書くことは可能でしょうか ?

擬似コードで書けば、

{result as boolean, a as float} = MyFunction(v() as vec3, k as integer)

のようなものですが
Re[484]: osamu さんのロープ作成スクリプト
2007年01月30日 (火) 17時54分
加藤俊明
返信
> 今すぐどうこうできないですが、移植というより、自分なりも新しいものとして作成したい。という気持ちは
> あります。

まあ、これは当然の気持ちですね。
移植といっても osamu さんがどういう方法で作っているかは知りませんし、人様の書いたスクリプトを解析してそれを調べるなんて面倒なことは頼まれても簡便願いたいものですね。

では、こうしましょう。
ロープ作成スクリプトを書いてくださる方がいるかどうかには関係なく、N 分割やロープ作成に関して知っておくと便利な擬似コードをとにかく紹介します。

N分割をからロープ形状作成までの方法はいろいろ考えられますが、大きく分ければ、次の二つに分けられます。

1)スクリプト内部で座標値を全部計算する
2)できる限りスクリプトを利用して Shade に図形を描かせて、その座標値を取得してロープ形状を作成する

1)が一番すっきるするのですが、Affine Matrix の計算がゴマンと出てきますので、まどろっこしく時間がかかりますが 2)の方法の一つを参考として紹介することにします。( あくまでも一つのアイデアにすぎませんから、ほかにもっといい方法があるかもしれません)
Re[483][482]: osamu さんのロープ作成スクリプト
2007年01月30日 (火) 17時23分
でった☆
返信
N分割の講座は、ぜひ拝聴したいところです。
移植については、左手の腱鞘炎がかなりひどく、ちょっとスクリプトを書ける状態じゃないので
今すぐどうこうできないですが、移植というより、自分なりも新しいものとして作成したい。という気持ちは
あります。
ありますが、要望されているかたは、そんなにのんきに待ってもいられないのでしょうから、移植に名乗りを
上げて下さる方がいると良いですね。
Re[482]: osamu さんのロープ作成スクリプト
2007年01月30日 (火) 12時51分
管理人
返信
> の python 版の要望が Shade Web で出ていますが、確か氏は Light Wave に乗り換えていたと思うので、無理じゃないのかな ?
>
> で、もって、ロープ作成に必要な計算の擬似コードと script を使った疑似操作の仕方について、不肖わたくしめがここで紹介すれば、誰か作ってみるという奇特な方はいらっしゃいませんでしょうか。

できれば、私が名乗りを上げたいところですが、
まだまともなPython1つ書いてない状態で、ベジェの出てくるやつとなると(^^;;

せっかく加藤さんに手法を紹介いただいたので、どなたか作ってみようという方がいらっしゃればいいんですが。
osamu さんのロープ作成スクリプト
2007年01月29日 (月) 21時26分
加藤俊明
返信
の python 版の要望が Shade Web で出ていますが、確か氏は Light Wave に乗り換えていたと思うので、無理じゃないのかな ?

で、もって、ロープ作成に必要な計算の擬似コードと script を使った疑似操作の仕方について、不肖わたくしめがここで紹介すれば、誰か作ってみるという奇特な方はいらっしゃいませんでしょうか。

もし、いらっしゃるようでしたら、紹介しますけど、

お前が作れと言われましても、Distributor で簡単にできちゃうので、いまさら python の書き方を勉強しながら作るのは、ちょっとね。


全体の流れは次のようになります。

0)入力インターフェース(入力項目とインターフェース部分は各自でお願いします。説明は省きます)
1)線形状長さの計算( 一度ここで紹介したことがありますが、再掲します)
2)線形状を N 分割するベジェパラメータの求め方
3)操作の流れの説明
  N分割するベジェパラメータに従ってポイントを追加
  正六角形の閉じた線形状をロープ中心線の線形状に沿って掃引
  掃引で得られた自由曲面の U 方向線形状のアンカーポイント座標をを特定の順序に従って取得
  取得した座標値を折れ線として複数本作成
  折れ線にスムースをかける
  スムースをかけられた複数本の線に沿って円形断面を掃引

閉じた線形状に対してロープ形状を作成する場合や、線形状長さと ロープのピッチ長さ×ピッチ数 の不一致をどうするかといった、ちと工夫を要する所もあるのですが、対象を開いた線形状にかぎったり、ピッチ長さを適当に modify することを許す仕様にすれば、案外と簡単ですよ。( でもちょっと長くなってしまうけど )

それと、もし紹介することになっても、一度に書き下ろす時間はないので、時間を見つけてすこしずつ分割して書き込むことになると思います。
Re[480]: いまさらながら
2007年01月29日 (月) 01時11分
管理人
返信
> スクリプトのリファレンスがあると、思い付きから取り掛かりまでが凄く気軽ですね。
> 実際に使ってみて、敷居が下がった感じを受けました。
> 提供者の方の苦労のおかげで、参照する側は信じられないほど楽が出来ます。
そうですよね。
というか、リファレンスも無しで、書かれていたうりさんはすごいです。

私はというと、完成度の高いでった☆さんのリファレンスも公開されたのに、
自分のTclのPython化が全然進んでいない・・・
9の体験版の期日も、もう切れるので9での動作も確認できそうにないです(^^;;
いまさらながら
2007年01月28日 (日) 00時58分
うり
返信
スクリプトのリファレンスがあると、思い付きから取り掛かりまでが凄く気軽ですね。
実際に使ってみて、敷居が下がった感じを受けました。
提供者の方の苦労のおかげで、参照する側は信じられないほど楽が出来ます。

もう感謝感謝です。
[1]
[2]
[3]
[4]
[5]
[6]
[7]
[8]
[9]
[10]
過去ログ
投稿順に表示
スレッドごとに表示