LoginSignup
42

More than 5 years have passed since last update.

Swiftで+や-を使ってCGPointを計算する

Posted at

タッチされた2点間の距離や方向ベクトルを計算するとき、 CGPoint をベクトルとみなして次のようにできると便利です。

let a = CGPoint(x: 1, y: 2), b = CGPoint(x: -3, y: 5)

let sum = a + b // aとbの和
let distance = (b - a).length // a、b間の距離
let direction = (b - a).unit // a→bの方向ベクトル

Swiftでは struct (構造体)に演算子を定義したり、 extension を使ってプロパティやメソッドを追加することができます。 CGPoint を次のように拡張しておくと便利です。

演算子を定義する

演算子を新たに定義する場合には、次のように、演算子の名前を持った関数を定義します。

func + (left: CGPoint, right: CGPoint) -> CGPoint {
    return CGPoint(x: left.x + right.x, y: left.y + right.y)
}

- の場合でも同じです。

* の場合は、スカラー(この場合は CGFloat )を右からかける場合と左からがあるのでオーバーロードします。

func * (left: CGPoint, right: CGFloat) -> CGPoint {
    return CGPoint(x: left.x * right, y: left.y * right)
}

func * (left: CGFloat, right: CGPoint) -> CGPoint {
    return CGPoint(x: right.x * left, y: right.y * left)
}

内積の計算もオーバーロードして定義します。戻り値の型が CGFloat なことに注意して下さい。

func * (left: CGPoint, right: CGPoint) -> CGFloat {
    return left.x * right.x + left.y * right.y
}

ひき算ではなく、 -a のように - をつけられるようにするには、 prefix キーワードを用いて演算子を定義します。

prefix func - (value: CGPoint) -> CGPoint {
    return CGPoint(x: -value.x, y: -value.y)
}

プロパティを追加する

extension を使えば、 struct に Conputational Property を追加することができます。

次のようにして、 CGPoint (をベクトルとみなした場合)の長さを得るプロパティを追加します。

extension CGPoint {
    var length: CGFloat {
        get {
            return sqrt(self.x * self.x + self.y * self.y)
        }
    }
}

単位ベクトルを得るプロパティも定義しておくと便利です。

extension CGPoint {
    var unit: CGPoint {
        get {
            return self * (1.0 / self.length)
        }
    }
}

メソッドを追加する

プロパティだけでなく、メソッドを追加することもできます。

ベクトルのなす角を計算するメソッドを追加してみましょう。ベクトルのなす角については

\cos \theta = \frac{\bf{a} \cdot \bf{b}}{|\bf{a}| |\bf{b}|}

が成り立つので、次のようにメソッドを定義します。

extension CGPoint {
    func angleFrom(point: CGPoint) -> CGFloat {
        return acos(fmin(fmax(self * point / (self.length * point.length), -1.0), 1.0))
    }
}

fminfmax は、浮動小数点数の計算誤差で 1.0-1.0 をわずかに超えてしまう場合への対処です。

GitHub

せっかくなので、 GitHubに公開しました。 CGPoint+Vector.swift をプロジェクトに追加するだけで使えます。

まとめ

Swiftでは struct に演算子やプロパティ、メソッドを追加することができます。 CGPoint をベクトルとして計算をすることは多いので、 +- の演算子や、 length などのプロパティを追加してみました。

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
42