ポイントが特定の線に属しているかどうかはどうすればわかりますか?
可能であれば、例をいただければ幸いです。
最も単純な形式では、座標を一次方程式に代入して、等しいかどうかを確認します。
与えられた:
Point p (X=4, Y=5)
Line l (Slope=1, YIntersect=1)
XとYを接続します。
Y = Slope * X + YIntersect
=> 5 = 1 * 4 + 1
=> 5 = 5
そうです、要点は線上にあります。
線が(X1、Y1)、(X2、Y2)形式で表されている場合は、次の方法で勾配を計算できます。
Slope = (y1 - y2) / (x1-x2)
そして、これでY-Intersectを取得します。
YIntersect = - Slope * X1 + Y1;
編集:Y-Intersectを修正しました(これはX1/Y1でした...)
x1 - x2
が0
ではないことを確認する必要があります。そうである場合、ポイントがライン上にあるかどうかを確認するのは、ポイントのY値がx1
またはx2
のいずれかに等しいかどうかを確認するだけです。また、ポイントのXが「x1」または「x2」でないことを確認してください。
描画アプリケーションでこのチェックを使用するので、いくつかの追加要件を処理する関数を作成しました。
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;
}
点R =(rx、ry)が点P =(px、py)とQ =(qx、qy)を結ぶ直線上にあるかどうかを判断する最良の方法は、行列式が行列式であるかどうかを確認することです。
{{qx - px, qy - py}, {rx - px, ry - py}},
つまり、(qx --px)*(ry --py)-(qy --py)*(rx --px)は0に近いです。このソリューションには、投稿された他のソリューションに比べていくつかの関連する利点があります。まず、垂直線に特別なケースは必要ありません。 、第2に、分割されません(通常は低速の操作)。第3に、線がほぼ垂直であるが完全に垂直ではない場合に、浮動小数点の動作が悪くなることはありません。
線上の2つの点L0
とL1
、およびテストする点P
が与えられます。
(L1 - L0) * (P - L0)
n = (P - L0) - --------------------- (L1 - L0)
(L1 - L0) * (L1 - L0)
ベクトルn
のノルムは、L0
とL1
を通る線からの点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)
パトリック・マクドナルド氏がほぼ正しい答えを出したと思います。これが彼の答えの訂正です。
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));
}
そしてもちろん、他にも多くの正解、特にジョシュ氏がいますが、これが最良の答えだと思いました。
Evryoneに感謝します。
y = m * x + c
これは直線の方程式です。 xとyは座標です。各線は、その傾き(m)とy軸と交差する場所(c)によって特徴付けられます。
したがって、直線のmとcが与えられた場合、方程式がx = x1とy = y1に当てはまるかどうかを確認することで、点(x1、y1)が直線上にあるかどうかを判断できます。
端点で定義された線がある場合
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
}
ただし、ゼロによる除算を確認する必要があります。
2D直線は通常、2つの変数xとyの方程式を使用して表されます。ここではよく知られている方程式です
ここで、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なのでこの線に属しますが、(10,12)は12!= 10からこの線に属しません。
注:垂直線の場合、傾き(m)の値は無限大ですが、この特殊なケースでは、垂直線の式を直接x = c(c = x1 = x2)で使用できます。
これがこれを行う最も効率的な方法であるかどうかはわかりませんが。もう少し時間があれば、もっと効率的な方法を見つけようと思います。
お役に立てれば。
直線の方程式は次のとおりです。
y = mx + c
したがって、点(a、b)は、この方程式を満たす場合、つまりb = ma + c
slope/y-intercept
メソッドの代わりに、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
に対するarcTanを決定します。
これらの値が等しい場合は、エンドポイントの観点からチェックします。
シンプルで、水平、垂直、その他すべてを処理します。
具体的に教えてください。
あなたはどのプログラミング言語について話しているのですか?
どんな環境について話しているのですか?
あなたはどんな「線」について話しているのですか?テキスト?何点?画面上のXY?