2009-05-25 2 views
18

ポイントが特定の行に属しているかどうかを確認するにはどうすればよいですか?可能であれば、実施例は理解される。別ウィンドウ(タブ)の大きな表示で見るポイントが特定の行に属しているかどうかを確認するにはどうすればよいですか?

+0

具体的にしてください。どのような情報から始めなければなりませんか?あなたは点と方程式の順序付けられたペアを持っていますか? –

答えて

28

当てはまる場合点(X1、Y1)をチェックすることにより、ライン上にあるかどうかを決定することができるが座標を線方程式に差し込み、等価性をチェックするだけです。

は考える:XとYで

Point p (X=4, Y=5) 
Line l (Slope=1, YIntersect=1) 

プラグ:

Y = Slope * X + YIntersect 
=> 5 = 1 * 4 + 1 
=> 5 = 5 

そうです、ポイントはライン上にあります。あなたのラインが(X1、Y1)、(X2、Y2)の形で表現されている場合

、その後、あなたが斜面を計算することができます。

Slope = (y1 - y2)/(x1-x2) 

そしてこれにY-交差を得る:

YIntersect = - Slope * X1 + Y1; 

編集:私はあなたがx1 - x20ではないことを確認する必要があります

(X1/Y1されている...)Y-交差を固定しました。そうであれば、そのポイントがライン上にあるかどうかを確認することは、あなたのポイントのY値がx1またはx2のいずれかに等しいかどうかをチェックすることです。また、ポイントのXが 'x1'または 'x2'でないことを確認します。

+0

これはどの言語ライブラリですか? –

+2

それはそうではありません - それは単なる擬似コードです。 – Eclipse

+23

これは擬似コードではなく、数学だけです。 – configurator

0

もっと具体的になりますか?

どのようなプログラミング言語について話していますか?

あなたはどのような環境について話していますか?

どのような "ライン"について話していますか?テキスト?何がポイント?画面上のXY?

+1

これは私が元の質問にコメントしたはずです – joshcomley

+5

投稿を削除してコメントを投稿することもできます:) –

4
y = m * x + c 

これは線の式です。 x & yは座標です。各線はその勾配(m)とそれがy軸(c)と交差するところで特徴づけられる。

そこでラインのM & C所与、あなたは式は最も単純な形態では、X = X1及びY = Y1

+0

この方程式は垂直線を表すことはできませんが、ラインの厚さがゼロでない。 – ChrisW

+4

ラインに太さがありません。 –

+1

「線には太さがありません」 - 画面に描画されたとき(つまりプログラミング上の問題のとき)、その太さは少なくとも1ピクセルで、それ以上の場合もあります。 – ChrisW

1

線の式である:

y = mx + c 

それは即ち、この式を満たすのであれば点は、(B)は、このライン上にありますb = ma + c

2

A 2Dラインは、一般的にここでは2つの変数xの方程式およびyを用いて表現されている周知の方程式

y-y1 = (y1-y2)/(x1-x2) (x-x1)

今すぐGDI +ラインが(に(0,0)から引き出されている想像であります100、100)の場合、m =(0-100)/(0-100)= 1の値になるので、線の方程式はy-0 = 1 *(x-0)=> y = xです。

ここで問題の行の方程式があり、その行がその行に属しているかどうかを簡単にテストできます。与えられた点(x3、y3)はx = x3とy = y3を代入すると線方程式を満たしていればこの行に属します。例えば、10 = 10であるので、この線に属する点(10,10)は、この線に属さないが、12!= 10であるから

注:垂直線については、 (m)は無限ですが、この特殊なケースでは、垂直線x = cの方程式を使用することができます。ここで、c = x1 = x2です。

これが最も効果的な方法であるかどうかはわかりませんが、もう少し時間があるときは、より効率的な方法を見つけようとします。

これが役に立ちます。

3

あなたは、そのエンドポイント

PointF pt1, pt2; 

によって定義されたラインを持っているとあなたは次のように、あなたは、関数を定義することができ

PointF checkPoint; 

をチェックしたいポイントを持っている場合:

bool IsOnLine(PointF endPoint1, PointF endPoint2, PointF checkPoint) 
{ 
    return (checkPoint.Y - endPoint1.Y)/(endPoint2.Y - endPoint1.Y) 
     == (checkPoint.X - endPoint1.X)/(endPoint2.X - endPoint1.X); 
} 
if (IsOnLine(pt1, pt2, checkPoint) { 
    // Is on line 
} 

ゼロで除算を行う必要があります。

+0

ありがとうございます。 –

+3

これは正しいとは言えません...ポイント座標はintなので、checkPointがendPoint1に近く、endPoint2から遠く離れていると、パークリシェーションが(クリティカルで)失われます。もしあなたがそれを10進数または2進数に変更したなら、それは両側でうまくいくでしょうが、私はまだこのequasionの正確さを信じません。 – configurator

+0

フェアポイント(punの意図)、PointFに変更 –

5

L0およびL1の2点と、試験する点Pが与えられています。

   (L1 - L0) * (P - L0) 
n = (P - L0) - --------------------- (L1 - L0) 
       (L1 - L0) * (L1 - L0) 

ベクターnのノルムがL0L1通る線から点Pの距離です。この距離がゼロまたは十分小さい場合(丸め誤差の場合)、ポイントはライン上にあります。

記号*は内積を表します。

P = (5, 5) 

L0 = (0, 10) 
L1 = (20, -10) 

L1 - L0 = (20, -20) 
P - L0 = (5, -5) 

       (20, -20) * (5, -5) 
n = (5, -5) - --------------------- (20, -20) 
       (20, -20) * (20, -20) 

       200 
    = (5, -5) - --- (20, -20) 
       800 

    = (5, -5) - (5, -5) 

    = (0, 0) 
+3

+1丸め誤差に言及します。浮動小数点演算で完全一致を使用すると、多くの場合、他の提案されたソリューションが失敗する可能性があります。私は提案されたアルゴリズムの数値的な頑健性についてはわかりませんが、数値の堅牢性は複雑であり、精度が重要な場合は、そのトピックに関する科学文献を見ることをお勧めします。あるいは、著者が研究を行った可能性の高い図書館を少なくとも使用してください。 –

+0

私はあなたの例が正しいとは思っていません。なぜなら、いくつかの変換 'n =(p-L0) - (p-L0)'の後に、いつでも 'n =(0、0)' 。 – nenito

18

点R =(RX、RY)は点P =(PX、PY)とQ =(QX、QY)を結ぶ直線上にあるかどうかを判断するための最良の方法*(RY - PY) - (QY - PY)*(RX - PX) - マトリックス

{{qx - px, qy - py}, {rx - px, ry - py}}, 

すなわち(PX QX)の行列かどうかをチェックすることは、0に近いです。このソリューションには、他にもいくつかの利点があります。第1に、縦線の特殊な場合は必要ありません。第2に、分割しない(通常は低速な操作)、第3に、浮動小数点ラインはほとんど、しかし全く垂直ではありません。

私はMr.Patrickマクドナルドはほぼ正しい答えを入れて、これが彼の答えの補正だと思う
+0

ポイントが5.1、5.1の0,0から10,10までの直線の場合、行列式はゼロです。しかし、ポイントはライン上にありません。 – Andy

+0

「0に近い」とはどういう意味ですか? – Leggy7

+0

これは「受け入れられた」ものよりはるかに良い答えです。行方不明の唯一のものは、「近く」の定義です。これは、減算される数の文脈で理解されなければならない:5つの減算があるので、 "重要な精度の喪失"の5つの機会があり、実際に近いところに良いスペックを置くことは実際には幾分難しいことを意味する。 – Floris

5

public bool IsOnLine(Point endPoint1, Point endPoint2, Point checkPoint) 
{ 
    return (((double)checkPoint.Y - endPoint1.Y))/((double)(checkPoint.X - endPoint1.X)) 
     == ((double)(endPoint2.Y - endPoint1.Y))/((double)(endPoint2.X - endPoint1.X)); 
} 

そしてもちろん、他の多くの正解がある特にMr.Joshが、私はこれが見つかりました一番いい。

感謝の意を表します。

+0

checkPoint.x == endPoint.xの場合、またはエンドポイントのx値が同じ場合はdivをゼロにします – ThiefMaster

22

は、私はちょうど私が描画アプリケーションでは、このチェックを使用するため、いくつかの余分な要求を処理する関数を書いた:

  • 許容量 - 機能をクリックして行を選択するために使用されているので、エラーの余地がなければなりませんそれらの上に。
  • この行にはEndPointとStartPointがあり、無限の行はありません。
  • 直線の垂直線と水平線を処理する必要があります。(x2 - x1)== 0は、他の回答で0で除算します。 slope/y-intercept方法に代わるものとして
private const double SELECTION_FUZZINESS = 3; 

internal override bool ContainsPoint(Point point) 
{ 
    LineGeometry lineGeo = geometry as LineGeometry; 
    Point leftPoint; 
    Point rightPoint; 

    // Normalize start/end to left right to make the offset calc simpler. 
    if (lineGeo.StartPoint.X <= lineGeo.EndPoint.X) 
    { 
     leftPoint = lineGeo.StartPoint; 
     rightPoint = lineGeo.EndPoint; 
    } 
    else 
    { 
     leftPoint = lineGeo.EndPoint; 
     rightPoint = lineGeo.StartPoint; 
    } 

    // If point is out of bounds, no need to do further checks.     
    if (point.X + SELECTION_FUZZINESS < leftPoint.X || rightPoint.X < point.X - SELECTION_FUZZINESS) 
     return false; 
    else if (point.Y + SELECTION_FUZZINESS < Math.Min(leftPoint.Y, rightPoint.Y) || Math.Max(leftPoint.Y, rightPoint.Y) < point.Y - SELECTION_FUZZINESS) 
     return false; 

    double deltaX = rightPoint.X - leftPoint.X; 
    double deltaY = rightPoint.Y - leftPoint.Y; 

    // If the line is straight, the earlier boundary check is enough to determine that the point is on the line. 
    // Also prevents division by zero exceptions. 
    if (deltaX == 0 || deltaY == 0) 
     return true; 

    double slope  = deltaY/deltaX; 
    double offset  = leftPoint.Y - leftPoint.X * slope; 
    double calculatedY = point.X * slope + offset; 

    // Check calculated Y matches the points Y coord with some easing. 
    bool lineContains = point.Y - SELECTION_FUZZINESS <= calculatedY && calculatedY <= point.Y + SELECTION_FUZZINESS; 

    return lineContains;    
} 
+5

これは受け入れられた答えではありません。他のものはすべて数学的なものばかりです。これは現実の世界であり、戦闘で強化された機能であり、好ましいものでなければなりません。私はこれがMathOverflowではなく、神のためのStackOverflowであることを意味します。 –

+0

これは最高の答えです。 SELECTION_FUZZINESSにとって最良の価値は何ですか? –

0

、IはMath.Atan2を使用して、このアプローチを選択した:

// as an extension method 
public static bool Intersects(this Vector2 v, LineSegment s) { 
    // check from line segment start perspective 
    var reference = Math.Atan2(s.Start.Y - s.End.Y, s.Start.X - s.End.X); 
    var aTanTest = Math.Atan2(s.Start.Y - v.Y, s.Start.X - v.X); 

    // check from line segment end perspective 
    if (reference == aTanTest) { 
     reference = Math.Atan2(s.End.Y - s.Start.Y, s.End.X - s.Start.X); 
     aTanTest = Math.Atan2(s.End.Y - v.Y, s.End.X - v.X); 
    } 

    return reference == aTanTest; 
} 

それはエンドだと最初のチェックreferenceは、線分の始点から逆正接を決定ポイント。 次に、開始点の観点から、arcTanをベクトルvに設定します。

これらの値が等しい場合は、エンドポイントの観点から確認します。

シンプルで、水平、垂直、およびその間のすべてを扱います。

関連する問題