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

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

新規登録して質問してみよう
ただいま回答率
85.48%
iOS

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

Xcode

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

Swift

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

Q&A

解決済

2回答

626閲覧

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

bilieikbilibili

総合スコア37

iOS

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

Xcode

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

Swift

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

0グッド

0クリップ

投稿2018/05/07 06:34

編集2018/05/07 08:08

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

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

イメージ説明

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

swift

1 2func drawing(){ 3 4 let a_x:Double! = Double(currentLocation.x) //パンドラッグ中に取得できるタップ位置X(pan changed) 5 let a_y:Double! = Double(currentLocation.y) //パンドラッグ中に取得できるタップ位置Y(pan changed) 6 let p_x:Double! = Double(previousLocation.x) //パン開始時に取得できるタップ位置X(pan began) 7 let p_y:Double! = Double(previousLocation.y) //パン開始時に取得できるタップ位置Y(pan began) 8 let o_x:Double! = Double(objectLocation.x) //図形の中心位置X 9 let o_y:Double! = Double(objectLocation.y) //図形の中心位置Y 10 var x_r:Double! = 0 //パン開始時の図形とタップ位置の距離 11 var y_r:Double! = 0 //ドラッグ時の図形とタップ位置の距離 12 let o_θ:Double! = Double(object_Rotate) //角度 13 var x_x:Double! = 0 //path.move関数の位置X 14 var x_y:Double! = 0 //path.move関数の位置Y 15 var y_x:Double! = 0 //path.addLine関数の位置X 16 var y_y:Double! = 0 //path.addLine関数の位置Y 17 18 x_r = sqrt(pow((p_x - o_x), 2.0) + pow((p_y - o_y), 2.0)) //パン開始時の図形とタップ位置との距離を算出 19 x_y = sin(o_θ) * x_r //三角関数を用いた描画位置Y 20 x_x = cos(o_θ) * x_r //三角関数を用いた描画位置X 21 22 y_r = sqrt(pow((a_x - o_x), 2.0) + pow((a_y - o_y), 2.0)) //ドラッグ時の図形とタップ位置との距離を算出 23 y_y = sin(o_θ) * y_r 24 y_x = cos(o_θ) * y_r 25 26 let path: UIBezierPath = UIBezierPath() 27 28 path.move(to: CGPoint.init(x: x_x + o_x, y: x_y + o_y)) //描画 29 path.addLine(to: CGPoint.init(x: y_x + o_x, y: y_y + o_y)) //描画 30 let layer = CAShapeLayer() 31 32 layer.strokeColor = UIColor.orange.cgColor 33 layer.fillColor = UIColor.clear.cgColor 34 35 layer.addSublayer(layer) 36 37 setNeedsDisplay() 38}

-2018 5 /7 16:39 追記-

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

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

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

イメージ説明

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2018/05/07 06:58

このコードで何らかの線は描画されているのでしょうか?
bilieikbilibili

2018/05/07 07:10

コメントありがとうございます。 描画はされているようです。いまどのような状態か画像を追加しますので少々お待ちください。
fuzzball

2018/05/07 07:13

その画像の3つの座標と角度も併せて書いていただけると動作確認しやすいです。
fuzzball

2018/05/07 07:49

弧度法=radian, 度=degreeかと思いますが‥。
bilieikbilibili

2018/05/07 08:08

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

2018/05/07 08:30

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

回答2

0

swift

1func nearest(A: CGPoint, B: CGPoint, P: CGPoint) -> CGPoint { 2 let a = CGVector(dx: B.x - A.x, dy: B.y - A.y) 3 let b = CGVector(dx: P.x - A.x, dy: P.y - A.y) 4 let r = (a.dx * b.dx + a.dy * b.dy) / (a.dx * a.dx + a.dy * a.dy) 5 return CGPoint(x: A.x + r * a.dx, y: A.y + r * a.dy) 6} 7 8let O = objectLocation 9let rot = object_Rotate 10let P1 = previousLocation 11let P2 = currentLocation 12 13let A = CGPoint(x: O.x - cos(rot), y: O.y - sin(rot)) 14let B = CGPoint(x: O.x + cos(rot), y: O.y + sin(rot)) 15 16let p1 = nearest(A: A, B: B, P: P1) 17let p2 = nearest(A: A, B: B, P: P2)

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

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

投稿2018/05/09 08:23

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bilieikbilibili

2018/05/10 14:48

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

0

自己解決

自己解決しました。

数学的に必要な公式としては
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 04:15

bilieikbilibili

総合スコア37

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2018/05/09 05:55

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問