画像を重ねる時の位置の研究(合成する)compositeImage();

Imagick::COMPOSITE_DEFAULTで指定する座標、すなわち画像を重ねる時には、重ねる画像の左上隅が座標位置になっています。下の例のように0,0で指定するとベースになる画像の0,0と重ねる画像の0,0が一致するので左上に配置されます。sample
$baseimagick = new Imagick('base.jpg');
$item1 = new Imagick('heart.png');

$baseimagick->compositeImage($item1, Imagick::COMPOSITE_DEFAULT, 0, 0);
$baseimagick->writeImage('out.jpg');

$baseimagick->destroy();
$item1->destroy();

しかしこれに回転をかけるとその座標はどの軸を中心に回ってゆくのかというところを探ってゆくと、回転している軸がぶれていて画像の合成位置が0,0で固定している筈なのに不規則になっているような感じになってしまった。
for ($i=0;$i<3;$i++) {

if ($i==0) {
$baseimagick = new Imagick('base'.$i.'.jpg');
} else {
$num = $i -1;
$baseimagick = new Imagick('base'.$num.'.jpg');
}

$item1 = new Imagick('heart1.png');

$rotate = mt_rand(0,360);
$item1->rotateImage('none', $rotate);

$baseimagick->compositeImage($item1, Imagick::COMPOSITE_DEFAULT, 0, 0);

$baseimagick->writeImage('base'.$i.'.jpg');

$baseimagick->destroy();
$item1->destroy();

}
base1どうやら画像を四角とみなしてその画像がきちんと画像内に収まるように四角の角を支点に回転をかけているのでありました。正円の画像に回転をかけると(私が予想するに)円の位置は固定されその画像の中心でローテートがかかるものだと思っていたが全然そうではないらしいです。つまり45度の倍数の角度になると中心軸は1番離れた場所になってくるということです。
もうちょっとわかりやすく長細い長方形でやってみると、中心軸がその画像の中心で回転してないことが如実にわかります。けっして画像の中心で回転しているわけではないです。こういう回転の仕方を何ていうんでしょう。Sample
となると、結局のところ時計の針のように1点の中心軸で回転するようにするには三角関数かなんか使って中心軸を求めないと駄目な感じになってきます。
Imagemagickのrotateのデフォルトはこんな風になってるんですね。

中心で画像が正確に回転するようにする

というわけで高校で習った三角関数を使って計算して中心軸を割り出してから画像を重ね合わせるというかなり面倒な計算が必要になってくるわけです。Sampleはリロードすると乱数で適当な角度がつくので理解できるかと思います。
やっていることは、回転した角度からsinθとcosθを求めて回転する中心軸のずれを画像を重ね合わせる時に補正しているんですね。compositeImageのx座標とy座標が回転角が変化するたびに同様に変化してゆくことになります。またPHPの三角関数の角度指定は度数じゃなくてラジアンなのでご注意です。
$baseimagick = new Imagick('base.jpg');
$item1 = new Imagick('item.png');

# 回転角
$rotate = mt_rand(0,360);

# 回転させる画像の大きさ
$item_width_x = 100;
$item_height_y = 100;

# 最初の座標
$orignal_axis_x = 0;
$orignal_axis_y = 0;

# 中心軸を求める
$central_axis_x = $orignal_axis_x + ($item_width_x / 2);
$central_axis_y = $orignal_axis_y + ($item_height_y / 2);

#---------------------
# 移動した中心軸を求める
#---------------------

$rech_rotate = $rotate%90;

list($cos,$sin) = axis_correction($rech_rotate, $item_width_x);
list($cos_sl,$sin_sl) = axis_correction($rech_rotate, $item_width_x/2);

$x = $orignal_axis_x + ($cos_sl + $sin_sl); # 移動した先のxの値
$y = $orignal_axis_y + ($cos_sl + $sin_sl); # 移動した先のyの値

$x_diff = $x - $central_axis_x;
$y_diff = $y - $central_axis_y;
$x_correct = ($central_axis_x - $x_diff) - ($item_width_x / 2);
$y_correct = ($central_axis_y - $y_diff) - ($item_height_y / 2);

$item1->rotateImage('none', $rotate);

$baseimagick->compositeImage($item1, Imagick::COMPOSITE_DEFAULT, $x_correct, $y_correct);
$baseimagick->writeImage('out'.$rotate.'.jpg');

$baseimagick->destroy();
$item1->destroy();

# sin cos
function axis_correction($angle, $a) {

$arg = deg2rad($angle);
$b = $a * cos($arg);
$c = $a * sin($arg);

return array($b,$c);
}