質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.85%

  • Swift

    6322questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Xcode

    3647questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

  • iOS

    3587questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

UIBezierPathを使って描画したいが、位置の計算が合わない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 91

ほぼ数学の問題のようになってますが、回答をお願いします。

私の書いたコードでは、タップした座標点、角度、原点との距離などを計算して画像内の薄い紫色の直線上にUIBezierPathを描画していくものを書いたつもりだったのですが、自分の計算式が間違えているようなので、どうすれば画像のような理想的な位置に直線を描くことができるのか教えてください。

イメージ説明

画像内で出ている変数等は全てコードに書きました。

func drawing(){

    let a_x:Double! = Double(currentLocation.x) //パンドラッグ中に取得できるタップ位置X(pan changed)
    let a_y:Double! = Double(currentLocation.y) //パンドラッグ中に取得できるタップ位置Y(pan changed)
    let p_x:Double! = Double(previousLocation.x) //パン開始時に取得できるタップ位置X(pan began)
    let p_y:Double! = Double(previousLocation.y) //パン開始時に取得できるタップ位置Y(pan began)
    let o_x:Double! = Double(objectLocation.x) //図形の中心位置X
    let o_y:Double! = Double(objectLocation.y) //図形の中心位置Y
    var x_r:Double! = 0 //パン開始時の図形とタップ位置の距離
    var y_r:Double! = 0 //ドラッグ時の図形とタップ位置の距離
    let o_θ:Double! = Double(object_Rotate) //角度
    var x_x:Double! = 0 //path.move関数の位置X
    var x_y:Double! = 0 //path.move関数の位置Y
    var y_x:Double! = 0 //path.addLine関数の位置X
    var y_y:Double! = 0 //path.addLine関数の位置Y

    x_r = sqrt(pow((p_x - o_x), 2.0) + pow((p_y - o_y), 2.0)) //パン開始時の図形とタップ位置との距離を算出
    x_y = sin(o_θ) * x_r //三角関数を用いた描画位置Y
    x_x = cos(o_θ) * x_r //三角関数を用いた描画位置X

    y_r = sqrt(pow((a_x - o_x), 2.0) + pow((a_y - o_y), 2.0)) //ドラッグ時の図形とタップ位置との距離を算出
    y_y = sin(o_θ) * y_r
    y_x = cos(o_θ) * y_r

    let path: UIBezierPath = UIBezierPath()

    path.move(to: CGPoint.init(x: x_x + o_x, y: x_y + o_y)) //描画
    path.addLine(to: CGPoint.init(x: y_x + o_x, y: y_y + o_y)) //描画
    let layer = CAShapeLayer()

    layer.strokeColor = UIColor.orange.cgColor
    layer.fillColor = UIColor.clear.cgColor

    layer.addSublayer(layer)

    setNeedsDisplay()
}

-2018 5 /7 16:39 追記-

現状描画自体は正常に動作しています。
計算が違うようなのですが、現在どういう動作をしているのかを載せていませんでした。

具体的には下記画像のような状態です。
画像内では2パターン動作をテストしています。(青と赤)
どちらも角度だけは変えていません。

しかし、初期タップ位置と原点との距離に応じて、描画される線と原点との距離が比例して離れてしまいます。

イメージ説明

(また、画像内の角度については弧度法(π)での値に直しています。degreeと書いてありますが、radianです。)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • bilieikbilibili

    2018/05/07 16:52

    すいません、修正しました。

    キャンセル

  • bilieikbilibili

    2018/05/07 17:08

    すいません、原点の座標が未記入だったため追記しました。

    キャンセル

  • fuzzball

    2018/05/07 17:30

    sin/cosでは、垂線との交点ではなく、円弧との交点になるのでは?

    キャンセル

回答 2

check解決した方法

+1

自己解決しました。

数学的に必要な公式としては
y-y1=m(x-x1)でした。
ようは、角度と1点を通る直線の式を求める公式になります。
m角度はtan(degree or radian)になります。

手順としては、原点と角度を入れた式を作ります。
垂線の足の座標を求めればそこが描画位置になるので、任意の点と角度(垂線なので、tan(θ)m = -1)を入れ、連立方程式にしてx or yをときます。あとは、どちらかの式に代入してyを求め、終了です。

キーマンは
y-y1=m(x-x1)と、垂線の交点の座標が描画位置になるということです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/09 14:55

    内積でも求められるのでぜひ。

    キャンセル

+1

func nearest(A: CGPoint, B: CGPoint, P: CGPoint) -> CGPoint {
    let a = CGVector(dx: B.x - A.x, dy: B.y - A.y)
    let b = CGVector(dx: P.x - A.x, dy: P.y - A.y)
    let r = (a.dx * b.dx + a.dy * b.dy) / (a.dx * a.dx + a.dy * a.dy)
    return CGPoint(x: A.x + r * a.dx, y: A.y + r * a.dy)
}

let O = objectLocation
let rot = object_Rotate
let P1 = previousLocation
let P2 = currentLocation

let A = CGPoint(x: O.x - cos(rot), y: O.y - sin(rot))
let B = CGPoint(x: O.x + cos(rot), y: O.y + sin(rot))

let p1 = nearest(A: A, B: B, P: P1)
let p2 = nearest(A: A, B: B, P: P2)

この記事のコードを一部変更して使わせていただきました。
図形情報を扱うのに大事なことは、全部高校で教わった

全然テストしてないので悪しからず‥。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/10 23:48

    これはとてもわかりやすい式ですね
    ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.85%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Swift

    6322questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • Xcode

    3647questions

    Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

  • iOS

    3587questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。