2つのセグメントが交差しているかどうかを確認するにはどうすればよいですか?
私は次のデータを持っています:
Segment1 [ {x1,y1}, {x2,y2} ]
Segment2 [ {x1,y1}, {x2,y2} ]
2行が交差しているかどうかを検出するために、Pythonで小さなアルゴリズムを記述する必要があります。
線の方程式は次のとおりです。
f(x) = A*x + b = y
セグメントの場合、間隔Iにxが含まれることを除いて、まったく同じです。
次のように定義された2つのセグメントがある場合:
Segment1 = {(X1, Y1), (X2, Y2)}
Segment2 = {(X3, Y3), (X4, Y4)}
潜在的な交差点(Xa、Ya)の横座標Xaは、次のように定義された間隔I1とI2の両方に含まれている必要があります。
I1 = [min(X1,X2), max(X1,X2)]
I2 = [min(X3,X4), max(X3,X4)]
そして、Xaは次のものに含まれていると言えます。
Ia = [max( min(X1,X2), min(X3,X4) ),
min( max(X1,X2), max(X3,X4) )]
次に、この間隔Iaが存在することを確認する必要があります。
if (max(X1,X2) < min(X3,X4))
return false; // There is no mutual abcisses
したがって、2行の式と相互間隔があります。線の式は次のとおりです。
f1(x) = A1*x + b1 = y
f2(x) = A2*x + b2 = y
セグメントごとに2つのポイントを得たので、A1、A2、b1、b2を決定できます。
A1 = (Y1-Y2)/(X1-X2) // Pay attention to not dividing by zero
A2 = (Y3-Y4)/(X3-X4) // Pay attention to not dividing by zero
b1 = Y1-A1*X1 = Y2-A1*X2
b2 = Y3-A2*X3 = Y4-A2*X4
セグメントが平行の場合、A1 == A2:
if (A1 == A2)
return false; // Parallel segments
両方の線上にあるポイント(Xa、Ya)は、式f1とf2の両方を検証する必要があります。
Ya = A1 * Xa + b1
Ya = A2 * Xa + b2
A1 * Xa + b1 = A2 * Xa + b2
Xa = (b2 - b1) / (A1 - A2) // Once again, pay attention to not dividing by zero
最後に行うことは、XaがIaに含まれていることを確認することです。
if ( (Xa < max( min(X1,X2), min(X3,X4) )) ||
(Xa > min( max(X1,X2), max(X3,X4) )) )
return false; // intersection is out of bound
else
return true;
これに加えて、起動時にすべてのテストを回避するために、提供された4つのポイントのうち2つが等しくないことを確認できます。
ユーザー@ i_4_gotは、Pythonで非常に効率的なソリューションを使用して このページ を指します。便宜上、ここに複製します(ここにあると嬉しかったので)。
def ccw(A,B,C):
return (C.y-A.y) * (B.x-A.x) > (B.y-A.y) * (C.x-A.x)
# Return true if line segments AB and CD intersect
def intersect(A,B,C,D):
return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)
正確に計算する必要はありませんwhereはセグメントが交差しますが、whetherそれらはまったく交差します。これにより、ソリューションが簡素化されます。
1つのセグメントを「アンカー」として扱い、2番目のセグメントを2つのポイントに分割するという考え方です。
次に、「アンカー」セグメント(OnLeft、OnRight、またはCollinear)に対する各ポイントの相対位置を見つける必要があります。
両方のポイントに対してこれを行った後、ポイントの一方がOnLeftで、もう一方がOnRightであることを確認します(またはimproper交差点も同様)。
その後、アンカーと分離したセグメントの役割でプロセスを繰り返す必要があります。
交差が存在するのは、一方のポイントがOnLeftで、もう一方のポイントがOnRightの場合のみです。 このリンク を参照して、可能性のある各ケースのサンプル画像を使用した詳細な説明を確認してください。
このようなメソッドの実装は、交差点を見つけるメソッドを実際に実装するよりもはるかに簡単になります(同様に多くのコーナーケースを処理する必要があるため)。
更新
次の関数は、アイデアを説明する必要があります(ソース: Computational Geometry in C )。
備考:このサンプルでは、整数の使用を想定しています。代わりに何らかの浮動小数点表現を使用している場合(明らかに複雑になる可能性があります)、「等価」を示すイプシロン値を決定する必要があります(主にIsCollinear
評価用)。
// points "a" and "b" forms the anchored segment.
// point "c" is the evaluated point
bool IsOnLeft(Point a, Point b, Point c)
{
return Area2(a, b, c) > 0;
}
bool IsOnRight(Point a, Point b, Point c)
{
return Area2(a, b, c) < 0;
}
bool IsCollinear(Point a, Point b, Point c)
{
return Area2(a, b, c) == 0;
}
// calculates the triangle's size (formed by the "anchor" segment and additional point)
int Area2(Point a, Point b, Point c)
{
return (b.X - a.X) * (c.Y - a.Y) -
(c.X - a.X) * (b.Y - a.Y);
}
もちろん、これらの関数を使用するときは、各セグメントが他のセグメントの「間にある」ことを忘れないでください(これらは有限のセグメントであり、無限の線ではないため)。
また、これらの関数を使用すると、properまたはimproper交差点があるかどうかを理解できます。
2つのセグメントにエンドポイントA、BおよびC、Dがあるとします。交差を決定する数値的に堅牢な方法は、4つの行列式の符号を確認することです。
| Ax-Cx Bx-Cx | | Ax-Dx Bx-Dx |
| Ay-Cy By-Cy | | Ay-Dy By-Dy |
| Cx-Ax Dx-Ax | | Cx-Bx Dx-Bx |
| Cy-Ay Dy-Ay | | Cy-By Dy-By |
交差の場合、左側の各行列式は右側の行列式の反対の符号を持っている必要がありますが、2つの線の間に関係がある必要はありません。基本的に、セグメントの各ポイントを他のセグメントと比較して、それらが他のセグメントによって定義された線の両側にあることを確認します。
こちらをご覧ください: http://www.cs.cmu.edu/~quake/robust.html
Liran's および Grumdrig's に基づく優れた答えは、ここに完全なPythonclosedセグメントは交差します。同一直線上のセグメント、Y軸に平行なセグメント、縮退セグメント(詳細は悪魔です)で動作します。整数座標を想定します。
def side(a,b,c):
""" Returns a position of the point c relative to the line going through a and b
Points a, b are expected to be different
"""
d = (c[1]-a[1])*(b[0]-a[0]) - (b[1]-a[1])*(c[0]-a[0])
return 1 if d > 0 else (-1 if d < 0 else 0)
def is_point_in_closed_segment(a, b, c):
""" Returns True if c is inside closed segment, False otherwise.
a, b, c are expected to be collinear
"""
if a[0] < b[0]:
return a[0] <= c[0] and c[0] <= b[0]
if b[0] < a[0]:
return b[0] <= c[0] and c[0] <= a[0]
if a[1] < b[1]:
return a[1] <= c[1] and c[1] <= b[1]
if b[1] < a[1]:
return b[1] <= c[1] and c[1] <= a[1]
return a[0] == c[0] and a[1] == c[1]
#
def closed_segment_intersect(a,b,c,d):
""" Verifies if closed segments a, b, c, d do intersect.
"""
if a == b:
return a == c or a == d
if c == d:
return c == a or c == b
s1 = side(a,b,c)
s2 = side(a,b,d)
# All points are collinear
if s1 == 0 and s2 == 0:
return \
is_point_in_closed_segment(a, b, c) or is_point_in_closed_segment(a, b, d) or \
is_point_in_closed_segment(c, d, a) or is_point_in_closed_segment(c, d, b)
# No touching and on the same side
if s1 and s1 == s2:
return False
s1 = side(c,d,a)
s2 = side(c,d,b)
# No touching and on the same side
if s1 and s1 == s2:
return False
return True
2つのラインセグメントがあります。エンドポイントAとBで1つのセグメントを定義し、エンドポイントC&Dで2番目のセグメントを定義します。セグメントの境界内で交差する必要があることを示す素敵なトリックがあります。 (線自体はセグメントの境界を越えて交差する可能性があるため、注意が必要です。優れたコードは平行線も監視します。)
トリックは、ポイントAとBがラインCDの反対側に並んでいる必要があり、ポイントCとDがラインABの反対側になければならないことをテストすることです。
これは宿題なので、明示的な解決策は提供しません。しかし、点が線のどちら側にあるかを確認する簡単なテストは、ドット積を使用することです。したがって、特定のラインCDについて、そのラインの法線ベクトルを計算します(N_Cと呼びます)。次に、これら2つの結果の符号をテストします。
dot(A-C,N_C)
そして
dot(B-C,N_C)
それらの結果の符号が反対の場合、AとBはCDの反対側にあります。次に、他の行ABに対して同じテストを実行します。法線ベクトルN_Aがあります。の兆候を比較する
dot(C-A,N_A)
そして
dot(D-A,N_A)
法線ベクトルの計算方法については、お任せします。 (2次元ではそれは簡単ですが、コードはAとBが別個の点であるかどうかを心配しますか?同様に、CとDは別個ですか?)
それでも、同じ無限線に沿った線分や、実際に1つの点が他の線分自体に当たるかどうかを心配する必要があります。適切なコードは、考えられるすべての問題に対応します。
以下は、2つの点が線分の反対側にあるかどうかを確認するCコードです。このコードを使用すると、2つのセグメントが交差するかどうかも確認できます。
// true if points p1, p2 lie on the opposite sides of segment s1--s2
bool oppositeSide (Point2f s1, Point2f s2, Point2f p1, Point2f p2) {
//calculate normal to the segment
Point2f vec = s1-s2;
Point2f normal(vec.y, -vec.x); // no need to normalize
// vectors to the points
Point2f v1 = p1-s1;
Point2f v2 = p2-s1;
// compare signs of the projections of v1, v2 onto the normal
float proj1 = v1.dot(normal);
float proj2 = v2.dot(normal);
if (proj1==0 || proj2==0)
cout<<"collinear points"<<endl;
return(SIGN(proj1) != SIGN(proj2));
}
閉じたセグメントが交差するかどうかを確認する別のpythonコード。これは http://www.cdn.geeksforgeeks.org/check-ifのC++コードの書き直されたバージョンです。 -two-given-line-segments-intersect / 。この実装は、すべての特殊なケースをカバーします(たとえば、すべてのポイントが同一直線上にある)。
def on_segment(p, q, r):
'''Given three colinear points p, q, r, the function checks if
point q lies on line segment "pr"
'''
if (q[0] <= max(p[0], r[0]) and q[0] >= min(p[0], r[0]) and
q[1] <= max(p[1], r[1]) and q[1] >= min(p[1], r[1])):
return True
return False
def orientation(p, q, r):
'''Find orientation of ordered triplet (p, q, r).
The function returns following values
0 --> p, q and r are colinear
1 --> Clockwise
2 --> Counterclockwise
'''
val = ((q[1] - p[1]) * (r[0] - q[0]) -
(q[0] - p[0]) * (r[1] - q[1]))
if val == 0:
return 0 # colinear
Elif val > 0:
return 1 # clockwise
else:
return 2 # counter-clockwise
def do_intersect(p1, q1, p2, q2):
'''Main function to check whether the closed line segments p1 - q1 and p2
- q2 intersect'''
o1 = orientation(p1, q1, p2)
o2 = orientation(p1, q1, q2)
o3 = orientation(p2, q2, p1)
o4 = orientation(p2, q2, q1)
# General case
if (o1 != o2 and o3 != o4):
return True
# Special Cases
# p1, q1 and p2 are colinear and p2 lies on segment p1q1
if (o1 == 0 and on_segment(p1, p2, q1)):
return True
# p1, q1 and p2 are colinear and q2 lies on segment p1q1
if (o2 == 0 and on_segment(p1, q2, q1)):
return True
# p2, q2 and p1 are colinear and p1 lies on segment p2q2
if (o3 == 0 and on_segment(p2, p1, q2)):
return True
# p2, q2 and q1 are colinear and q1 lies on segment p2q2
if (o4 == 0 and on_segment(p2, q1, q2)):
return True
return False # Doesn't fall in any of the above cases
以下は、機能することを確認するためのテスト関数です。
import matplotlib.pyplot as plt
def test_intersect_func():
p1 = (1, 1)
q1 = (10, 1)
p2 = (1, 2)
q2 = (10, 2)
fig, ax = plt.subplots()
ax.plot([p1[0], q1[0]], [p1[1], q1[1]], 'x-')
ax.plot([p2[0], q2[0]], [p2[1], q2[1]], 'x-')
print(do_intersect(p1, q1, p2, q2))
p1 = (10, 0)
q1 = (0, 10)
p2 = (0, 0)
q2 = (10, 10)
fig, ax = plt.subplots()
ax.plot([p1[0], q1[0]], [p1[1], q1[1]], 'x-')
ax.plot([p2[0], q2[0]], [p2[1], q2[1]], 'x-')
print(do_intersect(p1, q1, p2, q2))
p1 = (-5, -5)
q1 = (0, 0)
p2 = (1, 1)
q2 = (10, 10)
fig, ax = plt.subplots()
ax.plot([p1[0], q1[0]], [p1[1], q1[1]], 'x-')
ax.plot([p2[0], q2[0]], [p2[1], q2[1]], 'x-')
print(do_intersect(p1, q1, p2, q2))
p1 = (0, 0)
q1 = (1, 1)
p2 = (1, 1)
q2 = (10, 10)
fig, ax = plt.subplots()
ax.plot([p1[0], q1[0]], [p1[1], q1[1]], 'x-')
ax.plot([p2[0], q2[0]], [p2[1], q2[1]], 'x-')
print(do_intersect(p1, q1, p2, q2))
intersects
メソッドを使用して Shapely ライブラリを使用すると、ラインセグメントが交差しているかどうかを確認するのは非常に簡単です。
from shapely.geometry import LineString
line = LineString([(0, 0), (1, 1)])
other = LineString([(0, 1), (1, 0)])
print(line.intersects(other))
# True
line = LineString([(0, 0), (1, 1)])
other = LineString([(0, 1), (1, 2)])
print(line.intersects(other))
# False
ベクトルを利用してこれを解決することもできます。
セグメントを[start, end]
として定義しましょう。長さがゼロ以外の2つのセグメント[A, B]
と[C, D]
が与えられた場合、3つのベクトルを取得するために、参照ポイントとして使用するエンドポイントの1つを選択できます。
x = 0
y = 1
p = A-C = [C[x]-A[x], C[y]-A[y]]
q = B-A = [B[x]-A[x], B[y]-A[y]]
r = D-C = [D[x]-C[x], D[y]-C[y]]
そこから、p + t*r = u*q
でtとuを計算することにより、交差点を探すことができます。方程式を少し試してみると、次のようになります。
t = (q[y]*p[x] - q[x]*p[y])/(q[x]*r[y] - q[y]*r[x])
u = (p[x] + t*r[x])/q[x]
したがって、関数は次のとおりです。
def intersects(a, b):
p = [b[0][0]-a[0][0], b[0][1]-a[0][1]]
q = [a[1][0]-a[0][0], a[1][1]-a[0][1]]
r = [b[1][0]-b[0][0], b[1][1]-b[0][1]]
t = (q[1]*p[0] - q[0]*p[1])/(q[0]*r[1] - q[1]*r[0]) \
if (q[0]*r[1] - q[1]*r[0]) != 0 \
else (q[1]*p[0] - q[0]*p[1])
u = (p[0] + t*r[0])/q[0] \
if q[0] != 0 \
else (p[1] + t*r[1])/q[1]
return t >= 0 and t <= 1 and u >= 0 and u <= 1
線の交点を見つけたいとは言わないので、問題は簡単に解決できます。交点が必要な場合は、 OMG_peanuts による答えがより速いアプローチです。ただし、線が交差するかどうかだけを知りたい場合は、直線方程式(ax + by + c = 0)を使用して確認できます。アプローチは次のとおりです。
セグメント1とセグメント2の2つのラインセグメントから始めましょう。
segment1 = [[x1,y1], [x2,y2]]
segment2 = [[x3,y3], [x4,y4]]
2つのラインセグメントが長さ0以外のラインおよび別個のセグメントであるかどうかを確認します。
ここからは、2つのセグメントの長さはゼロではなく、異なると仮定します。各ラインセグメントについて、ラインの勾配を計算し、ax + by + c = 0の形でラインの方程式を取得します。次に、fの値を計算します。他のラインセグメント(他のラインセグメントについてもこれを繰り返します)。
a2 = (y3-y4)/(x3-x4);
b1 = -1;
b2 = -1;
c1 = y1 - a1*x1;
c2 = y3 - a2*x3;
// using the sign function from numpy
f1_1 = sign(a1*x3 + b1*y3 + c1);
f1_2 = sign(a1*x4 + b1*y4 + c1);
f2_1 = sign(a2*x1 + b2*y1 + c2);
f2_2 = sign(a2*x2 + b2*y2 + c2);
残っているのは、さまざまなケースだけです。任意のポイントでf = 0の場合、2つのラインはポイントで接触します。 f1_1とf1_2が等しいか、f2_1とf2_2が等しい場合、線は交差しません。 f1_1とf1_2が等しくないandf2_1とf2_2が等しくない場合、線分は交差します。接触する線を「交差」するかどうかに応じて、条件を調整できます。
セグメントABおよびCDの場合、CDの勾配を見つける
slope=(Dy-Cy)/(Dx-Cx)
cDをAとBに拡張し、CDがまっすぐ上に行くまでの距離を取る
dist1=slope*(Cx-Ax)+Ay-Cy
dist2=slope*(Dx-Ax)+Ay-Dy
それらが反対側にあるかどうかを確認します
return dist1*dist2<0
セグメント上にある線の交点を計算し(基本的に線形方程式システムを解くことを意味します)、セグメントの開始点と終了点の間にあるかどうかを確認します。
私は素敵なSwiftソリューションに貢献すると思いました:
struct Pt {
var x: Double
var y: Double
}
struct LineSegment {
var p1: Pt
var p2: Pt
}
func doLineSegmentsIntersect(ls1: LineSegment, ls2: LineSegment) -> Bool {
if (ls1.p2.x-ls1.p1.x == 0) { //handle vertical segment1
if (ls2.p2.x-ls2.p1.x == 0) {
//both lines are vertical and parallel
return false
}
let x = ls1.p1.x
let slope2 = (ls2.p2.y-ls2.p1.y)/(ls2.p2.x-ls2.p1.x)
let c2 = ls2.p1.y-slope2*ls2.p1.x
let y = x*slope2+c2 // y intersection point
return (y > ls1.p1.y && x < ls1.p2.y) || (y > ls1.p2.y && y < ls1.p1.y) // check if y is between y1,y2 in segment1
}
if (ls2.p2.x-ls2.p1.x == 0) { //handle vertical segment2
let x = ls2.p1.x
let slope1 = (ls1.p2.y-ls1.p1.y)/(ls1.p2.x-ls1.p1.x)
let c1 = ls1.p1.y-slope1*ls1.p1.x
let y = x*slope1+c1 // y intersection point
return (y > ls2.p1.y && x < ls2.p2.y) || (y > ls2.p2.y && y < ls2.p1.y) // validate that y is between y1,y2 in segment2
}
let slope1 = (ls1.p2.y-ls1.p1.y)/(ls1.p2.x-ls1.p1.x)
let slope2 = (ls2.p2.y-ls2.p1.y)/(ls2.p2.x-ls2.p1.x)
if (slope1 == slope2) { //segments are parallel
return false
}
let c1 = ls1.p1.y-slope1*ls1.p1.x
let c2 = ls2.p1.y-slope2*ls2.p1.x
let x = (c2-c1)/(slope1-slope2)
return (((x > ls1.p1.x && x < ls1.p2.x) || (x > ls1.p2.x && x < ls1.p1.x)) &&
((x > ls2.p1.x && x < ls2.p2.x) || (x > ls2.p2.x && x < ls2.p1.x)))
//validate that x is between x1,x2 in both segments
}
これは、線の交差と交差点の発生をチェックする私の方法です。 x1からx4およびy1からy4を使用してみましょう
Segment1 = {(X1, Y1), (X2, Y2)}
Segment2 = {(X3, Y3), (X4, Y4)}
次に、それらを表すためにいくつかのベクトルが必要です
dx1 = X2 - X1
dx2 = X4 - X4
dy1 = Y2 - Y1
dy2 = Y4 - Y3
今、私たちは決定要因を見ます
det = dx1 * dy2 - dx2 * dy1
行列式が0.0の場合、線分は平行です。これは、それらが重複することを意味する場合があります。エンドポイントでのみオーバーラップする場合、1つの交差ソリューションがあります。そうでなければ、無限の解決策があります。無限に多くのソリューションがありますが、あなたの交差点は何と言えますか?それは興味深い特別なケースです。行がオーバーラップできないことが事前にわかっている場合は、det == 0.0
そして、もしそうなら、それらは交差せず、行われると言ってください。それ以外の場合は、続行します
dx3 = X3 - X1
dy3 = Y3 - Y1
det1 = dx1 * dy3 - dx3 * dy1
det2 = dx2 * dy3 - dx3 * dy2
ここで、det、det1、およびdet2がすべてゼロの場合、線は同一直線上にあり、重なり合う可能性があります。 detがゼロであるが、det1またはdet2のいずれかがそうでない場合、それらは共直線ではなく、平行であるため、交差はありません。したがって、detがゼロの場合に残っているのは、2Dではなく1Dの問題です。 dx1がゼロかどうかに応じて、2つの方法のいずれかをチェックする必要があります(ゼロによる除算を回避できます)。 dx1がゼロの場合、以下のxではなくy値で同じロジックを実行します。
s = X3 / dx1
t = X4 / dx1
これは、ベクトル(dx1、dy1)をsでスケーリングするとポイント(x3、y3)を取得し、tで(x4、y4)を取得するように、2つのスケーラーを計算します。したがって、sまたはtのいずれかが0.0〜1.0の場合、ポイント3または4は最初の行にあります。負の場合は、ポイントがベクターの開始点よりも後ろにあることを意味し、> 1.0はベクターの終了点よりもさらに先にあることを意味します。 0.0は(x1、y1)にあり、1.0は(x2、y2)にあることを意味します。 sとtの両方が<0.0であるか、両方が> 1.0である場合、それらは交差しません。そして、それは平行線の特殊なケースを処理します。
今、det != 0.0
その後
s = det1 / det
t = det2 / det
if (s < 0.0 || s > 1.0 || t < 0.0 || t > 1.0)
return false // no intersect
これは、上記で実際に行っていたことに似ています。上記のテストに合格すると、ラインセグメントは交差し、交差は次のように簡単に計算できます。
Ix = X1 + t * dx1
Iy = Y1 + t * dy1
数学が何をしているのかを詳しく調べたい場合は、Cramerの規則を調べてください。
データが行を定義している場合、それらが並列ではないことを証明する必要があります。これを行うには、計算することができます
alpha = float(y2 - y1) / (x2 - x1).
この係数がLine1とLine2の両方で等しい場合、ラインが平行であることを意味します。そうでない場合は、交差することを意味します。
それらが並行している場合、それらが同じではないことを証明する必要があります。そのために、計算する
beta = y1 - alpha*x1
ベータがLine1とLine2で同じである場合、それらは等しいのでラインが交差することを意味します
それらがセグメントである場合、各ラインについて上記のようにアルファとベータを計算する必要があります。次に、(beta1-beta2)/(alpha1-alpha2)がMin(x1_line1、x2_line1)より大きくMax(x1_line1、x2_line1)より小さいことを確認する必要があります
Javaで実装されています。ただし、同一直線上では機能しないようです(別名L1(0,0)(10,10)L2(1,1)(2,2)
public class TestCode
{
public class Point
{
public double x = 0;
public double y = 0;
public Point(){}
}
public class Line
{
public Point p1, p2;
public Line( double x1, double y1, double x2, double y2)
{
p1 = new Point();
p2 = new Point();
p1.x = x1;
p1.y = y1;
p2.x = x2;
p2.y = y2;
}
}
//line segments
private static Line s1;
private static Line s2;
public TestCode()
{
s1 = new Line(0,0,0,10);
s2 = new Line(-1,0,0,10);
}
public TestCode(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4)
{
s1 = new Line(x1,y1, x2,y2);
s2 = new Line(x3,y3, x4,y4);
}
public static void main(String args[])
{
TestCode code = null;
////////////////////////////
code = new TestCode(0,0,0,10,
0,1,0,5);
if( intersect(code) )
{ System.out.println( "OK COLINEAR: INTERSECTS" ); }
else
{ System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(0,0,0,10,
0,1,0,10);
if( intersect(code) )
{ System.out.println( "OK COLINEAR: INTERSECTS" ); }
else
{ System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(0,0,10,0,
5,0,15,0);
if( intersect(code) )
{ System.out.println( "OK COLINEAR: INTERSECTS" ); }
else
{ System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(0,0,10,0,
0,0,15,0);
if( intersect(code) )
{ System.out.println( "OK COLINEAR: INTERSECTS" ); }
else
{ System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(0,0,10,10,
1,1,5,5);
if( intersect(code) )
{ System.out.println( "OK COLINEAR: INTERSECTS" ); }
else
{ System.out.println( "ERROR COLINEAR: DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(0,0,0,10,
-1,-1,0,10);
if( intersect(code) )
{ System.out.println( "OK SLOPE END: INTERSECTS" ); }
else
{ System.out.println( "ERROR SLOPE END: DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(-10,-10,10,10,
-10,10,10,-10);
if( intersect(code) )
{ System.out.println( "OK SLOPE Intersect(0,0): INTERSECTS" ); }
else
{ System.out.println( "ERROR SLOPE Intersect(0,0): DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(-10,-10,10,10,
-3,-2,50,-2);
if( intersect(code) )
{ System.out.println( "OK SLOPE Line2 VERTIAL: INTERSECTS" ); }
else
{ System.out.println( "ERROR SLOPE Line2 VERTICAL: DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(-10,-10,10,10,
50,-2,-3,-2);
if( intersect(code) )
{ System.out.println( "OK SLOPE Line2 (reversed) VERTIAL: INTERSECTS" ); }
else
{ System.out.println( "ERROR SLOPE Line2 (reversed) VERTICAL: DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(0,0,0,10,
1,0,1,10);
if( intersect(code) )
{ System.out.println( "ERROR PARALLEL VERTICAL: INTERSECTS" ); }
else
{ System.out.println( "OK PARALLEL VERTICAL: DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(0,2,10,2,
0,10,10,10);
if( intersect(code) )
{ System.out.println( "ERROR PARALLEL HORIZONTAL: INTERSECTS" ); }
else
{ System.out.println( "OK PARALLEL HORIZONTAL: DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(0,10,5,13.75,
0,18.75,10,15);
if( intersect(code) )
{ System.out.println( "ERROR PARALLEL SLOPE=.75: INTERSECTS" ); }
else
{ System.out.println( "OK PARALLEL SLOPE=.75: DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(0,0,1,1,
2,-1,2,10);
if( intersect(code) )
{ System.out.println( "ERROR SEPERATE SEGMENTS: INTERSECTS" ); }
else
{ System.out.println( "OK SEPERATE SEGMENTS: DO NOT INTERSECT" ); }
////////////////////////////
code = new TestCode(0,0,1,1,
-1,-10,-5,10);
if( intersect(code) )
{ System.out.println( "ERROR SEPERATE SEGMENTS 2: INTERSECTS" ); }
else
{ System.out.println( "OK SEPERATE SEGMENTS 2: DO NOT INTERSECT" ); }
}
public static boolean intersect( TestCode code )
{
return intersect( code.s1, code.s2);
}
public static boolean intersect( Line line1, Line line2 )
{
double i1min = Math.min(line1.p1.x, line1.p2.x);
double i1max = Math.max(line1.p1.x, line1.p2.x);
double i2min = Math.min(line2.p1.x, line2.p2.x);
double i2max = Math.max(line2.p1.x, line2.p2.x);
double iamax = Math.max(i1min, i2min);
double iamin = Math.min(i1max, i2max);
if( Math.max(line1.p1.x, line1.p2.x) < Math.min(line2.p1.x, line2.p2.x) )
return false;
double m1 = (line1.p2.y - line1.p1.y) / (line1.p2.x - line1.p1.x );
double m2 = (line2.p2.y - line2.p1.y) / (line2.p2.x - line2.p1.x );
if( m1 == m2 )
return false;
//b1 = line1[0][1] - m1 * line1[0][0]
//b2 = line2[0][1] - m2 * line2[0][0]
double b1 = line1.p1.y - m1 * line1.p1.x;
double b2 = line2.p1.y - m2 * line2.p1.x;
double x1 = (b2 - b1) / (m1 - m2);
if( (x1 < Math.max(i1min, i2min)) || (x1 > Math.min(i1max, i2max)) )
return false;
return true;
}
}
これまでの出力は
ERROR COLINEAR: DO NOT INTERSECT
ERROR COLINEAR: DO NOT INTERSECT
ERROR COLINEAR: DO NOT INTERSECT
ERROR COLINEAR: DO NOT INTERSECT
ERROR COLINEAR: DO NOT INTERSECT
OK SLOPE END: INTERSECTS
OK SLOPE Intersect(0,0): INTERSECTS
OK SLOPE Line2 VERTIAL: INTERSECTS
OK SLOPE Line2 (reversed) VERTIAL: INTERSECTS
OK PARALLEL VERTICAL: DO NOT INTERSECT
OK PARALLEL HORIZONTAL: DO NOT INTERSECT
OK PARALLEL SLOPE=.75: DO NOT INTERSECT
OK SEPERATE SEGMENTS: DO NOT INTERSECT
OK SEPERATE SEGMENTS 2: DO NOT INTERSECT
これは私がAS3のために持っているものです、pythonについてはあまり知りませんが、概念はそこにあります
public function getIntersectingPointF($A:Point, $B:Point, $C:Point, $D:Point):Number {
var A:Point = $A.clone();
var B:Point = $B.clone();
var C:Point = $C.clone();
var D:Point = $D.clone();
var f_ab:Number = (D.x - C.x) * (A.y - C.y) - (D.y - C.y) * (A.x - C.x);
// are lines parallel
if (f_ab == 0) { return Infinity };
var f_cd:Number = (B.x - A.x) * (A.y - C.y) - (B.y - A.y) * (A.x - C.x);
var f_d:Number = (D.y - C.y) * (B.x - A.x) - (D.x - C.x) * (B.y - A.y);
var f1:Number = f_ab/f_d
var f2:Number = f_cd / f_d
if (f1 == Infinity || f1 <= 0 || f1 >= 1) { return Infinity };
if (f2 == Infinity || f2 <= 0 || f2 >= 1) { return Infinity };
return f1;
}
public function getIntersectingPoint($A:Point, $B:Point, $C:Point, $D:Point):Point
{
var f:Number = getIntersectingPointF($A, $B, $C, $D);
if (f == Infinity || f <= 0 || f >= 1) { return null };
var retPoint:Point = Point.interpolate($A, $B, 1 - f);
return retPoint.clone();
}