จะตรวจสอบได้อย่างไรว่า 2 ส่วนตัดกัน?
ฉันมีข้อมูลต่อไปนี้:
Segment1 [ {x1,y1}, {x2,y2} ]
Segment2 [ {x1,y1}, {x2,y2} ]
ฉันต้องเขียนอัลกอริทึมเล็ก ๆ ใน Python เพื่อตรวจสอบว่า 2 บรรทัดตัดกันหรือไม่
จะตรวจสอบได้อย่างไรว่า 2 ส่วนตัดกัน?
ฉันมีข้อมูลต่อไปนี้:
Segment1 [ {x1,y1}, {x2,y2} ]
Segment2 [ {x1,y1}, {x2,y2} ]
ฉันต้องเขียนอัลกอริทึมเล็ก ๆ ใน Python เพื่อตรวจสอบว่า 2 บรรทัดตัดกันหรือไม่
คำตอบ:
สมการของเส้นคือ:
f(x) = A*x + b = y
สำหรับเซ็กเมนต์นั้นจะเหมือนกันทุกประการยกเว้นว่า x จะรวมอยู่ในช่วงเวลา I
หากคุณมีสองส่วนให้กำหนดดังนี้:
Segment1 = {(X1, Y1), (X2, Y2)}
Segment2 = {(X3, Y3), (X4, Y4)}
abcisse Xa ของจุดตัดที่เป็นไปได้ (Xa, Ya) ต้องอยู่ในช่วง 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) )]
ตอนนี้เราต้องตรวจสอบว่ามีช่วงเวลานี้อยู่หรือไม่:
if (max(X1,X2) < min(X3,X4)):
return False # There is no mutual abcisses
ดังนั้นเราจึงมีสูตรสองบรรทัดและช่วงเวลาร่วมกัน สูตรบรรทัดของคุณคือ:
f1(x) = A1*x + b1 = y
f2(x) = A2*x + b2 = y
เมื่อเราได้คะแนนสองจุดตามส่วนเราจึงสามารถกำหนด 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) )) or
(Xa > min( max(X1,X2), max(X3,X4) )) ):
return False # intersection is out of bound
else:
return True
นอกจากนี้คุณสามารถตรวจสอบเมื่อเริ่มต้นว่าสองในสี่คะแนนที่ให้มานั้นไม่เท่ากับเพื่อหลีกเลี่ยงการทดสอบทั้งหมด
User @ 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)
คุณไม่จำเป็นต้องคำนวณว่าส่วนต่างๆตัดกันตรงไหนแต่ต้องเข้าใจว่าทั้งสองส่วนตัดกันหรือไม่ วิธีนี้จะทำให้การแก้ปัญหาง่ายขึ้น
แนวคิดคือการปฏิบัติต่อส่วนหนึ่งเป็น "จุดยึด" และแยกส่วนที่สองออกเป็น 2 จุด
ตอนนี้คุณจะต้องค้นหาตำแหน่งสัมพัทธ์ของแต่ละจุดไปยังส่วนที่ "ยึด" (OnLeft, OnRight หรือ Collinear)
หลังจากทำทั้งสองจุดแล้วให้ตรวจสอบว่าจุดใดจุดหนึ่งคือ OnLeft และอีกจุดคือ OnRight (หรืออาจรวมถึงตำแหน่ง Collinear หากคุณต้องการรวมที่ไม่เหมาะสมจุดตัดที่ด้วย)
จากนั้นคุณต้องทำซ้ำกระบวนการโดยใช้บทบาทของจุดยึดและเซ็กเมนต์ที่แยกออก
จุดตัดจะมีอยู่ถ้าจุดใดจุดหนึ่งคือ OnLeft และอีกจุดคือ OnRight ดูลิงค์นี้เพื่อดูคำอธิบายโดยละเอียดพร้อมภาพตัวอย่างสำหรับแต่ละกรณีที่เป็นไปได้
การใช้วิธีการดังกล่าวจะง่ายกว่าการใช้วิธีที่พบจุดตัด (เนื่องจากมีหลายกรณีที่คุณจะต้องจัดการเช่นกัน)
อัปเดต
ฟังก์ชันต่อไปนี้ควรแสดงให้เห็นถึงแนวคิด (ที่มา: Computational Geometry ใน C )
หมายเหตุ:ตัวอย่างนี้ถือว่าการใช้จำนวนเต็ม หากคุณกำลังใช้การแสดงจุดลอยตัวแทน (ซึ่งอาจทำให้สิ่งต่าง ๆ ซับซ้อนขึ้นอย่างเห็นได้ชัด) คุณควรกำหนดค่า epsilon เพื่อระบุ "ความเท่าเทียมกัน" (ส่วนใหญ่ใช้สำหรับการ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);
}
แน่นอนเมื่อใช้ฟังก์ชันเหล่านี้เราต้องอย่าลืมตรวจสอบว่าแต่ละส่วนอยู่ "ระหว่าง" ส่วนอื่น ๆ (เนื่องจากเป็นส่วนที่ จำกัด และไม่ใช่เส้นที่ไม่มีที่สิ้นสุด)
นอกจากนี้การใช้ฟังก์ชั่นเหล่านี้คุณสามารถเข้าใจว่าคุณมีที่เหมาะสมหรือไม่เหมาะสมสี่แยก
สมมติว่าทั้งสองกลุ่มมีจุดสิ้นสุด A, B และ C, D วิธีที่มีประสิทธิภาพเชิงตัวเลขในการกำหนดจุดตัดคือการตรวจสอบสัญลักษณ์ของปัจจัยทั้งสี่:
| 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 |
สำหรับจุดตัดดีเทอร์มิแนนต์แต่ละตัวทางด้านซ้ายจะต้องมีเครื่องหมายตรงข้ามของตัวที่อยู่ทางขวา แต่ไม่จำเป็นต้องมีความสัมพันธ์ใด ๆ ระหว่างสองบรรทัด โดยพื้นฐานแล้วคุณกำลังตรวจสอบแต่ละจุดของส่วนกับส่วนอื่น ๆ เพื่อให้แน่ใจว่าพวกเขาอยู่คนละฟากของเส้นที่กำหนดโดยส่วนอื่น ๆ
ดูที่นี่: http://www.cs.cmu.edu/~quake/robust.html
การตรวจสอบว่าส่วนของเส้นตัดกันนั้นง่ายมากหรือไม่ด้วยไลบรารีShapelyโดยใช้intersects
วิธีการ:
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
จากคำตอบที่ยอดเยี่ยมของ LiranและGrumdrigนี่คือรหัส Python ที่สมบูรณ์เพื่อตรวจสอบว่าส่วนที่ปิดตัดกันหรือไม่ ใช้ได้กับเซกเมนต์ collinear, เซกเมนต์ขนานกับแกน 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
นี่คือวิธีแก้ปัญหาโดยใช้ผลิตภัณฑ์ดอท:
# assumes line segments are stored in the format [(x0,y0),(x1,y1)]
def intersects(s0,s1):
dx0 = s0[1][0]-s0[0][0]
dx1 = s1[1][0]-s1[0][0]
dy0 = s0[1][1]-s0[0][1]
dy1 = s1[1][1]-s1[0][1]
p0 = dy1*(s1[1][0]-s0[0][0]) - dx1*(s1[1][1]-s0[0][1])
p1 = dy1*(s1[1][0]-s0[1][0]) - dx1*(s1[1][1]-s0[1][1])
p2 = dy0*(s0[1][0]-s1[0][0]) - dx0*(s0[1][1]-s1[0][1])
p3 = dy0*(s0[1][0]-s1[1][0]) - dx0*(s0[1][1]-s1[1][1])
return (p0*p1<=0) & (p2*p3<=0)
นี่คือการแสดงภาพใน Desmos: Line Segment Intersection
คุณมีสองส่วนบรรทัด กำหนดส่วนหนึ่งตามจุดสิ้นสุด A & B และส่วนที่สองตามจุดสิ้นสุด C & D มีเคล็ดลับที่ดีในการแสดงว่าพวกเขาต้องตัดกันภายในขอบเขตของเซ็กเมนต์ (โปรดทราบว่าเส้นอาจตัดกันเกินขอบเขตของส่วนดังนั้นคุณต้องระวังโค้ดที่ดีจะคอยดูเส้นขนานด้วย)
เคล็ดลับคือการทดสอบว่าจุด A และ B ต้องเรียงกันคนละด้านของเส้นซีดีและจุด C และ D ต้องอยู่คนละฟากของเส้น AB
เนื่องจากนี่คือการบ้านฉันจะไม่ให้คำตอบที่ชัดเจนแก่คุณ แต่การทดสอบง่ายๆเพื่อดูว่าจุดตกที่ด้านใดของเส้นคือการใช้ผลิตภัณฑ์ดอท ดังนั้นสำหรับซีดีบรรทัดที่กำหนดให้คำนวณเวกเตอร์ปกติกับบรรทัดนั้น (ฉันจะเรียกมันว่า N_C) ตอนนี้เพียงแค่ทดสอบสัญญาณของผลลัพธ์ทั้งสองนี้:
dot(A-C,N_C)
และ
dot(B-C,N_C)
หากผลลัพธ์เหล่านั้นมีเครื่องหมายตรงกันข้ามแสดงว่า A และ B จะอยู่ตรงข้ามกันของไลน์ซีดี ตอนนี้ทำแบบทดสอบเดียวกันกับอีกบรรทัด AB มันมีเวกเตอร์ปกติ N_A เปรียบเทียบสัญญาณของ
dot(C-A,N_A)
และ
dot(D-A,N_A)
ผมจะปล่อยให้คุณหาวิธีคำนวณเวกเตอร์ปกติ (ใน 2 มิตินั่นเป็นเรื่องเล็กน้อย แต่โค้ดของคุณจะกังวลหรือไม่ว่า A และ B เป็นจุดที่แตกต่างกันหรือไม่เช่นเดียวกัน C และ D แตกต่างกันหรือไม่)
คุณยังคงต้องกังวลเกี่ยวกับส่วนของเส้นตรงที่อยู่ตามเส้นไม่มีที่สิ้นสุดเดียวกันหรือว่าจุดใดจุดหนึ่งตกลงบนส่วนของเส้นตรงอื่น ๆ รหัสที่ดีจะตอบสนองทุกปัญหาที่เป็นไปได้
นี่คือรหัส C เพื่อตรวจสอบว่าจุดสองจุดอยู่ที่ด้านตรงข้ามของส่วนของเส้นตรงหรือไม่ การใช้รหัสนี้คุณสามารถตรวจสอบว่าทั้งสองส่วนตัดกันด้วยหรือไม่
// 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));
}
นี่คือรหัสหลามอื่นเพื่อตรวจสอบว่าส่วนที่ปิดตัดกันหรือไม่ เป็นโค้ด C ++ รุ่นที่เขียนขึ้นใหม่ในhttp://www.cdn.geeksforgeeks.org/check-if-two-given-line-se segment-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))
closed_segment_intersect()
จากรหัสทดสอบไม่ได้กำหนดไว้
สำหรับเซ็กเมนต์ AB และ CD ให้ค้นหาความชันของซีดี
slope=(Dy-Cy)/(Dx-Cx)
ขยายซีดีบน A และ B และใช้ระยะทางไปยังซีดีตรงขึ้น
dist1=slope*(Cx-Ax)+Ay-Cy
dist2=slope*(Dx-Ax)+Ay-Dy
ตรวจสอบว่าอยู่คนละฟากกันหรือไม่
return dist1*dist2<0
เนื่องจากคุณไม่ได้ระบุว่าคุณต้องการหาจุดตัดกันของเส้นจึงแก้ปัญหาได้ง่ายขึ้น หากคุณต้องการจุดตัดคำตอบโดยOMG_peanutsเป็นแนวทางที่เร็วกว่า อย่างไรก็ตามหากคุณต้องการทราบว่าเส้นตัดกันหรือไม่คุณสามารถทำได้โดยใช้สมการเส้น (ax + by + c = 0) แนวทางมีดังนี้:
เริ่มจากสองส่วนของเส้นตรง: ส่วนที่ 1 และส่วนที่ 2
segment1 = [[x1,y1], [x2,y2]]
segment2 = [[x3,y3], [x4,y4]]
ตรวจสอบว่าส่วนของบรรทัดทั้งสองเป็นเส้นที่มีความยาวไม่เป็นศูนย์และส่วนที่แตกต่างกันหรือไม่
จากตรงนี้ฉันถือว่าทั้งสองส่วนมีความยาวไม่เป็นศูนย์และแตกต่างกัน สำหรับแต่ละส่วนของเส้นตรงให้คำนวณความชันของเส้นแล้วรับสมการของเส้นในรูปแบบของ ax + by + c = 0 ทีนี้คำนวณค่า f = ax + by + c สำหรับจุดสองจุดของ ส่วนของเส้นตรงอื่น ๆ (ทำซ้ำสำหรับส่วนของเส้นตรงอื่นด้วย)
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 สำหรับจุดใด ๆ ทั้งสองเส้นจะแตะที่จุดใดจุดหนึ่ง ถ้า f1_1 และ f1_2 เท่ากันหรือ f2_1 และ f2_2 เท่ากันเส้นจะไม่ตัดกัน ถ้า f1_1 และ f1_2 ไม่เท่ากันและ f2_1 และ f2_2 ไม่เท่ากันส่วนของเส้นก็จะตัดกัน ขึ้นอยู่กับว่าคุณต้องการพิจารณาเส้นที่สัมผัสเป็น "จุดตัด" หรือไม่คุณสามารถปรับเงื่อนไขของคุณได้
a1
และใช้ไม่ได้กับเส้นมุมฉาก
เรายังสามารถแก้ปัญหานี้โดยใช้เวกเตอร์
[start, end]
ลองกำหนดกลุ่มเป็น ด้วยสองส่วนดังกล่าว[A, B]
และ[C, D]
ทั้งสองมีความยาวไม่เป็นศูนย์เราสามารถเลือกจุดสิ้นสุดจุดใดจุดหนึ่งเพื่อใช้เป็นจุดอ้างอิงเพื่อให้เราได้เวกเตอร์สามตัว:
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]]
จากนั้นเราสามารถมองหาจุดตัดโดยการคำนวณค่า t และ u p + t*r = u*q
ใน หลังจากเล่นกับสมการเล็กน้อยเราจะได้รับ:
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
นี่คือวิธีตรวจสอบการข้ามเส้นและจุดตัดที่เกิดขึ้น ให้ใช้ 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 ส่วนของเส้นจะขนานกัน อาจหมายความว่ามันทับซ้อนกัน หากพวกมันทับซ้อนกันที่จุดสิ้นสุดแสดงว่ามีทางแยกหนึ่งทาง มิฉะนั้นจะมีทางออกที่ไม่สิ้นสุด ด้วยวิธีแก้ปัญหามากมายอะไรที่บอกว่าเป็นจุดตัดของคุณ? ดังนั้นจึงเป็นกรณีพิเศษที่น่าสนใจ หากคุณรู้ล่วงหน้าว่าเส้นไม่สามารถทับซ้อนกันได้คุณก็สามารถตรวจสอบว่า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 ไม่ใช่แสดงว่าไม่เป็น co-linear แต่ขนานกันจึงไม่มีจุดตัด ตอนนี้สิ่งที่เหลืออยู่ถ้า det เป็นศูนย์คือปัญหา 1D แทนที่จะเป็น 2D เราจะต้องตรวจสอบวิธีใดวิธีหนึ่งในสองวิธีขึ้นอยู่กับว่า dx1 เป็นศูนย์หรือไม่ (ดังนั้นเราจึงสามารถหลีกเลี่ยงการหารด้วยศูนย์ได้) ถ้า dx1 เป็นศูนย์ให้ใช้ตรรกะเดียวกันกับค่า y แทนที่จะเป็น x ด้านล่าง
s = X3 / dx1
t = X4 / dx1
สิ่งนี้จะคำนวณสเกลเลอร์สองตัวเช่นถ้าเราปรับขนาดเวกเตอร์ (dx1, dy1) ด้วย s เราจะได้จุด (x3, y3) และโดย t เราจะได้ (x4, y4) ดังนั้นถ้า 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
คำตอบโดยGeorgyคือวิธีที่สะอาดที่สุดในการนำไปใช้ ต้องไล่สิ่งนี้ลงเนื่องจากตัวอย่าง brycboe ในขณะที่เรียบง่ายเช่นกันมีปัญหาเกี่ยวกับ colinearity
รหัสสำหรับการทดสอบ:
#!/usr/bin/python
#
# Notes on intersection:
#
# https://bryceboe.com/2006/10/23/line-segment-intersection-algorithm/
#
# /programming/3838329/how-can-i-check-if-two-segments-intersect
from shapely.geometry import LineString
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def ccw(A,B,C):
return (C.y-A.y)*(B.x-A.x) > (B.y-A.y)*(C.x-A.x)
def intersect(A,B,C,D):
return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)
def ShapelyIntersect(A,B,C,D):
return LineString([(A.x,A.y),(B.x,B.y)]).intersects(LineString([(C.x,C.y),(D.x,D.y)]))
a = Point(0,0)
b = Point(0,1)
c = Point(1,1)
d = Point(1,0)
'''
Test points:
b(0,1) c(1,1)
a(0,0) d(1,0)
'''
# F
print(intersect(a,b,c,d))
# T
print(intersect(a,c,b,d))
print(intersect(b,d,a,c))
print(intersect(d,b,a,c))
# F
print(intersect(a,d,b,c))
# same end point cases:
print("same end points")
# F - not intersected
print(intersect(a,b,a,d))
# T - This shows as intersected
print(intersect(b,a,a,d))
# F - this does not
print(intersect(b,a,d,a))
# F - this does not
print(intersect(a,b,d,a))
print("same end points, using shapely")
# T
print(ShapelyIntersect(a,b,a,d))
# T
print(ShapelyIntersect(b,a,a,d))
# T
print(ShapelyIntersect(b,a,d,a))
# T
print(ShapelyIntersect(a,b,d,a))
ถ้าข้อมูลของคุณกำหนดเส้นคุณก็ต้องพิสูจน์ว่ามันไม่ขนานกัน คุณสามารถคำนวณได้
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)
คำนวณจุดตัดกันของเส้นที่วางบนส่วนของคุณ (โดยทั่วไปหมายถึงการแก้ระบบสมการเชิงเส้น) จากนั้นตรวจสอบว่าอยู่ระหว่างจุดเริ่มต้นและจุดสิ้นสุดของกลุ่มของคุณหรือไม่
นี่คือสิ่งที่ฉันมีสำหรับ 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();
}
ดำเนินการใน 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
ฉันคิดว่าฉันจะมีส่วนร่วมในโซลูชัน 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
}
หนึ่งในวิธีแก้ปัญหาข้างต้นทำงานได้ดีฉันจึงตัดสินใจเขียนโปรแกรมสาธิตที่สมบูรณ์โดยใช้ wxPython คุณควรจะรันโปรแกรมได้ดังนี้ python " your file name "
# Click on the window to draw a line.
# The program will tell you if this and the other line intersect.
import wx
class Point:
def __init__(self, newX, newY):
self.x = newX
self.y = newY
app = wx.App()
frame = wx.Frame(None, wx.ID_ANY, "Main")
p1 = Point(90,200)
p2 = Point(150,80)
mp = Point(0,0) # mouse point
highestX = 0
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)
def is_intersection(p1, p2, p3, p4):
return intersect(p1, p2, p3, p4)
def drawIntersection(pc):
mp2 = Point(highestX, mp.y)
if is_intersection(p1, p2, mp, mp2):
pc.DrawText("intersection", 10, 10)
else:
pc.DrawText("no intersection", 10, 10)
def do_paint(evt):
pc = wx.PaintDC(frame)
pc.DrawLine(p1.x, p1.y, p2.x, p2.y)
pc.DrawLine(mp.x, mp.y, highestX, mp.y)
drawIntersection(pc)
def do_left_mouse(evt):
global mp, highestX
point = evt.GetPosition()
mp = Point(point[0], point[1])
highestX = frame.Size[0]
frame.Refresh()
frame.Bind(wx.EVT_PAINT, do_paint)
frame.Bind(wx.EVT_LEFT_DOWN, do_left_mouse)
frame.Show()
app.MainLoop()
ใช้โซลูชันOMG_Peanutsฉันแปลเป็น SQL (ฟังก์ชัน HANA Scalar)
ขอบคุณ OMG_Peanuts มันใช้งานได้ดี ฉันใช้ดินกลม แต่ระยะทางมีขนาดเล็กดังนั้นฉันคิดว่ามันโอเค
FUNCTION GA_INTERSECT" ( IN LAT_A1 DOUBLE,
IN LONG_A1 DOUBLE,
IN LAT_A2 DOUBLE,
IN LONG_A2 DOUBLE,
IN LAT_B1 DOUBLE,
IN LONG_B1 DOUBLE,
IN LAT_B2 DOUBLE,
IN LONG_B2 DOUBLE)
RETURNS RET_DOESINTERSECT DOUBLE
LANGUAGE SQLSCRIPT
SQL SECURITY INVOKER AS
BEGIN
DECLARE MA DOUBLE;
DECLARE MB DOUBLE;
DECLARE BA DOUBLE;
DECLARE BB DOUBLE;
DECLARE XA DOUBLE;
DECLARE MAX_MIN_X DOUBLE;
DECLARE MIN_MAX_X DOUBLE;
DECLARE DOESINTERSECT INTEGER;
SELECT 1 INTO DOESINTERSECT FROM DUMMY;
IF LAT_A2-LAT_A1 != 0 AND LAT_B2-LAT_B1 != 0 THEN
SELECT (LONG_A2 - LONG_A1)/(LAT_A2 - LAT_A1) INTO MA FROM DUMMY;
SELECT (LONG_B2 - LONG_B1)/(LAT_B2 - LAT_B1) INTO MB FROM DUMMY;
IF MA = MB THEN
SELECT 0 INTO DOESINTERSECT FROM DUMMY;
END IF;
END IF;
SELECT LONG_A1-MA*LAT_A1 INTO BA FROM DUMMY;
SELECT LONG_B1-MB*LAT_B1 INTO BB FROM DUMMY;
SELECT (BB - BA) / (MA - MB) INTO XA FROM DUMMY;
-- Max of Mins
IF LAT_A1 < LAT_A2 THEN -- MIN(LAT_A1, LAT_A2) = LAT_A1
IF LAT_B1 < LAT_B2 THEN -- MIN(LAT_B1, LAT_B2) = LAT_B1
IF LAT_A1 > LAT_B1 THEN -- MAX(LAT_A1, LAT_B1) = LAT_A1
SELECT LAT_A1 INTO MAX_MIN_X FROM DUMMY;
ELSE -- MAX(LAT_A1, LAT_B1) = LAT_B1
SELECT LAT_B1 INTO MAX_MIN_X FROM DUMMY;
END IF;
ELSEIF LAT_B2 < LAT_B1 THEN -- MIN(LAT_B1, LAT_B2) = LAT_B2
IF LAT_A1 > LAT_B2 THEN -- MAX(LAT_A1, LAT_B2) = LAT_A1
SELECT LAT_A1 INTO MAX_MIN_X FROM DUMMY;
ELSE -- MAX(LAT_A1, LAT_B2) = LAT_B2
SELECT LAT_B2 INTO MAX_MIN_X FROM DUMMY;
END IF;
END IF;
ELSEIF LAT_A2 < LAT_A1 THEN -- MIN(LAT_A1, LAT_A2) = LAT_A2
IF LAT_B1 < LAT_B2 THEN -- MIN(LAT_B1, LAT_B2) = LAT_B1
IF LAT_A2 > LAT_B1 THEN -- MAX(LAT_A2, LAT_B1) = LAT_A2
SELECT LAT_A2 INTO MAX_MIN_X FROM DUMMY;
ELSE -- MAX(LAT_A2, LAT_B1) = LAT_B1
SELECT LAT_B1 INTO MAX_MIN_X FROM DUMMY;
END IF;
ELSEIF LAT_B2 < LAT_B1 THEN -- MIN(LAT_B1, LAT_B2) = LAT_B2
IF LAT_A2 > LAT_B2 THEN -- MAX(LAT_A2, LAT_B2) = LAT_A2
SELECT LAT_A2 INTO MAX_MIN_X FROM DUMMY;
ELSE -- MAX(LAT_A2, LAT_B2) = LAT_B2
SELECT LAT_B2 INTO MAX_MIN_X FROM DUMMY;
END IF;
END IF;
END IF;
-- Min of Max
IF LAT_A1 > LAT_A2 THEN -- MAX(LAT_A1, LAT_A2) = LAT_A1
IF LAT_B1 > LAT_B2 THEN -- MAX(LAT_B1, LAT_B2) = LAT_B1
IF LAT_A1 < LAT_B1 THEN -- MIN(LAT_A1, LAT_B1) = LAT_A1
SELECT LAT_A1 INTO MIN_MAX_X FROM DUMMY;
ELSE -- MIN(LAT_A1, LAT_B1) = LAT_B1
SELECT LAT_B1 INTO MIN_MAX_X FROM DUMMY;
END IF;
ELSEIF LAT_B2 > LAT_B1 THEN -- MAX(LAT_B1, LAT_B2) = LAT_B2
IF LAT_A1 < LAT_B2 THEN -- MIN(LAT_A1, LAT_B2) = LAT_A1
SELECT LAT_A1 INTO MIN_MAX_X FROM DUMMY;
ELSE -- MIN(LAT_A1, LAT_B2) = LAT_B2
SELECT LAT_B2 INTO MIN_MAX_X FROM DUMMY;
END IF;
END IF;
ELSEIF LAT_A2 > LAT_A1 THEN -- MAX(LAT_A1, LAT_A2) = LAT_A2
IF LAT_B1 > LAT_B2 THEN -- MAX(LAT_B1, LAT_B2) = LAT_B1
IF LAT_A2 < LAT_B1 THEN -- MIN(LAT_A2, LAT_B1) = LAT_A2
SELECT LAT_A2 INTO MIN_MAX_X FROM DUMMY;
ELSE -- MIN(LAT_A2, LAT_B1) = LAT_B1
SELECT LAT_B1 INTO MIN_MAX_X FROM DUMMY;
END IF;
ELSEIF LAT_B2 > LAT_B1 THEN -- MAX(LAT_B1, LAT_B2) = LAT_B2
IF LAT_A2 < LAT_B2 THEN -- MIN(LAT_A2, LAT_B2) = LAT_A2
SELECT LAT_A2 INTO MIN_MAX_X FROM DUMMY;
ELSE -- MIN(LAT_A2, LAT_B2) = LAT_B2
SELECT LAT_B2 INTO MIN_MAX_X FROM DUMMY;
END IF;
END IF;
END IF;
IF XA < MAX_MIN_X OR
XA > MIN_MAX_X THEN
SELECT 0 INTO DOESINTERSECT FROM DUMMY;
END IF;
RET_DOESINTERSECT := :DOESINTERSECT;
END;
ได้รับการแก้ไขแล้ว แต่ทำไมไม่ใช้ python ... :)
def islineintersect(line1, line2):
i1 = [min(line1[0][0], line1[1][0]), max(line1[0][0], line1[1][0])]
i2 = [min(line2[0][0], line2[1][0]), max(line2[0][0], line2[1][0])]
ia = [max(i1[0], i2[0]), min(i1[1], i2[1])]
if max(line1[0][0], line1[1][0]) < min(line2[0][0], line2[1][0]):
return False
m1 = (line1[1][1] - line1[0][1]) * 1. / (line1[1][0] - line1[0][0]) * 1.
m2 = (line2[1][1] - line2[0][1]) * 1. / (line2[1][0] - line2[0][0]) * 1.
if m1 == m2:
return False
b1 = line1[0][1] - m1 * line1[0][0]
b2 = line2[0][1] - m2 * line2[0][0]
x1 = (b2 - b1) / (m1 - m2)
if (x1 < max(i1[0], i2[0])) or (x1 > min(i1[1], i2[1])):
return False
return True
นี้:
print islineintersect([(15, 20), (100, 200)], [(210, 5), (23, 119)])
เอาท์พุต:
True
และนี่:
print islineintersect([(15, 20), (100, 200)], [(-1, -5), (-5, -5)])
เอาท์พุต:
False