« 「スプラインの長さ c4d」で検索された人がいらしたので… | トップページ | たまには、公開されている、C4DのPluginでも見てみようか…と思ったけど… »

C4D C.O.F.F.E.E.SDK R12 スプラインオブジェクト…

C.O.F.F.E.E.SDK R12で変更された、スプラインオブジェクト(SplineObject class)…

前の記事で、スプラインの長さをXPressoで求めていましたが、C.O.F.F.E.E.の場合は、これを参考にしてください。

R11までのSplineObject classは、以下の通りだ…

//c.o.f.f.e.e.sdk R9.5
class SplineObject : PointObject
{
public:
  SplineObject();

  [int] GetSegmentCount();       //スプラインオブジェクト内のセグメント数
  [array] GetSegments();         //各セグメントのポイント数の配列の取得
  [bool] SetSegments([array] s); //セグメント配列の適用
 
  [array] GetTangents();         //各ポイントのハンドル配列の取得
  [bool] SetTangents([array] t); //ハンドル配列の適用

  [vector] GetSplinePoint([float] x, [int] segment);   //任意のセグメント上の1D座標(0.0~1.0)での3D座標を取得
  [vector] GetSplineTangent([float] x, [int] segment); //任意のセグメント上の1D座標(0.0~1.0)での接線を取得

  [bool] InitLength([int] segment);    //以下GetLength(),UniformToNatural()の為に任意のセグメント番号を指定して初期化
  [bool] FreeLength();                 //InitLength()で使用したメモリを開放

  [float] GetLength();                 //セグメントの長さの取得
  [float] UniformToNatural([float] x); //セグメント上の均等分布位置を取得
}

c.o.f.f.e.e.SDK R9.5より抜粋

コメントが間違っていたら、ごめんなさい…

c.o.f.f.e.e.SDK R12より、InitLength()以下が別の新たなクラス(SplineLengthData class)に分けられたのね…

//c.o.f.f.e.e.sdk R12
class SplineObject : PointObject
{
public:
  SplineObject();

  [int] GetSegmentCount();
  [array] GetSegments();
  [bool] SetSegments([array] s);

  [array] GetTangents();
  [bool] SetTangents([array] t);

  [vector] GetSplinePoint([float] x, [int] segment);
  [vector] GetSplineTangent([float] x, [int] segments);
};

c.o.f.f.e.e.SDK R12より抜粋

//c.o.f.f.e.e.sdk R12
class SplineLengthData
{
public:
  SplineLengthData();

  [bool] Init([SplineObject] op, [int] segm  =  0);
  [void] Free();

  [float] UniformToNatural([float] pos);
  [float] GetLength();
  [float] GetSegmentLength([int] a, [int] b);
};

c.o.f.f.e.e.SDK R12より抜粋

SplineObjectクラスのメンバは、以前と変わりないようだ…
新たに分けられたSplineLengthDataクラスは、InitLength()がInit()へ変更されスプラインオブジェクトとセグメント番号を渡すのだ…

SplineLengthDataクラスを割り当ててからGetLength()等のメンバを使う前に、Init()を必ず実行してから使用してください。
c.o.f.f.e.e.SDK R12以前は、InitLength()を実行しないと、よくフリーズを起こしていましたが、R12からは、フリーズしないようですね…

SplineLengthDataクラスはメモリを消費するので、使い終わったらメンバのFree()を実行して、メモリを開放してくださいね…

使用方法は、以前と変わりないので特別書きません…

新たに追加された、GetSegmentLength()メンバ関数だけ…
このメンバ関数は、ポイント間の長さをセグメント全体からのパーセンテージで返します。
セグメントの長さは、GetLength()で取得できますので、実際のポイント間の長さは…

ポイント間の長さ = sl->GetLength() * GetSegmentLength(a, b);

GetSegmentLength()に渡すa、bは、セグメント毎のポイント番号です。

Splinelengthdata_01

閉じている場合は、次のようになります。

Splinelengthdata_02

GetSegmentLength()に渡すa、bの値の大きの関係と返り値は、

a < b 正の長さ
a > b 負の長さ

最後に、スプラインのセグメント:0のポイント間の長さをコンソールに表示するスクリプトです。

/*
スプラインのセグメント:0のポイント間の長さをコンソールに表示する
2011.1.3
*/


main(doc , op)
{
  if(!instanceof(op, SplineObject))return;    //スプライン以外終了

  var pts;                        //セグメント:0のポイント数を格納する変数
  var seg = op->GetSegments();    //セグメントの取得
  if(seg){                        //セグメントの取得に成功したら…
    pts = seg[0];                 //セグメント:0のポイント数を格納
  }else{                          //セグメントの取得に失敗したら…
    pts = op->GetPointCount();    //代わりに総ポイント数を格納
  }
  if(pts < 2)return;              //ポイント数が2個に満たないときは終了
  if(!op#SPLINEOBJECT_CLOSED)pts -= 1;    //スプラインが開いているときはポイント数を1減らす

  var sld = new(SplineLengthData);    //SplinLengthDataクラスの割り当て
  sld->Init(op, 0);                 //割り当てたsldを選択オブジェクトとセグメント:0を指定して初期化
  var length = sld->GetLength();    //スプラインの長さを取得
  println(op->GetName());           //コンソールにオブジェクト名を表示
  println("length : ", length);     //スプラインの長さを表示

  var i;             //カウンタ変数
  var sum = 0.0;     //ポイント間の長さの集計変数
  var btw_length;    //ポイント間の長さを格納する変数
  for(i = 0; i < pts; i++)
  {
    btw_length = length * sld->GetSegmentLength(i, i + 1);    //ポイント間の実際の長さを算出
    println(i, "-", i + 1, " : ", btw_length);
    sum += btw_length;       //ポイント間の長さの集計
  }
  println("---------------");
  println("sum : ", sum);    //ポイント間長さの集計を表示
  println("===============");

  sld->Free();               //sldで使用したメモリを開放
}

ごめん…読みづらい…
スプラインを開いて実行…

Splinelengthdata_03

スプライン
length : 1025.708151
0-1 : 169.344208
1-2 : 144.713120
2-3 : 145.807144
3-4 : 167.886246
4-5 : 178.794067
5-6 : 100.956291
6-7 : 118.279030
---------------
sum : 1025.708151
===============

スプラインを閉じて実行…

Splinelengthdata_04

スプライン
length : 1185.544678
0-1 : 169.344208
1-2 : 144.713120
2-3 : 145.807144
3-4 : 167.886246
4-5 : 178.794067
5-6 : 100.956291
6-7 : 118.279137
7-8 : 159.764481
---------------
sum : 1185.544678
===============

同じスプラインでも終点付近のポイント間の長さが微妙に変わる…
ま、算出して取得しているので…

SplineLengthDataクラスのGetLength()で取得した長さと、GetSegmentLength()で取得したポイント間の長さを合計した物が同じになったので、問題ないですね…

そう言えば…以前、GetSegmentLength()が無かったので、ポイント間の長さを取得するのに、SendModelingCommand()を使って不必要なポイントを削除して、GetLength()で取得してましたっけ…
http://villager-and-c4d.cocolog-nifty.com/blog/2009/06/c4d-coffee-603e.html#more

もう、こんな事しなくても良いわけで…

|

« 「スプラインの長さ c4d」で検索された人がいらしたので… | トップページ | たまには、公開されている、C4DのPluginでも見てみようか…と思ったけど… »