LoginSignup
45
35

More than 5 years have passed since last update.

三角関数で角度から座標を導くふたつの式の使い途

Last updated at Posted at 2018-04-09

三角関数の$sin$と$cos$を使うと、角度から座標を求めることができます。おもに用いられるのは、ふたつの方程式です。それぞれがどのようなところで、どのように使われるのかをご説明します。

三角関数で角度から座標を定めるふたつの方程式

まずは、ふたつの方程式を以下に示しましょう。第1は、原点$(0, 0)$からの距離$r$と$x$軸正方向となす角度$\theta$から座標$(x, y)$を求めます。

x = r\cos\theta\\
y = r\sin\theta

第2は、座標$(x, y)$を原点$(0, 0)$から角度$\theta$回して、新たな座標$(x', y')$を導く式です。

x' = x\cos\theta - y\sin\theta\\
y' = x\sin\theta + y\cos\theta

原点からの距離と角度で座標を定める ー 極座標

第1の方程式は、三角関数の定義にもとづきます。半径1の円(単位円)の円周上の点$P(x, y)$と原点$O$を結ぶ$OA$が$x$軸の正方向となす角度を$\theta$としたとき、座標$(x, y)$はつぎのように定められています。

x = \cos\theta\\
y = \sin\theta

三角関数のsinとcos

図001

すると、原点が$(x_o, y_o)$で距離は$r$、角度が$\theta$のときは、座標$(x, y)$はつぎの式で表されます。距離と角度からレーダーのように定める座標は「極座標」と呼ばれます。

x = r\cos\theta + x_o\\
y = r\sin\theta + y_o

座標を原点から一定角回した新たな座標も計算できます。まず、座標の原点からの距離および$x$軸となす角度を求めます。つぎに、距離はそのまま、回す角度を足し込んで導けばよいのです。

JavaScriptコードで書くなら、つぎのとおりです。なお、ECMAScript 2015のMath.hypot()メソッドは、座標の原点からの距離を返します。

const r = Math.hypot(x, y);
const angle = Math.atan2(y, x);
const newX = r * Math.cos(angle + rotation);
const newY = r * Math.sin(angle + rotation);

座標を原点から決められた角度回す

座標を原点から決められた角度回す場合には、第2の方程式を使う方が無駄な手間は省けます。もとの座標の原点からの距離も角度も求めなくて済むからです。とくに、たくさんの座標を同じ角度回すときなら、$sin$と$cos$の値は一度計算すれば使い回せるので、さらにお得になります(「任意の座標を原点から指定した角度回す」参照)。

x' = x\cos\theta - y\sin\theta\\
y' = x\sin\theta + y\cos\theta

原点が$(x_o, y_o)$のときは、それらの値を$(x, y)$座標から差し引いて回し、そのあとで原点座標を足し込みます。

x' = (x - x_o)\cos\theta - (y - y_o)\sin\theta + x_o\\
y' = (x - x_o)\sin\theta + (y - y_o)\cos\theta + y_o

三角関数のふたつの式を使った作例

つぎのjudo.itの作例はふたつの方程式を使ってみました。CreateJSを用いたアニメーションです。ウィンドウ内をクリックするたびに、円がランダムに置かれて、中心から回ります。

ランダムに置いた円を回す

1804002_001.png
>> jsdo.itへ

円の配置は、中心からの距離と角度をランダムに決めて、第1の方程式で定めました。距離には範囲を定めて、円は中心近くには置かず、真ん中は空白にしています。

function getPolar(r, angle, center) {
    const x = r * Math.cos(angle) + center.x;
    const y = r * Math.sin(angle) + center.y;
    return {x: x, y: y};
}

多くの座標を同じ角度回すときは、第2の方程式がお得でした。$cos$と$sin$の値ははじめに求め、それをすべての座標計算に使い回しています。引数に受け取る複数の座標は、配列に納められている前提です。

function rotatePoints(points, angle, center) {
    const cos = Math.cos(angle);
    const sin = Math.sin(angle);
    points.forEach((point) => {
        const x = point.x - center.x;
        const y = point.y - center.y;
        point.x = x * cos - y * sin + center.x;
        point.y = x * sin + y * cos + center.y;
    });
}
45
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
35