2 বিভাগগুলি ছেদ করলে আমি কীভাবে তা পরীক্ষা করতে পারি?
আমি নিম্নলিখিত তথ্য আছে:
Segment1 [ {x1,y1}, {x2,y2} ]
Segment2 [ {x1,y1}, {x2,y2} ]
2 লাইন ছেদ করছে কিনা তা সনাক্ত করতে পাইথনে একটি ছোট অ্যালগরিদম লিখতে হবে।
2 বিভাগগুলি ছেদ করলে আমি কীভাবে তা পরীক্ষা করতে পারি?
আমি নিম্নলিখিত তথ্য আছে:
Segment1 [ {x1,y1}, {x2,y2} ]
Segment2 [ {x1,y1}, {x2,y2} ]
2 লাইন ছেদ করছে কিনা তা সনাক্ত করতে পাইথনে একটি ছোট অ্যালগরিদম লিখতে হবে।
উত্তর:
একটি রেখার সমীকরণ হ'ল:
f(x) = A*x + b = y
একটি বিভাগের জন্য, এটি হুবহু একই, এক্স ব্যতীত একটি অন্তর অন্তর্ভুক্ত করা হয় except
যদি আপনার দুটি বিভাগ থাকে তবে নিম্নলিখিত হিসাবে সংজ্ঞায়িত:
Segment1 = {(X1, Y1), (X2, Y2)}
Segment2 = {(X3, Y3), (X4, Y4)}
সংযোগের সম্ভাব্য বিন্দুর আব্সিস জা (Xa, Ya) অবশ্যই অন্তর্ভুক্ত I1 এবং I2 উভয়ই অন্তর্ভুক্ত থাকতে হবে, নিম্নলিখিত হিসাবে সংজ্ঞায়িত:
I1 = [min(X1,X2), max(X1,X2)]
I2 = [min(X3,X4), max(X3,X4)]
এবং আমরা বলতে পারি যে জা এর মধ্যে অন্তর্ভুক্ত রয়েছে:
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
উভয় লাইনে দাঁড়িয়ে একটি বিন্দু (জা, ইয়া) অবশ্যই 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 কে আইএ'র অন্তর্ভুক্ত করা হয়েছে তা পরীক্ষা করে দেখুন:
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
এগুলি ছাড়াও, আপনি শুরুতে পরীক্ষা করতে পারেন যে প্রদত্ত চারটি পয়েন্টের মধ্যে দুটি সেই সমস্ত পরীক্ষা এড়াতে সমান নয়।
ব্যবহারকারী @ i_4_got পাইথনে খুব কার্যকরী সমাধান সহ এই পৃষ্ঠাটিতে দেখায়। আমি এখানে সুবিধার্থে এটি পুনরুত্পাদন করি (যেহেতু এটি এখানে পেয়ে আমাকে আনন্দিত করত):
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 পয়েন্টে পৃথক করার ধারণাটি।
এখন, আপনাকে "অ্যাঙ্করড" বিভাগের (অনলিফ্ট, অনরাইট বা কল্লাইনার) প্রতিটি পয়েন্টের আপেক্ষিক অবস্থানটি সন্ধান করতে হবে।
উভয় পয়েন্টের জন্য এটি করার পরে, পরীক্ষা করুন যে পয়েন্টগুলির একটি হ'ল অন-লেফট এবং অন্যটি অনরাইট (অথবা সম্ভবত আপনি যদি ভুলভাবে অন্তর্ভুক্ত করতে চান তবে কল্লিনিয়ার পজিশন অন্তর্ভুক্ত করুন) )।
তারপরে আপনাকে অবশ্যই অ্যাঙ্কর এবং পৃথক বিভাগগুলির ভূমিকা দিয়ে প্রক্রিয়াটি পুনরাবৃত্তি করতে হবে।
একটি ছেদটি বিদ্যমান থাকলে এবং কেবল যদি, পয়েন্টগুলির একটি হ'ল অন-লেফট এবং অন্যটি অনরাইট। প্রতিটি সম্ভাব্য মামলার উদাহরণ উদাহরণ সহ আরও বিশদ ব্যাখ্যার জন্য এই লিঙ্কটি দেখুন ।
ছেদ বিন্দুটি আবিষ্কার করে এমন একটি পদ্ধতি বাস্তবায়নের চেয়ে এ জাতীয় পদ্ধতির বাস্তবায়ন করা আরও সহজ হবে (অনেকগুলি ক্ষেত্রে যেমন আপনাকে পরিচালনা করতে হবে)।
হালনাগাদ
নিম্নলিখিত ক্রিয়াকলাপগুলির ধারণাটি উত্পন্ন করা উচিত (উত্স: সি তে কম্পিউটেশনাল জ্যামিতি )।
মন্তব্য: এই নমুনাটি পূর্ণসংখ্যার ব্যবহার অনুমান করে। আপনি যদি এর পরিবর্তে কিছু ভাসমান-পয়েন্ট উপস্থাপনা ব্যবহার করছেন (যা স্পষ্টতই বিষয়গুলিকে জটিল করে তুলতে পারে), তবে আপনাকে "সমতা" (বেশিরভাগ 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);
}
অবশ্যই, এই ফাংশনগুলি ব্যবহার করার সময়, অবশ্যই অবশ্যই প্রতিটি খণ্ডটি অন্য বিভাগের "মধ্যে" রয়েছে বলে মনে রাখতে হবে (যেহেতু এগুলি সীমাবদ্ধ বিভাগ, এবং অসীম রেখা নয়)।
এছাড়াও, এই ফাংশনগুলি ব্যবহার করে আপনি বুঝতে পারবেন যে আপনার কাছে সঠিক বা অনুপযুক্ত ছেদটি রয়েছে কিনা ।
ধরা যাক, দুটি বিভাগের এ, বি এবং সি, ডি সমাপ্তি রয়েছে। ছেদটি নির্ধারণের সাংখ্যিক শক্তিশালী উপায়টি হল চারটি নির্ধারকের চিহ্নটি পরীক্ষা করা:
| 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 |
ছেদ করার জন্য, বামে প্রতিটি নির্ধারকের ডানদিকে একটির বিপরীত চিহ্ন থাকতে হবে, তবে দুটি লাইনের মধ্যে কোনও সম্পর্ক থাকতে হবে না। আপনি অন্যান্য বিভাগের বিপরীতে লাইনটির বিপরীত দিকে অবস্থান করছেন কিনা তা নিশ্চিত করার জন্য আপনি মূলত অন্য সেগমেন্টের বিপরীতে একটি সেগমেন্টের প্রতিটি পয়েন্ট পরীক্ষা করছেন checking
এখানে দেখুন: http://www.cs.cmu.edu/~quake/robust.html
শেপলি লাইব্রেরিতে 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
লিরানের এবং গ্রুমড্রিগের দুর্দান্ত উত্তরের উপর ভিত্তি করে এখানে বন্ধ বিভাগগুলি ছেদ করে কিনা তা যাচাই করার জন্য একটি পাইথন কোডের একটি সম্পূর্ণ কোড । কলিনারি বিভাগগুলির জন্য কাজ করে, অক্ষগুলি Y এর সমান্তরাল বিভাগগুলি, অবনতিযুক্ত বিভাগগুলি (শয়তান বিশদে রয়েছে)। পূর্ণসংখ্যা স্থানাঙ্ক ধরে। সমতা পরীক্ষার পয়েন্টগুলিতে ফ্লোটিং পয়েন্টের স্থানাঙ্কগুলির একটি পরিবর্তন প্রয়োজন require
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)
এখানে ডেসমোসে একটি ভিজ্যুয়ালাইজেশন রয়েছে: লাইন সেগমেন্ট ছেদ
আপনার দুটি লাইনের বিভাগ রয়েছে। একটি বিভাগকে এন্ডপয়েন্ট পয়েন্ট এ এবং বি দ্বারা এবং দ্বিতীয় সেগমেন্টটি এন্ডপয়েন্টস সি এবং ডি দ্বারা সংজ্ঞায়িত করুন একটি দুর্দান্ত কৌশল আছে যেগুলি অবশ্যই ছেদ করতে হবে, সেগমেন্টের সীমানা ছাড়াই bound (নোট করুন যে লাইনগুলি সেগমেন্টের সীমা ছাড়িয়ে ছেদ করতে পারে, তাই আপনাকে অবশ্যই যত্নবান হতে হবে Good ভাল কোডটি সমান্তরাল রেখাগুলির জন্যও নজর রাখবে))
কৌশলটি হ'ল পরীক্ষাটি হ'ল যে বিন্দু A এবং B অবশ্যই লাইন সিডির বিপরীত দিকে লাইন করা উচিত, এবং যে বিন্দু সি এবং ডি অবশ্যই লাইন AB এর বিপরীত দিকে থাকা উচিত।
যেহেতু এটি হোমওয়ার্ক, আমি আপনাকে একটি স্পষ্ট সমাধান দেব না। তবে একটি বিন্দু কোন বিন্দুতে কোন বিন্দুতে পড়ে যায় তা দেখার জন্য একটি সহজ পরীক্ষা হ'ল বিন্দু পণ্য ব্যবহার করা। সুতরাং, একটি প্রদত্ত লাইন সিডির জন্য, সাধারণ ভেক্টরটিকে সেই লাইনের সাথে গণনা করুন (আমি এটিকে এন_সি বলব)) এখন কেবল এই দুটি ফলাফলের লক্ষণগুলি পরীক্ষা করুন:
dot(A-C,N_C)
এবং
dot(B-C,N_C)
যদি এই ফলাফলগুলির বিপরীত চিহ্ন থাকে তবে A এবং B লাইন সিডির বিপরীত দিক। এখন অন্য লাইনের জন্য একই পরীক্ষা করুন, এবি। এটিতে সাধারণ ভেক্টর এন_এ রয়েছে। এর লক্ষণগুলির সাথে তুলনা করুন
dot(C-A,N_A)
এবং
dot(D-A,N_A)
আমি কীভাবে একটি সাধারণ ভেক্টর গণনা করব তা নির্ধারণ করার জন্য এটি আপনার কাছে রেখে দেব। (২-ডি-তে, এটি তুচ্ছ, তবে আপনার কোডটি কি এ এবং বি স্বতন্ত্র পয়েন্ট কিনা তা নিয়ে চিন্তিত হবে? একইভাবে, সি এবং ডি পৃথক?)
একই সীমাহীন লাইনের সাথে থাকা লাইন বিভাগগুলি সম্পর্কে আপনার এখনও চিন্তিত হওয়া প্রয়োজন, অথবা যদি একটি পয়েন্টটি অন্য লাইনের অংশে পড়ে যায়। ভাল কোড প্রতিটি সম্ভাব্য সমস্যা পূরণ করবে।
লাইন বিভাগের বিপরীত দিকে দুটি পয়েন্ট রয়েছে কিনা তা পরীক্ষা করতে এখানে সি কোড দেওয়া আছে। এই কোডটি ব্যবহার করে আপনি দুটি বিভাগকে ছেদ করে কিনা তা পরীক্ষা করতে পারেন।
// 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));
}
বন্ধ বিভাগগুলি ছেদ করেছে কিনা তা যাচাই করার জন্য এখানে আরেকটি পাইথন কোড রয়েছে। এটি http://www.cdn.geeksforgeeks.org/check-if-two-given-line-setions-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 বিভাগগুলির জন্য, সিডির slালু সন্ধান করুন
slope=(Dy-Cy)/(Dx-Cx)
A এবং B এর উপরে সিডি প্রসারিত করুন, এবং সরাসরি উপরে যাওয়ার সিডির দূরত্বটি নিন
dist1=slope*(Cx-Ax)+Ay-Cy
dist2=slope*(Dx-Ax)+Ay-Dy
তারা বিপরীত দিকে আছে কিনা তা পরীক্ষা করুন
return dist1*dist2<0
যেহেতু আপনি উল্লেখ করেননি যে আপনি লাইনের ছেদ বিন্দুটি সন্ধান করতে চান, সমস্যাটি সমাধান করা সহজ হয়ে যায়। যদি আপনার ছেদ বিন্দুর প্রয়োজন হয় তবে ওএমজি_পিয়ানস দ্বারা উত্তর একটি দ্রুত পদ্ধতির। তবে, আপনি যদি কেবল লাইনগুলি ছেদ করছেন কিনা তা সন্ধান করতে চাইলে আপনি লাইন সমীকরণটি ব্যবহার করতে পারেন (ax + by + c = 0) ব্যবহার করে। পন্থাটি নিম্নরূপ:
আসুন দুটি লাইন বিভাগগুলি দিয়ে শুরু করা যাক: বিভাগ 1 এবং বিভাগ 2।
segment1 = [[x1,y1], [x2,y2]]
segment2 = [[x3,y3], [x4,y4]]
দুটি লাইন বিভাগগুলি শূন্য দৈর্ঘ্যের লাইন এবং স্বতন্ত্র বিভাগ নয় কিনা তা পরীক্ষা করুন।
এখান থেকে, আমি ধরে নিই যে দুটি বিভাগটি শূন্য-দৈর্ঘ্য এবং স্বতন্ত্র। প্রতিটি রেখাংশের জন্য, রেখার slাল গণনা করুন এবং তারপরে অক্ষের আকারে একটি রেখার সমীকরণ + + দ্বারা + সি = 0 অর্জন করুন, এখন, দুটি দফার জন্য f = ax + এর মানকে + 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]]
সেখান থেকে, আমরা টি এবং ইউ তে গণনা করে একটি ছেদ দেখতে চাই 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
লাইন ক্রসিং এবং যেখানে ছেদ ঘটে সেখানে যাবার জন্য এটি পরীক্ষা করার আমার উপায়। X4 এর মাধ্যমে 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
এখন, যদি ডিট, ডিট 1 এবং ডিট 2 সমস্ত শূন্য হয়, তবে আপনার লাইনগুলি সহ-লিনিয়ার এবং ওভারল্যাপ হতে পারে। যদি ডিটি শূন্য হয় তবে ডিট 1 বা ডিট 2 হয় না, তবে সেগুলি সহ-লিনিয়ার নয়, তবে সমান্তরাল হয়, সুতরাং কোনও ছেদ নেই। তাহলে এখন কী বাকি আছে যদি ডিটি শূন্য হয় তবে 2 ডি এর পরিবর্তে 1 ডি সমস্যা। আমাদের dx1 শূন্য কিনা তা নির্ভর করে দুটি উপায়ের একটি পরীক্ষা করতে হবে (তাই আমরা শূন্য দ্বারা বিভাগ এড়াতে পারি)। Dx1 যদি শূন্য হয় তবে কেবল নীচের x এর চেয়ে y মানগুলির সাথে একই যুক্তিটি করুন।
s = X3 / dx1
t = X4 / dx1
এটি দুটি স্কেলারের গণনা করে, যেমন আমরা যদি ভেক্টর (dx1, dy1) এর দ্বারা স্কেল করে পয়েন্ট পাই (x3, y3), এবং টি দ্বারা আমরা পাই (x4, y4)। সুতরাং s বা t যদি 0.0 এবং 1.0 এর মধ্যে হয় তবে আমাদের প্রথম লাইনে 3 বা 4 টি পয়েন্ট করুন। Gণাত্মক বলতে বোঝায় পয়েন্টটি আমাদের ভেক্টর শুরুর পিছনে রয়েছে, তবে> ০.০ এর অর্থ এটি আমাদের ভেক্টরের সমাপ্তির আগে আরও এগিয়ে রয়েছে। 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
আপনি যদি গণিতটি কী করছে তার আরও গভীর খনন করতে চাইলে ক্র্যামারের নিয়মটি দেখুন।
জর্জি দ্বারা উত্তর কার্যকরভাবে প্রয়োগ করা সবচেয়ে পরিষ্কার by এটিকে তাড়া করতে হয়েছিল, যেহেতু ব্রাইকবো উদাহরণ যেমন সহজ ছিল তবুও কোলিনারিটি নিয়ে সমস্যা ছিল।
পরীক্ষার জন্য কোড:
#!/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).
এই সহগটি যদি লাইন 1 এবং লাইন 2 উভয়ের জন্য সমান হয় তবে এর অর্থ লাইনটি সমান্তরাল। যদি তা না হয় তবে এর অর্থ তারা ছেদ করবে।
তারা যদি আপনার সাথে সমান্তরাল হয় তবে প্রমাণ করতে হবে যে তারা এক নয়। তার জন্য, আপনি গণনা করুন
beta = y1 - alpha*x1
বিটা যদি লাইন 1 এবং লাইন 2 এর জন্য সমান হয় তবে এর অর্থ এটি সমান হওয়ায় আপনি ছেদ করুন ect
যদি সেগমেন্ট হয়, তবুও আপনাকে প্রতিটি লাইনের উপরে বর্ণিত হিসাবে আলফা এবং বিটা গণনা করতে হবে। তারপরে আপনাকে দেখতে হবে যে (বিটা 1 - বিটা 2) / (আলফা 1 - আলফা 2) ন্যূনতম (x1_line1, x2_line1) এর চেয়ে বড় এবং সর্বোচ্চ (x1_line1, x2_line1) এর চেয়ে কম
এটি আমি এএস 3 এর জন্য পেয়েছি, অজগর সম্পর্কে খুব বেশি কিছু জানেন না তবে ধারণাটি রয়েছে
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();
}
জাভাতে প্রয়োগ করা হয়েছে। তবে মনে হয় এটি সহ-লিনিয়ার লাইনগুলির জন্য কাজ করে না (একে অপরের মধ্যে বিদ্যমান লাইন বিভাগগুলি ওরফ লাইন (0,0) (10,10) এল 2 (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
আমি ভেবেছিলাম আমি একটি দুর্দান্ত সুইফট সমাধানটিতে অবদান রাখব:
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
}
উপরের সমাধানগুলির মধ্যে একটি এত ভাল কাজ করেছে আমি ডাব্লুএক্সপিথন ব্যবহার করে একটি সম্পূর্ণ বর্ধন কর্মসূচী লেখার সিদ্ধান্ত নিয়েছি। আপনার এই প্রোগ্রামটি এইভাবে চালাতে সক্ষম হওয়া উচিত: অজগর " আপনার ফাইলের নাম "
# 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()
ওএমজি_পিন্টস সমাধানটি ব্যবহার করে , আমি এসকিউএল অনুবাদ করেছি translated (হানা স্কেলার ফাংশন)
ধন্যবাদ ওএমজি_পিন্টস, এটি দুর্দান্ত কাজ করে। আমি বৃত্তাকার পৃথিবী ব্যবহার করছি, তবে দূরত্বগুলি খুব কম, তাই আমি এটি ঠিক করেছি figure
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;
সমাধান হয়েছে তবে এখনও অজগর দিয়ে কেন নয় ... :)
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