【Swift】三角比で辺の長さや角度を求める

はじめに

直角三角形で隣辺 (底辺) と角度 (θ) がわかる時に対辺 (高さ) を求めたいといったアレです。

アプリ内で図形のお絵描きをする際によく忘れるのでまとめます。

開発環境 Xcode 13.2 / Swift 5.5.2

定義

名称の確認。

コード

Playgroundで動かせます。

下の方にある point〜という関数は、各値から円周上の座標 (CGPoint) を一度に取得したい時用です。

import UIKit

/// Convert Degree to Radian
func radian(_ degree: CGFloat) -> CGFloat {
    degree * .pi / 180
}

/// Convert Radian to Degree
func degree(_ radian: CGFloat) -> CGFloat {
    radian * 180 / .pi
}

/// Find the Angle by using the given Adjacent and Hypotenuse
func angle(adjacent: CGFloat, hypotenuse: CGFloat) -> CGFloat {
    acos(adjacent / hypotenuse)
}

/// Find the Angle by using the given Opposite and Hypotenuse
func angle(opposite: CGFloat, hypotenuse: CGFloat) -> CGFloat {
    asin(opposite / hypotenuse)
}

/// Find the Angle by using the given Adjacent and Opposite
func angle(adjacent: CGFloat, opposite: CGFloat) -> CGFloat {
    atan2(opposite, adjacent)
}

/// Find the Adjacent by using the given Opposite and Angle
func adjacent(opposite: CGFloat, angle: CGFloat) -> CGFloat {
    opposite / tan(angle)
}

/// Find the Adjacent using by the given Hypotenuse and Angle
func adjacent(hypotenuse: CGFloat, angle: CGFloat) -> CGFloat {
    hypotenuse * cos(angle)
}

/// Find the Opposite by using the given Adjacent and Angle
func opposite(adjacent: CGFloat, angle: CGFloat) -> CGFloat {
    adjacent * tan(angle)
}

/// Find the Opposite by using the given Hypotenuse and Angle
func opposite(hypotenuse: CGFloat, angle: CGFloat) -> CGFloat {
    hypotenuse * sin(angle)
}

/// Find the Hypotenuse by using the given Adjacent and Angle
func hypotenuse(adjacent: CGFloat, angle: CGFloat) -> CGFloat {
    adjacent / cos(angle)
}

/// Find the Hypotenuse by using the given Opposite and Angle
func hypotenuse(opposite: CGFloat, angle: CGFloat) -> CGFloat {
    opposite / sin(angle)
}

/// Find the point by using the given Adjacent and Angle
func point(adjacent: CGFloat, angle: CGFloat) -> CGPoint {
    let y = opposite(adjacent: adjacent, angle: angle)
    return CGPoint(x: adjacent, y: y)
}

/// Find the point by using the given Opposite and Angle
func point(opposite: CGFloat, angle: CGFloat) -> CGPoint {
    let x = adjacent(opposite: opposite, angle: angle)
    return CGPoint(x: x, y: opposite)
}

/// Find the point by using the given Hypotenuse and Angle
func point(hypotenuse: CGFloat, angle: CGFloat) -> CGPoint {
    let x = adjacent(hypotenuse: hypotenuse, angle: angle)
    let y = opposite(hypotenuse: hypotenuse, angle: angle)
    return CGPoint(x: x, y: y)
}

/// Find the point by using the given Adjacent and Hypotenuse
func point(adjacent: CGFloat, hypotenuse: CGFloat) -> CGPoint {
    let angle = angle(adjacent: adjacent, hypotenuse: hypotenuse)
    let y = opposite(adjacent: adjacent, angle: angle)
    return CGPoint(x: adjacent, y: y)
}

/// Find the point by using the given Opposite and Hypotenuse
func point(opposite: CGFloat, hypotenuse: CGFloat) -> CGPoint {
    let angle = angle(opposite: opposite, hypotenuse: hypotenuse)
    let x = adjacent(opposite: opposite, angle: angle)
    return CGPoint(x: x, y: opposite)
}

検証

Playgroundに引き続き以下を書いて動かしてみます。

値は角度60°、隣辺 : 斜辺 : 対辺 = 1 : 2 : √3 の直角三角形。

let adjacent: CGFloat = 1
let opposite: CGFloat = sqrt(3)
let hypotenuse: CGFloat = 2
let angle: CGFloat = radian(60)
print("adjacent = \(adjacent)")
print("opposite = \(opposite)")
print("hypotenuse = \(hypotenuse)")
print("60 deg = \(angle) rad")
print("angle(adjacent, opposite)  = \(angle(adjacent: adjacent, opposite: opposite))")
print("angle(adjacent, hypotenuse)  = \(angle(adjacent: adjacent, hypotenuse: hypotenuse))")
print("angle(opposite, hypotenuse)  = \(angle(opposite: opposite, hypotenuse: hypotenuse))")
print("adjacent(opposite, angle)  = \(adjacent(opposite: opposite, angle: angle))")
print("adjacent(hypotenuse, angle)  = \(adjacent(hypotenuse: hypotenuse, angle: angle))")
print("opposite(adjacent, angle)  = \(opposite(adjacent: adjacent, angle: angle))")
print("opposite(hypotenuse, angle)  = \(opposite(hypotenuse: hypotenuse, angle: angle))")
print("hypotenuse(adjacent, angle)  = \(hypotenuse(adjacent: adjacent, angle: angle))")
print("hypotenuse(opposite, angle)  = \(hypotenuse(opposite: opposite, angle: angle))")
print("point(adjacent, angle)  = \(point(adjacent: adjacent, angle: angle))")
print("point(opposite, angle)  = \(point(opposite: opposite, angle: angle))")
print("point(hypotenuse, angle)  = \(point(hypotenuse: hypotenuse, angle: angle))")
print("point(adjacent, hypotenuse)  = \(point(adjacent: adjacent, hypotenuse: hypotenuse))")
print("point(opposite, hypotenuse)  = \(point(opposite: opposite, hypotenuse: hypotenuse))")

これを実行すると以下のような結果が出力されました。

adjacent = 1.0
opposite = 1.7320508075688772
hypotenuse = 2.0
60 deg = 1.0471975511965976 rad
angle(adjacent, opposite)  = 1.0471975511965976
angle(adjacent, hypotenuse)  = 1.0471975511965976
angle(opposite, hypotenuse)  = 1.0471975511965976
adjacent(opposite, angle)  = 1.0000000000000002
adjacent(hypotenuse, angle)  = 1.0000000000000002
opposite(adjacent, angle)  = 1.7320508075688767
opposite(hypotenuse, angle)  = 1.7320508075688772
hypotenuse(adjacent, angle)  = 1.9999999999999996
hypotenuse(opposite, angle)  = 2.0
point(adjacent, angle)  = (1.0, 1.7320508075688767)
point(opposite, angle)  = (1.0000000000000002, 1.7320508075688772)
point(hypotenuse, angle)  = (1.0000000000000002, 1.7320508075688772)
point(adjacent, hypotenuse)  = (1.0, 1.7320508075688767)
point(opposite, hypotenuse)  = (1.0000000000000002, 1.7320508075688772)

👈 ヨシッ!

参考リンク

・三角関数 – ウィキペディア
https://ja.wikipedia.org/wiki/%E4%B8%89%E8%A7%92%E9%96%A2%E6%95%B0

おわりに

過去を振り返ると、何年かごとにお絵描きが必要なアプリをやることになり、そのたびに今回のようなことを調べてコードを書いていた気がします。

もっと早くブログをやって自分用にまとめていたらと思いました。

同じような誰かのご参考になれば幸いです。