どのように伝えるかどうかは右または左側のライン
-
21-09-2019 - |
質問
をセットにした点です。たい分けて2つの異なる。このためには、選べる二つのポイント(a や b やが描く、想像上のとします。現したいすべてのポイントは左からこのオールインワンセット、および右からこの線にその他のセットです。
どのように伝えれる点 z かどうかを左右す。また計算となり a-z-b –角度比180、右側では、以上の180左側にあるものの定義ArcCos、算出した角度は常に以下180°となっています。ある計算式の角度を超え180°(またはその他の式を選択するには右または左側)?
解決
使用(AB,AM)
は、クエリ点であるベクトルM(X,Y)
の決定、の符号ます:
position = sign((Bx - Ax) * (Y - Ay) - (By - Ay) * (X - Ax))
これは、ライン上の0
、片側に+1
、他方側-1
である。
他のヒント
外積するを利用し、このコードを試してみてください。
public bool isLeft(Point a, Point b, Point c){
return ((b.X - a.X)*(c.Y - a.Y) - (b.Y - a.Y)*(c.X - a.X)) > 0;
}
A =ラインポイント1。 B =ラインポイント2。 のC の=に対してチェックするポイントます。
式が0に等しい場合、点は同一直線上にあります。
線が水平である場合、点がライン上にある場合、この戻り真
は、
の行列式の看板を見て| x2-x1 x3-x1 |
| y2-y1 y3-y1 |
これは(ライン自体の点に対して、ゼロ)一面上の点について陽性、他方で負になります。
ベクトル(y1 - y2, x2 - x1)
が線に垂直であり、常に右向き(あなた面方位が鉱山から異なる場合、または常にが、左ポインティング)。
は、次に垂直ベクトル(内積> (x3 - x1, y3 - y1)
)として線の同じ側の場合の点が位置を決定するために、そのベクトルと0
のドット積を計算するか、することができない。
私は、Javaでこれを実現し、ユニットテスト(以下ソース)を実行しました。上記の解決策の作業のなし。このコードは、ユニットテストに合格します。誰もが通過しないユニットテストを見つけた場合、私に知らせてくださいます。
コード:注:真nearlyEqual(double,double)
戻りは2つの数字が非常に接近している場合は、
/*
* @return integer code for which side of the line ab c is on. 1 means
* left turn, -1 means right turn. Returns
* 0 if all three are on a line
*/
public static int findSide(
double ax, double ay,
double bx, double by,
double cx, double cy) {
if (nearlyEqual(bx-ax,0)) { // vertical line
if (cx < bx) {
return by > ay ? 1 : -1;
}
if (cx > bx) {
return by > ay ? -1 : 1;
}
return 0;
}
if (nearlyEqual(by-ay,0)) { // horizontal line
if (cy < by) {
return bx > ax ? -1 : 1;
}
if (cy > by) {
return bx > ax ? 1 : -1;
}
return 0;
}
double slope = (by - ay) / (bx - ax);
double yIntercept = ay - ax * slope;
double cSolution = (slope*cx) + yIntercept;
if (slope != 0) {
if (cy > cSolution) {
return bx > ax ? 1 : -1;
}
if (cy < cSolution) {
return bx > ax ? -1 : 1;
}
return 0;
}
return 0;
}
ここでユニットテストがあります:
@Test public void testFindSide() {
assertTrue("1", 1 == Utility.findSide(1, 0, 0, 0, -1, -1));
assertTrue("1.1", 1 == Utility.findSide(25, 0, 0, 0, -1, -14));
assertTrue("1.2", 1 == Utility.findSide(25, 20, 0, 20, -1, 6));
assertTrue("1.3", 1 == Utility.findSide(24, 20, -1, 20, -2, 6));
assertTrue("-1", -1 == Utility.findSide(1, 0, 0, 0, 1, 1));
assertTrue("-1.1", -1 == Utility.findSide(12, 0, 0, 0, 2, 1));
assertTrue("-1.2", -1 == Utility.findSide(-25, 0, 0, 0, -1, -14));
assertTrue("-1.3", -1 == Utility.findSide(1, 0.5, 0, 0, 1, 1));
assertTrue("2.1", -1 == Utility.findSide(0,5, 1,10, 10,20));
assertTrue("2.2", 1 == Utility.findSide(0,9.1, 1,10, 10,20));
assertTrue("2.3", -1 == Utility.findSide(0,5, 1,10, 20,10));
assertTrue("2.4", -1 == Utility.findSide(0,9.1, 1,10, 20,10));
assertTrue("vertical 1", 1 == Utility.findSide(1,1, 1,10, 0,0));
assertTrue("vertical 2", -1 == Utility.findSide(1,10, 1,1, 0,0));
assertTrue("vertical 3", -1 == Utility.findSide(1,1, 1,10, 5,0));
assertTrue("vertical 3", 1 == Utility.findSide(1,10, 1,1, 5,0));
assertTrue("horizontal 1", 1 == Utility.findSide(1,-1, 10,-1, 0,0));
assertTrue("horizontal 2", -1 == Utility.findSide(10,-1, 1,-1, 0,0));
assertTrue("horizontal 3", -1 == Utility.findSide(1,-1, 10,-1, 0,-9));
assertTrue("horizontal 4", 1 == Utility.findSide(10,-1, 1,-1, 0,-9));
assertTrue("positive slope 1", 1 == Utility.findSide(0,0, 10,10, 1,2));
assertTrue("positive slope 2", -1 == Utility.findSide(10,10, 0,0, 1,2));
assertTrue("positive slope 3", -1 == Utility.findSide(0,0, 10,10, 1,0));
assertTrue("positive slope 4", 1 == Utility.findSide(10,10, 0,0, 1,0));
assertTrue("negative slope 1", -1 == Utility.findSide(0,0, -10,10, 1,2));
assertTrue("negative slope 2", -1 == Utility.findSide(0,0, -10,10, 1,2));
assertTrue("negative slope 3", 1 == Utility.findSide(0,0, -10,10, -1,-2));
assertTrue("negative slope 4", -1 == Utility.findSide(-10,10, 0,0, -1,-2));
assertTrue("0", 0 == Utility.findSide(1, 0, 0, 0, -1, 0));
assertTrue("1", 0 == Utility.findSide(0,0, 0, 0, 0, 0));
assertTrue("2", 0 == Utility.findSide(0,0, 0,1, 0,2));
assertTrue("3", 0 == Utility.findSide(0,0, 2,0, 1,0));
assertTrue("4", 0 == Utility.findSide(1, -2, 0, 0, -1, 2));
}
を使用 方程式の線 ab, のx座標(ワールド座標系の線のy座標(ワールド座標系としてのポイントが並びます。
- まるならポイントのx>のx線を右に。
- まるならポイントの x < ラインのx、ポイントは左側のライン。
- まるならポイントのx==ラインのxの点はしたものである。
まずチェック
if (x2-x1) == 0
if x3 < x2
it's on the left
if x3 > x2
it's on the right
else
it's on the line
次に、勾配を計算する:m = (y2-y1)/(x2-x1)
y - y1 = m*(x-x1) + y1
:はその後、点スロープフォームを使用して線の方程式を作成します。私の説明のために、(あなたのアルゴリズムでは必要ありません)スロープ - インターセプトフォームにそれを簡素化:。y = mx+b
今(x3, y3)
とx
ためy
に差し込みます。ここでどうするかを詳述いくつかの擬似コードがあります:
if m > 0
if y3 > m*x3 + b
it's on the left
else if y3 < m*x3 + b
it's on the right
else
it's on the line
else if m < 0
if y3 < m*x3 + b
it's on the left
if y3 > m*x3+b
it's on the right
else
it's on the line
else
horizontal line; up to you what you do
基本的に、私ははるかに簡単で単純です解決策があると思い、任意の多角形のために、多角形で両極端の反対の頂点を見つけ、4つの頂点(P1、P2、P3、P4)で構成されて言うことができます別の言葉で、例えば最も左上の頂点(例えばP1とすることができ)、最も右下の(発言権をすることができます)に配置され、反対の頂点を見つけます。したがって、あなたのテストの点C(x、y)が与えられ、今では、CおよびC p1との間に二重チェックをしなければならないとP4ます:
もしCX> P1X AND CY> P1Y ==> Cが低いとP1の右側にあることを意味 次 Cは、上部およびP4
の左側にあることもしCX結論として、Cが矩形の内側にある。
感謝:)
のポイントを仮定している(アックス、Ayの)(BX、別)及び(Cxと、Cyは)、あなたは計算する必要があります。
(Bxを - AX)*(サイ - Ayの) - (BY - Ayの)*(Cxの - AX)
これは、点Cが点AとBにより形成されたライン上にある場合は、ゼロに等しくなり、側面に依存して異なる符号を有することになります。どちら側これはあなたの座標(x、y)の向きに依存しますが、負の値は左または右にあるかどうかを決定するために、この式にA、BおよびCのための試験値をプラグインすることができます。
@ AVBの答え
det = Matrix[
[(x2 - x1), (x3 - x1)],
[(y2 - y1), (y3 - y1)]
].determinant
det
は、その下の負の場合、その上で正である場合。 0であれば、そのライン上ます。
ここでもClojureの中に書かれた外積のロジックを使用して、バージョンです。
(defn is-left? [line point]
(let [[[x1 y1] [x2 y2]] (sort line)
[x-pt y-pt] point]
(> (* (- x2 x1) (- y-pt y1)) (* (- y2 y1) (- x-pt x1)))))
使用例:
(is-left? [[-3 -1] [3 1]] [0 10])
true
点(0、10)線の左側にあるということであるは(-3、-1)によって決定され、(3,1)。
注:この実装は、他のどれもが、(今のところ)行わないという問題を解決します!ラインを決定するポイントを与えたときの注文は、の問題になります。すなわち、それはある意味では、「有向ライン」です。したがって、上記のコードで、この呼び出しもtrue
の結果を生成します:
(is-left? [[3 1] [-3 -1]] [0 10])
true
ので、このコードのスニペットのその者:
(sort line)
は最後に、他のクロス積ベースのソリューションと同様に、この解決策は、ブール値を返し、共線のための第三の結果を与えません。しかし、それは感覚、例えばになる結果が得られます:ます。
(is-left? [[1 1] [3 1]] [10 1])
false
私は物理学に触発された溶液を提供したかったです。
線に沿って加えられる力を想像して、あなたは、ポイントについての力のトルクを測定しています。トルク(反時計回り)が正である場合、点は線の「左」であるが、トルクが負である場合、点は線の「右」である。
だから力ベクトルは、
の行を定義する2点のスパンと等しい場合fx = x_2 - x_1
fy = y_2 - y_1
次のテストの符号に基づいてポイント(px,py)
の側面のためのあなたのテスト
var torque = fx*(py-y_1)-fy*(px-x_1)
if torque>0 then
"point on left side"
else if torque <0 then
"point on right side"
else
"point on line"
end if
代替多種多様なレストランがたくさんの気分解によるnettersはあまり聞きとれない形状に影響を与えるおそれの
ましょう pqr=[P、Q、R】ポイントを形成する平面で2分割面による線 [P、R].またすぐの場合はポイント pqr 平面、A、B、同じ側となります。
の任意の点 T にpqr面を表現できる2つのベクトル: v =P-Q u =R-Q:
T'=T-Q= i *v+ j *u
現在の形状の影響:
- i+j=1:T pr線
- i+j <1:T Sq
- i+j>1:T Snq
- i+j=0の場合T=Q
- i+j <0:T SqえQ.
i+j: <0 0 <1 =1 >1
---------Q------[PR]--------- <== this is PQR plane
^
pr line
一般に、
- i+j度からは離れてからはライン[P、R], は、
- の看板 i+j-1 エネルギーに変換T sideness.
その他の幾何学の意義 i や j (関係のないこのソリューション)は次のとおりです。
- i,j のscalars T新しい座標系が v u の新しい軸 Q の起源;
- i, j として見ることができ <url> <url> <url> <url> <url> <url> <url> <url> のための P R, ます。大きな i, の遠Tは親元を離れてやってきました R (大から引 P).
の値 i,j 取得できる解決の方程式:
i*vx + j*ux = T'x
i*vy + j*uy = T'y
i*vz + j*uz = T'z
それが自分たちに与えられた2点、A、B面:
A = a1 * v + a2 * u
B = b1 * v + b2 * u
場合、Bは同じ側に、true:
sign(a1+a2-1) = sign(b1+b2-1)
なお、この適用にも質問 はA、Bの側面の[P、Q、R], る:
T= i *P+ j *Q+ k *R
や i+j+k=1 このTの平面[P、Q、R】の看板 i+j+k-1 とそのsideness.このことからまで:
A = a1 * P + a2 * Q + a3 * R
B = b1 * P + b2 * Q + b3 * R
A、Bと同一の側面の[P、Q、R]の場合
sign(a1+a2+a3-1) = sign(b1+b2+b3-1)