Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
23
Help us understand the problem. What is going on with this article?
@FumioNonaka

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

More than 3 years have passed since last update.

三角関数の$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;
    });
}
23
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
FumioNonaka
はなし家、もの書き、コード書き。詳しくはwebで。 担当講座: 電気通信大学ウェブシステムデザインプログラム「Web UI・UXプログラミング演習I・Ⅱ」 https://www.websys.edu.uec.ac.jp/ ロクナナワークショップ「Vue.js入門講座」 https://67.org/ws/workshop/detail/0136javascript.html

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
23
Help us understand the problem. What is going on with this article?