研究で与えられた3点をパラボラフィッティング(Parabola Fitting)で関数近似して最小解を求めるようなC++プログラムを作る機会があったので、ちゃんとできているか確認するためにMELで同じようなものを書いてMayaでビジュアル化しました。
本当はMathematicaとか使うんでしょうけど、私には慣れているMayaの方が手っとり早い。
3つトランスフォームノードを選んで、下記のようにコマンドを実行するとフィッティングしたカーブに沿ったアニメーションが作られます。
createXYParabolaAnimExpression_SelectedThreePoints("pSphere1", 0.1, -30);
この場合はpSphere1というオブジェクトにExpressionでアニメーションがつきます。0.1がアニメーション速度で、-30は接線が平行になる点のオフセットです。
動画にするとこんな感じです。
こういった関数あてはめを行うことで、サンプル点よりも細かい情報を得ることができます。MELで作ったところで、このままでは何の役にも立ちませんけどソースを載せておきます。
global proc fit2dParabolaFromThreePoints(
float $in_x1, float $in_x2, float $in_x3,
float $in_y1, float $in_y2, float $in_y3,
float $o_result[]
){
float $denom = ($in_x1 - $in_x2)*($in_x1 - $in_x3)*($in_x2 - $in_x3);
$o_result[0] = ($in_x3 * ($in_y2 - $in_y1) + $in_x2 * ($in_y1 - $in_y3) + $in_x1 * ($in_y3 - $in_y2)) / $denom;
$o_result[1] = ($in_x3*$in_x3 * ($in_y1 - $in_y2) + $in_x2*$in_x2 * ($in_y3 - $in_y1) + $in_x1*$in_x1 * ($in_y2 - $in_y3)) / $denom;
$o_result[2] = ($in_x2 * $in_x3 * ($in_x2 - $in_x3) * $in_y1 + $in_x3 * $in_x1 * ($in_x3 - $in_x1) * $in_y2 + $in_x1 * $in_x2 * ($in_x1 - $in_x2) * $in_y3) / $denom;
};
// Example
// createXYParabolaAnimExpression("pSphere1", 1, 1, 0, 0.1, -30);
global proc createXYParabolaAnimExpression(
string $target_transform,
float $a, float $b, float $c,
float $speed,
float $frame_offset
){
string $tx = $target_transform + ".tx";
string $ty = $target_transform + ".ty";
string $exp_str =
"float $a="+$a+";\n"+
"float $b="+$b+";\n"+
"float $c="+$c+";\n"+
"float $speed="+$speed+";\n"+
$tx+" = (frame+"+$frame_offset+")*$speed;\n"+
$ty+" = $a*"+$tx+"*"+$tx+" + $b*"+$tx+"+$c;";
expression -s $exp_str;
};
// Example
// createXYParabolaAnimExpression_SelectedThreePoints("pSphere1", 0.1, -30);
global proc createXYParabolaAnimExpression_SelectedThreePoints(
string $target_transform,
float $speed,
float $frame_offset
){
string $point_list[] = `ls -sl`;
if(size($point_list)<3){
print "error: Number of selected point is not enough, must be more than 3."; return;
}
float $coefs[3];
fit2dParabolaFromThreePoints(
`getAttr ($point_list[0]+".tx")`,
`getAttr ($point_list[1]+".tx")`,
`getAttr ($point_list[2]+".tx")`,
`getAttr ($point_list[0]+".ty")`,
`getAttr ($point_list[1]+".ty")`,
`getAttr ($point_list[2]+".ty")`,
$coefs
);
createXYParabolaAnimExpression($target_transform, $coefs[0], $coefs[1], $coefs[2], $speed, $frame_offset);
}