1. Qiita
  2. 投稿
  3. Swift

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

  • 36
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

タッチされた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 などのプロパティを追加してみました。

Comments Loading...