質問

をセットにした点です。たい分けて2つの異なる。このためには、選べる二つのポイント(ab やが描く、想像上のとします。現したいすべてのポイントは左からこのオールインワンセット、および右からこの線にその他のセットです。

どのように伝えれる点 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

現在の形状の影響:

  1. i+j=1:T pr線
  2. i+j <1:T Sq
  3. i+j>1:T Snq
  4. i+j=0の場合T=Q
  5. 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.

その他の幾何学の意義 ij (関係のないこのソリューション)は次のとおりです。

  • 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)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top