昔作った 最小二乗法で頂点等を整列する MEL スクリプト が使いづらかったので改良しました。
具体的には、以前は引数で整頓する軸を指定しなければいけなかったんですが、軸を自動で選ぶように改良しました。
ソースコード
global proc int[] findAxisesSortedByDispersion(string $targets[])
{
float $sums[3] = {0.0, 0.0, 0.0};
float $n = size($targets);
for($target in $targets)
{
float $pos[] = `xform -q -ws -t $target`;
$sums[0] += $pos[0];
$sums[1] += $pos[1];
$sums[2] += $pos[2];
}
float $averages[3] = {$sums[0] / $n, $sums[1] / $n, $sums[2] / $n};
float $dispersions[3] = {0.0, 0.0, 0.0};
for($target in $targets)
{
float $pos[] = `xform -q -ws -t $target`;
$dispersions[0] += abs($pos[0] - $averages[0]);
$dispersions[1] += abs($pos[1] - $averages[1]);
$dispersions[2] += abs($pos[2] - $averages[2]);
}
float $sorted_dispersions[] = `sort $dispersions`;
int $max_axises[3] = {0, 0, 0};
int $axis = 0;
for ($axis = 0; $axis < 3; ++$axis)
{
if ($sorted_dispersions[2] == $dispersions[$axis])
{
$max_axises[0] = $axis;
}
if ($sorted_dispersions[1] == $dispersions[$axis])
{
$max_axises[1] = $axis;
}
if ($sorted_dispersions[0] == $dispersions[$axis])
{
$max_axises[2] = $axis;
}
}
return $max_axises;
}
global proc alignToMinimumDispersionLine(string $targets[], int $axis_x, int $axis_y)
{
float $n = size($targets);
float $a, $b;
float $y, $pos[];
float $sum_x, $sum_y, $sum_xy, $sum_xx;
$sum_x = $sum_y = $sum_xy = $sum_xx = 0.0;
for($target in $targets)
{
$pos = `xform -q -ws -t $target`;
$sum_x += $pos[$axis_x];
$sum_y += $pos[$axis_y];
$sum_xy += $pos[$axis_x]*$pos[$axis_y];
$sum_xx += $pos[$axis_x]*$pos[$axis_x];
}
$slope = ($n*$sum_xy-$sum_x*$sum_y) / ($n*$sum_xx - $sum_x*$sum_x);
$offset = ($sum_xx*$sum_y-$sum_xy*$sum_x) / ($n*$sum_xx - $sum_x*$sum_x);
for($target in $targets)
{
$pos = `xform -q -ws -t $target`;
$pos[$axis_y] = $slope * $pos[$axis_x] + $offset;
xform -ws -t $pos[0] $pos[1] $pos[2] $target;
}
}
global proc alignSelectedToMinimumDispersionLine2d()
{
string $sels[] = `ls -sl`;
string $targets[] = `filterExpand -sm 31 $sels`;
int $target_axises[] = findAxisesSortedByDispersion($targets);
alignToMinimumDispersionLine($targets, $target_axises[0], $target_axises[2]);
}
global proc alignSelectedToMinimumDispersionLine1d()
{
string $sels[] = `ls -sl`;
string $targets[] = `filterExpand -sm 31 $sels`;
int $target_axises[] = findAxisesSortedByDispersion($targets);
alignToMinimumDispersionLine($targets, $target_axises[0], $target_axises[1]);
}
使用例
// 2次元平面に整列
alignSelectedToMinimumDispersionLine2d();
// 1本の線に整列
alignSelectedToMinimumDispersionLine1d();