আমি কীভাবে দুটি বিভাগকে ছেদ করে তা পরীক্ষা করতে পারি?


90

2 বিভাগগুলি ছেদ করলে আমি কীভাবে তা পরীক্ষা করতে পারি?

আমি নিম্নলিখিত তথ্য আছে:

Segment1 [ {x1,y1}, {x2,y2} ]
Segment2 [ {x1,y1}, {x2,y2} ] 

2 লাইন ছেদ করছে কিনা তা সনাক্ত করতে পাইথনে একটি ছোট অ্যালগরিদম লিখতে হবে।


বিকল্প পাঠ


উত্তর:


62

একটি রেখার সমীকরণ হ'ল:

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

এগুলি ছাড়াও, আপনি শুরুতে পরীক্ষা করতে পারেন যে প্রদত্ত চারটি পয়েন্টের মধ্যে দুটি সেই সমস্ত পরীক্ষা এড়াতে সমান নয়।


4
খণ্ডগুলি, সেগমেন্টগুলি, দুঃখিত। আপনি কি আপনার উত্তর প্রদত্ত বিভাগগুলি আপডেট করতে পারবেন?
aneuryzm

13
এটি এত জটিল নয়, আমি একটি বোঝার উদ্দেশ্যে প্রচুর (অপ্রয়োজনীয়?) মধ্যবর্তী পদক্ষেপ লিখেছি wrote প্রয়োগগুলির মূল পয়েন্টগুলি হ'ল: পারস্পরিক ব্যবধানের অস্তিত্ব পরীক্ষা করুন, A1, A2, b1, b2 এবং Xa গণনা করুন এবং তারপরে Xa পারস্পরিক ব্যবধানে অন্তর্ভুক্ত রয়েছে কিনা তা পরীক্ষা করুন।
এগুলি

4
A1 - A2 কখনই শূন্য হবে না কারণ যদি (A1 == A2) সেই ক্ষেত্রে এই গণনার আগে ফিরে আসত।
inkredibl

4
যদি এ 1 == এ 2 এবং বি 1 ==
বি

4
সূত্র A1 * x + b1 = y উল্লম্ব লাইনগুলি পরিচালনা করে না তাই উল্লম্ব বিভাগগুলি এই পদ্ধতির সাথে পৃথকভাবে পরিচালনা করা উচিত।
দিমিত্রি

77

ব্যবহারকারী @ 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)

8
খুব সাধারণ এবং মার্জিত, তবে এটি কোলিনারিটির সাথে ভালভাবে মোকাবেলা করে না এবং এই উদ্দেশ্যে আরও কোডের প্রয়োজন।
চার্লস

7
সমাধানের ক্ষেত্রেও যে সমাধান রয়েছে তা geeforforgeeks.org/check-if-two-given-line-setions-intersect
জসোল্ট সাফরনি

এই সমাধান ভালবাসা। খুব সহজ এবং সংক্ষিপ্ত! আমি একটি ডাব্লুএক্সপিথন প্রোগ্রাম তৈরি করেছি যা একটি লাইন আঁকে এবং এটি অন্য লাইনের সাথে ছেদ করে কিনা তা দেখুন। আমি এটি এখানে রাখতে পারিনি তাই এটি এই মন্তব্যের নীচে।
ব্যবহারকারী 1766438

33

সেগমেন্টগুলি কোথায় ছেদ করে ঠিক সেখানে আপনাকে গণনা করতে হবে না , তবে কেবল তারা বুঝতে পারে যে তারা আদৌ ছেদ করেছে কিনা । এটি সমাধানটিকে সহজতর করবে।

একটি বিভাগকে "অ্যাঙ্কর" হিসাবে বিবেচনা করা এবং দ্বিতীয় বিভাগটিকে 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);
}

অবশ্যই, এই ফাংশনগুলি ব্যবহার করার সময়, অবশ্যই অবশ্যই প্রতিটি খণ্ডটি অন্য বিভাগের "মধ্যে" রয়েছে বলে মনে রাখতে হবে (যেহেতু এগুলি সীমাবদ্ধ বিভাগ, এবং অসীম রেখা নয়)।

এছাড়াও, এই ফাংশনগুলি ব্যবহার করে আপনি বুঝতে পারবেন যে আপনার কাছে সঠিক বা অনুপযুক্ত ছেদটি রয়েছে কিনা ।

  • যথাযথ : কোনও কলিনারি পয়েন্ট নেই। বিভাগগুলি একে অপরকে "পাশ থেকে একপাশে" অতিক্রম করে।
  • অনুপযুক্ত : একটি বিভাগ কেবলমাত্র অন্যটিকে "স্পর্শ" করে (পয়েন্টগুলির মধ্যে কমপক্ষে একটি অ্যাঙ্করড অংশে কলিনারি)।

আমার পছন্দটিও +1 খুব সুন্দর। পয়েন্টগুলি একে অপরের সাথে সম্পর্কিত হওয়ার বিষয়ে আপনি যদি কেবল চিন্তা করেন, তবে আপনি সিদ্ধান্ত নিতে পারেন যে তাদের বিভাগগুলি অবশ্যই ছেদ করতে হবে কিনা, কিছুই গণনা ছাড়াই।
জোচেন রিটজেল

এবং @ THC4k উহম, এটি আসলে পরিষ্কার নয়। বা উদাহরণস্বরূপ চিত্রটিতে আমি যুক্ত করা ইমেজটি পরীক্ষা করুন: 2 পয়েন্টগুলি "অন-লেফট" এবং "অনরাইট" তবে 2 টি বিভাগগুলি ছেদ করছে না।
aneuryzm

@ পেট্রিক, আসলে না কোন অংশটি "অ্যাঙ্কর" নির্ভর করে তারপরে উভয় পয়েন্টই হয় অনন্যফিট বা এই ক্ষেত্রে অনরাইট। (আমার আপডেট হওয়া উত্তরটি দেখুন)।
লিরান

4
+1 আমি এই সমস্যার কয়েক ডজন উত্তর দেখেছি তবে এটি এখন পর্যন্ত সবচেয়ে পরিষ্কার, সরল এবং সবচেয়ে দক্ষ যেটি আমি দেখেছি। :)
মিগুয়েল

16

ধরা যাক, দুটি বিভাগের এ, বি এবং সি, ডি সমাপ্তি রয়েছে। ছেদটি নির্ধারণের সাংখ্যিক শক্তিশালী উপায়টি হল চারটি নির্ধারকের চিহ্নটি পরীক্ষা করা:

| 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


এটি কি অনুচিত ছেদগুলির জন্য কাজ করে যখন ছেদ বিন্দু যখন একটি লাইন বিভাগে থাকে?
সায়াম কাজী

@ সাইয়ামকাজি মনে হয় আপনি যদি কমপক্ষে কোনও লাইন বিভাগের শেষ পয়েন্টটি পাস করেন তবে এটি ছেদটি ব্যর্থ হতে পারে। যদি আপনি এই বিভাগটিতে থাকেন: আমি ধরে নিয়েছি এটি 0 বনাম 1 / -1 তুলনা হবে, সুতরাং এটি কোনও ছেদটি সনাক্ত করতে পারে না।
ওয়ার্টি

4
যাইহোক, এটি ব্যাখ্যা করার জন্য: প্রতিটি নির্ধারক দুটি লাইন বিভাগের ভেক্টর সমাপ্তি পয়েন্টের ক্রস-প্রোডাক্টটি গণনা করছে। উপরের বামটি সিএ এক্স সিবি বনাম শীর্ষ ডান ডিএ এক্স ডিবি, উদাহরণস্বরূপ। এটি মূলত পরীক্ষা করে যে কোন প্রান্তটি (ঘড়ির কাঁটা) উপর রয়েছে side তবুও এটি কীভাবে লাইন বিভাগগুলিতে কাজ করে যা সীমাহীনভাবে প্রসারিত হয় না তা জানার চেষ্টা করছি।
ওয়ার্টি 18

7

শেপলি লাইব্রেরিতে 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

এখানে চিত্র বর্ণনা লিখুন


6

লিরানের এবং গ্রুমড্রিগের দুর্দান্ত উত্তরের উপর ভিত্তি করে এখানে বন্ধ বিভাগগুলি ছেদ করে কিনা তা যাচাই করার জন্য একটি পাইথন কোডের একটি সম্পূর্ণ কোড । কলিনারি বিভাগগুলির জন্য কাজ করে, অক্ষগুলি 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

"বদ্ধ বিভাগ" এর অর্থ কী?
স্যাম

@ সাম ক্লোজড সেগমেন্টে এর শেষ পয়েন্ট রয়েছে। উদাহরণস্বরূপ আর থেকে পয়েন্টগুলির একটি বদ্ধ বিভাগটি হবে [0, 1] (0 <= x <= 1) বিপরীতে] 0, 1] (0 <x <= 1)
দিমিত্রি

5

এখানে ডট পণ্য ব্যবহার করে একটি সমাধান দেওয়া হয়েছে:

# 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)

এখানে ডেসমোসে একটি ভিজ্যুয়ালাইজেশন রয়েছে: লাইন সেগমেন্ট ছেদ


এটি দুর্দান্ত, এবং আমি ডেসমোস সম্পর্কে ভুলে গেছি - এটি এই সমস্যার জন্য উপযুক্ত! ধন্যবাদ!
পোনাড্টো

আপনার সমাধানটিকে ভালবাসুন তবে মনে হচ্ছে এটি ব্যর্থ হয়েছে যদি দুটি লাইনের বিভাগগুলি লাইনে থাকে
এইচ পোপ

খুব সুন্দর. অন্য যে কোনও ব্যক্তিকে এটি আলাদা ভাষায় পোর্ট করার জন্য, নিশ্চিত করুন যে ভাসা বা ইন্টু 64৪ এর একটি ইন্টিওরিও 1280x720 এর চেয়ে কম সংখ্যায় খুব দ্রুত উপচে পড়বে
এই লোকটি

4

আপনার দুটি লাইনের বিভাগ রয়েছে। একটি বিভাগকে এন্ডপয়েন্ট পয়েন্ট এ এবং বি দ্বারা এবং দ্বিতীয় সেগমেন্টটি এন্ডপয়েন্টস সি এবং ডি দ্বারা সংজ্ঞায়িত করুন একটি দুর্দান্ত কৌশল আছে যেগুলি অবশ্যই ছেদ করতে হবে, সেগমেন্টের সীমানা ছাড়াই 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)

আমি কীভাবে একটি সাধারণ ভেক্টর গণনা করব তা নির্ধারণ করার জন্য এটি আপনার কাছে রেখে দেব। (২-ডি-তে, এটি তুচ্ছ, তবে আপনার কোডটি কি এ এবং বি স্বতন্ত্র পয়েন্ট কিনা তা নিয়ে চিন্তিত হবে? একইভাবে, সি এবং ডি পৃথক?)

একই সীমাহীন লাইনের সাথে থাকা লাইন বিভাগগুলি সম্পর্কে আপনার এখনও চিন্তিত হওয়া প্রয়োজন, অথবা যদি একটি পয়েন্টটি অন্য লাইনের অংশে পড়ে যায়। ভাল কোড প্রতিটি সম্ভাব্য সমস্যা পূরণ করবে।


3

লাইন বিভাগের বিপরীত দিকে দুটি পয়েন্ট রয়েছে কিনা তা পরীক্ষা করতে এখানে সি কোড দেওয়া আছে। এই কোডটি ব্যবহার করে আপনি দুটি বিভাগকে ছেদ করে কিনা তা পরীক্ষা করতে পারেন।

// 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));

}


3

বন্ধ বিভাগগুলি ছেদ করেছে কিনা তা যাচাই করার জন্য এখানে আরেকটি পাইথন কোড রয়েছে। এটি 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))

4
closed_segment_intersect()পরীক্ষার কোড থেকে সংজ্ঞায়িত করা হয় না।
hhquark

4
@hhquark আপনাকে ধন্যবাদ আমি এখন এই লাইনগুলি সরিয়েছি। আমার প্রয়োগটি অন্য উত্তর থেকে প্রয়োগের সাথে সম্মত কিনা তা যাচাই করার জন্য আমি এই লাইনগুলি অন্তর্ভুক্ত করেছি ( stackoverflow.com/a/18524383/7474256 , আমি মনে করি)।
ফ্যাবিয়ান ইয়ং

1

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

আপনি কি সূত্র সম্পর্কে নিশ্চিত? কারণ বি এর স্থানাঙ্কগুলি ব্যবহৃত হয় না, সুতরাং আপনি কীভাবে সমস্ত 4 টি উল্লম্ব বিবেচনা না করে AB এবং CD এর ছেদটি খুঁজে পাবেন?
ম্যাক

4
আমি মনে করি এখানে থাকা উচিত: ডিস্ট 2 = opeাল * (ডিএক্স-বিএক্স) + বাই
ডায়

1

যেহেতু আপনি উল্লেখ করেননি যে আপনি লাইনের ছেদ বিন্দুটি সন্ধান করতে চান, সমস্যাটি সমাধান করা সহজ হয়ে যায়। যদি আপনার ছেদ বিন্দুর প্রয়োজন হয় তবে ওএমজি_পিয়ানস দ্বারা উত্তর একটি দ্রুত পদ্ধতির। তবে, আপনি যদি কেবল লাইনগুলি ছেদ করছেন কিনা তা সন্ধান করতে চাইলে আপনি লাইন সমীকরণটি ব্যবহার করতে পারেন (ax + by + c = 0) ব্যবহার করে। পন্থাটি নিম্নরূপ:

  1. আসুন দুটি লাইন বিভাগগুলি দিয়ে শুরু করা যাক: বিভাগ 1 এবং বিভাগ 2।

    segment1 = [[x1,y1], [x2,y2]]
    segment2 = [[x3,y3], [x4,y4]]
    
  2. দুটি লাইন বিভাগগুলি শূন্য দৈর্ঘ্যের লাইন এবং স্বতন্ত্র বিভাগ নয় কিনা তা পরীক্ষা করুন।

  3. এখান থেকে, আমি ধরে নিই যে দুটি বিভাগটি শূন্য-দৈর্ঘ্য এবং স্বতন্ত্র। প্রতিটি রেখাংশের জন্য, রেখার 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);
    
  4. এখন যা বাকি আছে তা হ'ল বিভিন্ন কেস। যদি কোনও পয়েন্টের জন্য f = 0 হয়, তবে দুটি লাইন একটি বিন্দুতে স্পর্শ করে। যদি f1_1 এবং f1_2 সমান বা f2_1 এবং f2_2 সমান হয় তবে লাইনগুলি ছেদ করে না। যদি f1_1 এবং f1_2 অসম হয় এবং f2_1 এবং f2_2 অসম হয়, তবে রেখাংশগুলি ছেদ করে। আপনি যে লাইনগুলিকে "ছেদ করা" হিসাবে বিবেচনা করছেন তা বিবেচনা করতে চান কিনা তার উপর নির্ভর করে আপনি আপনার অবস্থার সাথে মানিয়ে নিতে পারেন।


এই কোডটি গণনা করে না a1এবং এটি অर्थোগোনাল লাইনের জন্য কাজ করে না।
বিজার্ন লিন্ডকভিস্ট

1

আমরা এই ব্যবহারকারী ভেক্টরগুলিও সমাধান করতে পারি।

এর বিভাগগুলি হিসাবে সংজ্ঞায়িত করা যাক [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

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

আপনি যদি গণিতটি কী করছে তার আরও গভীর খনন করতে চাইলে ক্র্যামারের নিয়মটি দেখুন।


4
টাইপো: "dx2 = X4 - X4" "dx2 = X4 - X3" হওয়া উচিত
geowar

1

জর্জি দ্বারা উত্তর কার্যকরভাবে প্রয়োগ করা সবচেয়ে পরিষ্কার 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))

0

যদি আপনার ডেটা লাইনের সংজ্ঞা দেয় তবে আপনাকে কেবল প্রমাণ করতে হবে যে তারা সমান্তরাল নয়। এটি করতে আপনি গণনা করতে পারেন

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) এর চেয়ে কম


0

আপনার বিভাগগুলিতে স্থাপন রেখার ছেদ বিন্দু গণনা করুন (এর অর্থ মূলত একটি রৈখিক সমীকরণ সিস্টেমটি সমাধান করা), তারপরে পরীক্ষা করুন যে এটি আপনার বিভাগগুলির শুরু এবং শেষ পয়েন্টগুলির মধ্যে কিনা।


0

এটি আমি এএস 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,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

0

আমি ভেবেছিলাম আমি একটি দুর্দান্ত সুইফট সমাধানটিতে অবদান রাখব:

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

}

0

উপরের সমাধানগুলির মধ্যে একটি এত ভাল কাজ করেছে আমি ডাব্লুএক্সপিথন ব্যবহার করে একটি সম্পূর্ণ বর্ধন কর্মসূচী লেখার সিদ্ধান্ত নিয়েছি। আপনার এই প্রোগ্রামটি এইভাবে চালাতে সক্ষম হওয়া উচিত: অজগর " আপনার ফাইলের নাম "

# 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()

0

ওএমজি_পিন্টস সমাধানটি ব্যবহার করে , আমি এসকিউএল অনুবাদ করেছি 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;

-2

সমাধান হয়েছে তবে এখনও অজগর দিয়ে কেন নয় ... :)

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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.