বহুভুজ পয়েন্টগুলির একটি তালিকা ঘড়ির কাঁটার ক্রমে রয়েছে কীভাবে তা নির্ধারণ করবেন?


259

পয়েন্টগুলির একটি তালিকা থাকা, তারা কীভাবে ঘড়ির কাঁটার দিকে থাকে তা আমি কীভাবে খুঁজে পাব?

উদাহরণ স্বরূপ:

point[0] = (5,0)
point[1] = (6,4)
point[2] = (4,5)
point[3] = (1,5)
point[4] = (1,0)

বলবে যে এটি ঘড়ির কাঁটা বিরোধী (বা কিছু লোকের জন্য ঘড়ির কাঁটার বিপরীতে)।


4
অনুগ্রহ করে নোট করুন: গৃহীত উত্তর, এবং এর পরে অনেক উত্তরগুলির জন্য প্রচুর সংযোজন এবং গুণগুলি প্রয়োজন (এগুলি ক্ষেত্রের গণনার ভিত্তিতে হয় যা নেতিবাচক বা ধনাত্মক সমাপ্ত হয়; যেমন "জুতার সূত্র")। এর মধ্যে একটি বাস্তবায়নের আগে, lhf এর উত্তরটি বিবেচনা করুন , যা সহজ / দ্রুত - উইকির উপর ভিত্তি করে - সাধারণ বহুভুজের অভিমুখীকরণ
টুলমেকারস্টেভ

আমি সবসময় এটি দুটি সংলগ্ন ভেক্টরগুলির ক্রস প্রোডাক্টের বিবেচনায় ভাবি। আমি যদি বহুভুজের পরিধি ঘুরে বেড়াতে পারি তবে আমার মাথাটি বিমান থেকে বেরিয়ে আসে। আমার স্থানাঙ্ক সিস্টেমে তৃতীয় দিক পেতে আমি বিমানের ভেক্টরটির বাইরে আমার হাঁটার দিকের ভেক্টরে প্রবেশ করি। যদি সেই ভেক্টরটি নির্দেশ করে যাতে অভ্যন্তরটি আমার বাম দিকে থাকে তবে এটি ঘড়ির কাঁটার বিপরীতে থাকে; যদি অভ্যন্তরটি আমার ডানদিকে থাকে তবে এটি ঘড়ির কাঁটার দিকে।
duffymo

উত্তর:


416

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

প্রান্তগুলি জুড়ে, (x 2 - x 1 ) (y 2 + y 1 )। ফলাফলটি যদি ইতিবাচক হয় তবে বক্রটি ঘড়ির কাঁটার দিকে হয়, যদি এটি নেতিবাচক হয় তবে বক্রটি ঘড়ির কাঁটার বিপরীতে থাকে। (ফলাফলটি +/- কনভেনশন সহ দ্বিগুণ আবদ্ধ অঞ্চল is

point[0] = (5,0)   edge[0]: (6-5)(4+0) =   4
point[1] = (6,4)   edge[1]: (4-6)(5+4) = -18
point[2] = (4,5)   edge[2]: (1-4)(5+5) = -30
point[3] = (1,5)   edge[3]: (1-1)(0+5) =   0
point[4] = (1,0)   edge[4]: (5-1)(0+0) =   0
                                         ---
                                         -44  counter-clockwise

28
এটি ক্যালকুলাস একটি সাধারণ ক্ষেত্রে প্রয়োগ করা হয়। (গ্রাফিক্স পোস্ট করার দক্ষতা আমার নেই।) একটি লাইন বিভাগের আওতাভুক্ত অঞ্চলটি তার দৈর্ঘ্যের দৈর্ঘ্যের (x2-x1) এর গড় উচ্চতা (y2 + y1) / 2 গুণ সমান। এক্স সাইন কনভেনশন লক্ষ্য করুন। কিছু ত্রিভুজ দিয়ে এটি ব্যবহার করে দেখুন আপনি কীভাবে এটি কাজ করছেন তা শীঘ্রই দেখতে পাবেন।
বিটা

72
একটি ছোটখাটো সতর্কতা: এই উত্তরটি একটি সাধারণ কার্তেসিয়ান সমন্বয় ব্যবস্থা গ্রহণ করে। যে কারণে এটি উল্লেখযোগ্য তা হল হ'ল এইচটিএমএল 5 ক্যানভাসের মতো কিছু সাধারণ প্রসঙ্গ একটি উল্টানো ওয়াই-অক্ষ ব্যবহার করে। তারপরে নিয়মটি উল্টাতে হবে: যদি অঞ্চলটি নেতিবাচক হয় তবে বাঁকটি ঘড়ির কাঁটার দিকে।
LarsH

8
@ মিঃ কিউবিস: সুতরাং আমার পদ্ধতিটি কাজ করে তবে আপনি যদি কোনও গুরুত্বপূর্ণ অংশটি এড়িয়ে যান তবে তা কার্যকর হয় না। এটি কোনও সংবাদ নয়।
বিটা

11
@ মিঃ কিউবিস: আপনাকে সর্বদা সর্বশেষ পয়েন্টটি প্রথমটির সাথে যুক্ত করতে হবে। আপনার যদি 0 থেকে N-1 পর্যন্ত N পয়েন্ট রয়েছে, তবে আপনাকে অবশ্যই গণনা করতে হবে: Sum( (x[(i+1) mod N] - x[i]) * (y[i] + y[(i+1) mod N]) )i = 0 থেকে N-1 এর জন্য। উদাহরণস্বরূপ, সূচিটি অবশ্যই মডুলো এন ( N ≡ 0) নিতে হবে সূত্রটি কেবল বদ্ধ বহুভুজগুলির জন্য কাজ করে । বহুভুজগুলির কোনও কল্পিত প্রান্ত নেই।
অলিভিয়ার জ্যাকট-ডেসকোম্বেস

4
এই ব্লগ.ইলেটমেন্ট৪৪ / পলিগন-উইন্ডিং এইচটিএমএল সহজ ইংরেজীতে ব্যাখ্যা করে যে এই সমাধানটি কেন কাজ করে।
ডেভিড জোরিচটা

49

ক্রস পণ্য দুই ভেক্টর ঋজু-অন্তরীপ ডিগ্রী পরিমাপ। কল্পনা করুন যে আপনার বহুভুজের প্রতিটি প্রান্তটি ত্রিমাত্রিক (3-ডি) জাইজেড স্পেসের এক্সওয়াই প্লেনের ভেক্টর। তারপরে দুটি ধারাবাহিক প্রান্তের ক্রস প্রোডাক্টটি z- দিকের একটি ভেক্টর, (দ্বিতীয় বিভাগটি যদি ঘড়ির কাঁটার দিকে থাকে তবে বিয়োগক্ষেত্র- z- দিক যদি এটি ঘড়ির কাঁটার দিকে থাকে)। এই ভেক্টরের প্রস্থটি দুটি মূল প্রান্তের মধ্যবর্তী কোণের সমান সমানুপাতিক, তাই এটি লম্ব যখন হয় তখন এটি সর্বাধিক পৌঁছে যায় এবং প্রান্তগুলি সমান্তরাল (সমান্তরাল) হলে অদৃশ্য হয়ে যায়।

সুতরাং, বহুভুজের প্রতিটি প্রান্তের (বিন্দু) জন্য দুটি সংলগ্ন প্রান্তের ক্রস-প্রোডাক্ট প্রস্থের গণনা করুন:

Using your data:
point[0] = (5, 0)
point[1] = (6, 4)
point[2] = (4, 5)
point[3] = (1, 5)
point[4] = (1, 0)

তাই পরপর প্রান্ত লেবেল হিসাবে
edgeAথেকে সেগমেন্ট হয় point0থেকে point1এবং
edgeBমধ্যে point1থেকে point2
...
edgeEমধ্যে point4এবং point0

তারপরে ভার্টেক্স এ ( point0)
edgeE[থেকে point4থেকে point0]
edgeA[ point0পয়েন্ট 1 'এর মধ্যে রয়েছে

এই দুটি প্রান্তটি তারা নিজেরাই ভেক্টর, যার x এবং y স্থানাঙ্কগুলি তাদের শুরু এবং শেষের পয়েন্টগুলির স্থানাঙ্কগুলি বিয়োগ করে নির্ধারণ করা যেতে পারে:

edgeE= point0- point4= (1, 0) - (5, 0)= (-4, 0) এবং
edgeA= point1- point0= (6, 4) - (1, 0)= (5, 4) এবং

এই দু'টি সংলগ্ন প্রান্ত ক্রস পণ্য নিম্নলিখিত ম্যাট্রিক্স, যা অক্ষ তুল্য চিহ্ন তিনটি প্রতিনিধিত্বমূলক নিচের দুটি ভেক্টর স্থানাঙ্ক রেখে নির্মান করা হয় নির্ধারক ব্যবহার করে হিসাব করা হয় ( i, j, & k)। তৃতীয় (শূন্য) -মুল্য স্থানাংক সেখানে রয়েছে কারণ ক্রস পণ্য ধারণাটি 3-ডি নির্মাণ, এবং সুতরাং আমরা ক্রস-পণ্য প্রয়োগের জন্য এই 2-ডি ভেক্টরগুলিকে 3-ডি-তে প্রসারিত করি:

 i    j    k 
-4    0    0
 1    4    0    

সমস্ত ক্রস-প্রোডাক্টগুলি দুটি ভেক্টরের গুণমানের সমতলের জন্য একটি ভেক্টর লম্বকে উত্পাদন করে, উপরের ম্যাট্রিক্সের নির্ধারকটির কেবলমাত্র একটি k, (বা জেড-অক্ষ) উপাদান রয়েছে। Z বা অক্ষের উপাদানটির परिमाण
গণনা করার সূত্রটি = k
a1*b2 - a2*b1 = -4* 4 - 0* 1-16

এই মানটির परिमाण ( -16), 2 টি ভেক্টরগুলির দৈর্ঘ্যের গুণফল দ্বারা গুণিত 2 মূল ভেক্টরগুলির মধ্যে কোণের সাইনগুলির একটি পরিমাপ।
আসলে, এর মানটির জন্য অন্য একটি সূত্র
A X B (Cross Product) = |A| * |B| * sin(AB)

সুতরাং, -16দুটি ভেক্টরগুলির প্রস্থের গুণমানের দ্বারা , এই মানটি ( )) কে ভাগ করার জন্য আপনাকে একটি কোণে কিছুটা ফিরে যেতে হবে ।

|A| * |B| = 4 * Sqrt(17) =16.4924...

সুতরাং পাপের পরিমাপ (AB) = -16 / 16.4924=-.97014...

এটি ভার্টেক্সের পরের অংশটি বাম বা ডানদিকে বাঁকানো হয়েছে কিনা এবং কতটা তার একটি পরিমাপ। তোরণ-সাইন নেওয়ার দরকার নেই। আমরা যা যা যত্ন করব তা হ'ল তার দৈর্ঘ্য এবং অবশ্যই এর চিহ্ন (ধনাত্মক বা নেতিবাচক)!

বন্ধ পথের চারপাশে অন্যান্য 4 টি পয়েন্টের প্রতিটি এটির জন্য করুন এবং প্রতিটি গণমাধ্যমে এই গণনা থেকে মান যুক্ত করুন ..

যদি চূড়ান্ত যোগফল ইতিবাচক হয় তবে আপনি ঘড়ির কাঁটার দিকে, নেতিবাচক, ঘড়ির কাঁটার দিকে চলে গিয়েছিলেন।


3
আসলে, এই সমাধানটি গৃহীত সমাধানের চেয়ে আলাদা সমাধান। তারা সমতুল্য কিনা তা আমি অনুসন্ধান করছি, তবে আমার সন্দেহ হয় যে তারা তা নয় ... গৃহীত উত্তর বহুভুজের উপরের প্রান্তের অধীনে এবং এর অধীনে থাকা অঞ্চলটির মধ্যে পার্থক্য গ্রহণ করে বহুভুজের ক্ষেত্রফল গণনা করে বহুভুজের নীচের প্রান্ত একটি নেতিবাচক হবে (একটি যেখানে আপনি বাম থেকে ডানে পাড়ি দিচ্ছেন), এবং অন্যটি নেতিবাচক হবে। ঘড়ির কাঁটার দিকে ট্র্যাভার করার সময়, উপরের প্রান্তটি বাম থেকে ডানদিকে ট্র্যাশ করা হয় এবং এটি আরও বড় হয়, সুতরাং মোটটি ইতিবাচক।
চার্লস ব্রেটানা

1
আমার সমাধান প্রতিটি শীর্ষবিন্দুতে প্রান্ত কোণে পরিবর্তনের সাইনের যোগফল পরিমাপ করে। ঘড়ির কাঁটার দিক দিয়ে ট্র্যাভার করার সময় এটি ইতিবাচক হবে এবং যখন ঘড়ির কাঁটার বিপরীতে ট্র্যাভার করবে তখন negativeণাত্মক হবে।
চার্লস ব্রেটানা

2
এই পদ্ধতির সাথে মনে হয় আপনার আরকসিন নেওয়ার দরকার নেই, যদি না আপনি উত্তেজকতা ধরে না নেন (এই ক্ষেত্রে আপনার কেবলমাত্র একটি শীর্ষবিন্দু পরীক্ষা করতে হবে)
এজেন্ট

2
আপনার আরকসিন নেওয়া দরকার। এলোমেলো নন-উত্তল বহুভুজগুলির একগুচ্ছ এটি ব্যবহার করে দেখুন এবং আপনি অর্কসিন না নিলে পরীক্ষাটি বহুভুজগুলির জন্য ব্যর্থ হবে find
লুক হাচিসন

1
@ চার্লসব্রেটানা - যদিও আমি লুকের পরীক্ষা চালাচ্ছি না, আমি বিশ্বাস করি তিনি সঠিক is এটাই প্রকৃতি summing একটি সঙ্গে মিলিত অরৈখিক স্কেল [arcsin বনাম arcsin সঙ্গে ছাড়া]। মার্শবার কী পরামর্শ দিয়েছে তা বিবেচনা করুন, যা আপনি সঠিকভাবে প্রত্যাখ্যান করেছেন। তিনি আপনাকে "মাত্র গণনা" করার পরামর্শ দিয়েছিলেন, এবং আপনি উল্লেখ করেছেন যে মুষ্টিমেয় বিশাল মূল্যবোধগুলি ছোট সংখ্যার সংখ্যাকে ছাড়িয়ে যেতে পারে। এখন প্রতিটি মান বনাম আরকসিন বিবেচনা করুন। এখনও কি এমনটি হয় না যে আরকসিন নিতে ব্যর্থ হওয়া প্রতিটি মানকেই ভুল ওজন দেয়, সুতরাং একই ত্রুটি রয়েছে (যদিও এত কম)?
নির্মাতা স্টিভ

47

আমি অনুমান করি এটি একটি পুরানো প্রশ্ন, তবে আমি যেভাবেই হোক না কেন অন্য সমাধান বের করতে যাচ্ছি, কারণ এটি সোজা এবং গাণিতিকভাবে নিবিড় নয় - এটি কেবল মৌলিক বীজগণিত ব্যবহার করে। বহুভুজের স্বাক্ষরিত অঞ্চল গণনা করুন। যদি এটি নেতিবাচক হয় তবে পয়েন্টগুলি ঘড়ির কাঁটার দিকে থাকে, যদি এটি ইতিবাচক হয় তবে তারা ঘড়ির কাঁটার বিপরীতে থাকে। (এটি বিটার সমাধানের সাথে খুব মিল) is

স্বাক্ষরিত অঞ্চলটি গণনা করুন: এ = 1/2 * (x 1 * y 2 - x 2 * y 1 + x) 2 * ই 3 - এক্স 3 * ই 2 + ... + এক্স এন * ইয় 1 - এক্স 1 * y এন )

বা সিউডো কোডে:

signedArea = 0
for each point in points:
    x1 = point[0]
    y1 = point[1]
    if point is last point
        x2 = firstPoint[0]
        y2 = firstPoint[1]
    else
        x2 = nextPoint[0]
        y2 = nextPoint[1]
    end if

    signedArea += (x1 * y2 - x2 * y1)
end for
return signedArea / 2

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

সূত্র: http://mathworld.wolfram.com/PolygonArea.html


এটি কি আপনার উপরে স্বাক্ষরিত অঞ্চল সূত্রের একটি টাইপো ছিল? এটি "xn * y1 - x1 * yn" দিয়ে শেষ হয়; যখন আমি বিশ্বাস করি এটি "x_n y_ {n + 1} - y_n x_ {n-1}" হওয়া উচিত (কমপক্ষে ল্যাটেক্সে)। অন্যদিকে, আমি যে কোনও লিনিয়ার বীজগণিত ক্লাস গ্রহণ করে দশ বছর হয়ে গেছে।
মাইকেল এরিক ওবারলিন

নাঃ। যদি আপনি উত্সটি পরীক্ষা করেন তবে আপনি দেখতে পাবেন যে সূত্রটি আসলে শেষ পর্বে আবার প্রথম পয়েন্টটি রেফারেন্স করে (y1 এবং x1)। (দুঃখিত, আমি ল্যাটেক্সের সাথে খুব বেশি পরিচিত নই, তবে সাবস্ক্রিপ্টগুলি আরও বেশি পঠনযোগ্য করে তোলার জন্য আমি ফর্ম্যাট করে দিয়েছি))
সান দ্য বিয়ান

আমি এই সমাধানটি ব্যবহার করেছি এবং এটি আমার ব্যবহারের জন্য পুরোপুরি কাজ করেছে। মনে রাখবেন যে আপনি যদি এগিয়ে যান এবং আপনার অ্যারেতে আরও দুটি ভেক্টর রেখে বাছাই করতে পারেন তবে অ্যারের লেজে প্রথম ভেক্টর যুক্ত করে আপনি তুলনা (বা%) থেকে মুক্তি পেতে পারেন। এইভাবে আপনি কেবল সর্বশেষটি বাদ দিয়ে (সমস্ত দৈর্ঘ্য -১ এর পরিবর্তে দৈর্ঘ্য -২) বাদ দিয়ে সমস্ত উপাদানকে ঘষতে পারেন।
এরিক ফরটিয়ার

2
@ এরিকফোটিয়ার - এফডাব্লুআইডাব্লু, সম্ভবত একটি বৃহত অ্যারের আকার পরিবর্তন করার পরিবর্তে, প্রতিটি পুনরাবৃত্তির previousPointজন্য পরবর্তী পুনরাবৃত্তির মতো তার পয়েন্ট সংরক্ষণ করার জন্য একটি কার্যকর বিকল্প । লুপটি শুরু করার আগে previousPointঅ্যারের শেষ পয়েন্টে সেট করুন । বাণিজ্য বন্ধ অতিরিক্ত স্থানীয় পরিবর্তনীয় অনুলিপি কিন্তু কম অ্যারে অ্যাক্সেস। এবং সবচেয়ে গুরুত্বপূর্ণ, ইনপুট অ্যারে স্পর্শ করতে হবে না।
টুলমেকারস্টেভ

2
@ মিশেল এরিক অবারলিন - শেষ বিন্দু থেকে প্রথম বিন্দুতে রেখাংশটি অন্তর্ভুক্ত করে বহুভুজটি বন্ধ করা প্রয়োজনীয় । (একটি সঠিক গণনা সমান হবে, কোন পয়েন্টটি বন্ধ বহুভুজটি শুরু করে তা বিবেচনা করে না))
টুলমেকারস্টেভ

36

ক্ষুদ্রতম y এর সাথে শীর্ষবিন্দুটি সন্ধান করুন (এবং যদি বন্ধন থাকে তবে বৃহত্তম x)। তালিকার শীর্ষটি Aএবং পূর্বের প্রান্তটি এবং তালিকার Bপরবর্তী প্রান্তটি হতে দিন C। এখন গনা চিহ্ন ক্রস পণ্যের ABএবং AC


তথ্যসূত্র:


7
এটি এন.ইউইকিপিডিয়া.আর / উইকি / কর্ক_অরিয়েন্টেশন- এও ব্যাখ্যা করা হয়েছে । মুল বক্তব্যটি হ'ল প্রাপ্ত পয়েন্টটি উত্তল হলের উপর থাকা উচিত এবং পুরো বহুভুজের অবস্থান নির্ধারণের জন্য উত্তল হলের (এবং তার আশেপাশের প্রতিবেশীদের) একক পয়েন্টে স্থানীয়ভাবে দেখার প্রয়োজন।
এম কাটজ

1
হতবাক এবং বিস্মিত এটি আরও উত্সব পায় নি। সাধারণ বহুভুজ ( যা কিছু ক্ষেত্রে বেশিরভাগ বহুভুজ ) এর জন্য, এই উত্তরটি একটি O(1)সমাধান দেয়। অন্যান্য সমস্ত উত্তর বহুভুজ পয়েন্টের সংখ্যার O(n)জন্য সমাধান দেয় n। এমনকি আরও গভীরতর অপ্টিমাইজেশনের জন্য, উইকিপিডিয়ায় দুর্দান্ত কার্ভ ওরিয়েন্টেশন নিবন্ধের ব্যবহারিক বিবেচ্য বিষয়গুলি দেখুন ।
সিসিল কারি

8
স্পেসিফিকেশন: এই সমাধানটিO(1)কেবল তখনই হয় (এ) এই বহুভুজটি উত্তল (যদি কোনও স্বেচ্ছাচারী ভার্টেক্স উত্তল হলের উপর নির্ভর করে এবং তাই যথেষ্ট হয়) বা (খ) আপনি ইতিমধ্যে ক্ষুদ্রতম Y স্থানাঙ্কের সাথে শীর্ষটি জানেন। যদি এটি না হয় (উদাহরণস্বরূপ, এই বহুভুজটি নন-উত্তল এবং আপনি এটি সম্পর্কে কিছুই জানেন না), একটিO(n)অনুসন্ধান প্রয়োজন। যেহেতু কোনও সংশ্লেষের প্রয়োজন নেই, তবে এটি সাধারণ বহুভুজগুলির জন্য অন্য কোনও সমাধানের তুলনায় নাটকীয়ভাবে দ্রুত।
সিসিল কারি


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

23

এই উত্তরের উপর ভিত্তি করে অ্যালগরিদমের একটি সাধারণ সি # বাস্তবায়ন ।

আসুন ধরে নেওয়া যাক আমাদের একটি Vectorটাইপ থাকার Xএবং Yপ্রকারের বৈশিষ্ট্য রয়েছে double

public bool IsClockwise(IList<Vector> vertices)
{
    double sum = 0.0;
    for (int i = 0; i < vertices.Count; i++) {
        Vector v1 = vertices[i];
        Vector v2 = vertices[(i + 1) % vertices.Count];
        sum += (v2.X - v1.X) * (v2.Y + v1.Y);
    }
    return sum > 0.0;
}

%মডুলো বা বাকী অপারেটর এমন মডুলো অপারেশন করছেন যা ( উইকিপিডিয়া অনুসারে ) একের পর এক সংখ্যার বিভাজনের পরে বাকী অংশটি খুঁজে পায়।


6

শীর্ষেগুলির একটিতে শুরু করুন এবং প্রতিটি পক্ষের দ্বারা বদ্ধ কোণটি গণনা করুন।

প্রথম এবং শেষটি শূন্য হবে (সুতরাং এগুলি এড়িয়ে যান); বাকিগুলির জন্য, কোণটির সাইনটি স্বাভাবিককরণের ক্রস প্রোডাক্ট দ্বারা (পয়েন্ট [এন]-পয়েন্ট [0]) এবং (পয়েন্ট [এন-1]-পয়েন্ট [0]) এর একক দৈর্ঘ্যে দেওয়া হবে।

মানগুলির যোগফল যদি ধনাত্মক হয় তবে আপনার বহুভুজটি অ্যান্টি-ক্লকওয়াইজ অর্থে আঁকবে।


ক্রস প্রোডাক্টটি কীভাবে কোণার সময়কে ধনাত্মক স্কেলিং ফ্যাক্টর হিসাবে উত্সাহিত করে তা দেখে কেবল একটি ক্রস পণ্যটি করা আরও ভাল। এটি দ্রুত এবং কম জটিল হবে।
নভেম্বর

4

এটির মূল্যের জন্য, আমি গুগল ম্যাপস এপিআই v3 অ্যাপ্লিকেশনগুলির জন্য ঘূর্ণন ক্রম গণনা করতে এই মিশ্রিনটি ব্যবহার করেছি।

কোডটি বহুভুজ অঞ্চলের পার্শ্ব প্রতিক্রিয়াটিকে উপকৃত করে: ভার্টেক্সেসের একটি ঘড়ির কাঁটার ঘূর্ণায়মান ক্রমটি একটি ইতিবাচক অঞ্চল দেয়, যখন একই ভার্টেক্সগুলির একটি পাল্টা-ঘড়ির কাঁটার বিপরীত ক্রম একই অঞ্চলটিকে নেতিবাচক মান হিসাবে উত্পাদন করে। কোডটি গুগল ম্যাপ জ্যামিতি লাইব্রেরিতে এক ধরণের প্রাইভেট এপিআই ব্যবহার করে। আমি এটি ব্যবহার করে স্বাচ্ছন্দ্য বোধ করেছি - নিজের ঝুঁকিতে ব্যবহার করুন।

নমুনা ব্যবহার:

var myPolygon = new google.maps.Polygon({/*options*/});
var isCW = myPolygon.isPathClockwise();

ইউনিট পরীক্ষার সাথে সম্পূর্ণ উদাহরণ @ http://jsfiddle.net/stevejansen/bq2ec/

/** Mixin to extend the behavior of the Google Maps JS API Polygon type
 *  to determine if a polygon path has clockwise of counter-clockwise winding order.
 *  
 *  Tested against v3.14 of the GMaps API.
 *
 *  @author  stevejansen_github@icloud.com
 *
 *  @license http://opensource.org/licenses/MIT
 *
 *  @version 1.0
 *
 *  @mixin
 *  
 *  @param {(number|Array|google.maps.MVCArray)} [path] - an optional polygon path; defaults to the first path of the polygon
 *  @returns {boolean} true if the path is clockwise; false if the path is counter-clockwise
 */
(function() {
  var category = 'google.maps.Polygon.isPathClockwise';
     // check that the GMaps API was already loaded
  if (null == google || null == google.maps || null == google.maps.Polygon) {
    console.error(category, 'Google Maps API not found');
    return;
  }
  if (typeof(google.maps.geometry.spherical.computeArea) !== 'function') {
    console.error(category, 'Google Maps geometry library not found');
    return;
  }

  if (typeof(google.maps.geometry.spherical.computeSignedArea) !== 'function') {
    console.error(category, 'Google Maps geometry library private function computeSignedArea() is missing; this may break this mixin');
  }

  function isPathClockwise(path) {
    var self = this,
        isCounterClockwise;

    if (null === path)
      throw new Error('Path is optional, but cannot be null');

    // default to the first path
    if (arguments.length === 0)
        path = self.getPath();

    // support for passing an index number to a path
    if (typeof(path) === 'number')
        path = self.getPaths().getAt(path);

    if (!path instanceof Array && !path instanceof google.maps.MVCArray)
      throw new Error('Path must be an Array or MVCArray');

    // negative polygon areas have counter-clockwise paths
    isCounterClockwise = (google.maps.geometry.spherical.computeSignedArea(path) < 0);

    return (!isCounterClockwise);
  }

  if (typeof(google.maps.Polygon.prototype.isPathClockwise) !== 'function') {
    google.maps.Polygon.prototype.isPathClockwise = isPathClockwise;
  }
})();

এটির চেষ্টা করে আমি ঠিক বিপরীত ফলাফলটি পেয়েছি, ঘড়ির কাঁটার ক্রমে টানা বহুভুজ একটি নেতিবাচক ক্ষেত্রফল দেয়, যখন একটি আঁকা পাল্টা ঘড়ির কাঁটার দিক থেকে ইতিবাচক ফল পাওয়া যায়। উভয় ক্ষেত্রেই, এই স্নিপেটটি এখনও 5 বছরের জন্য দরকারী দরকারী, আপনাকে ধন্যবাদ।
ক্যামেরন রবার্টস

@ ক্যামেরনরোবার্টস আদর্শ (জিওজেসনের জন্য বিশেষত আইইটিএফ দেখুন) 'ডান হাতের নিয়ম' অনুসরণ করা। আমার ধারণা গুগল অভিযোগ করছে। সেক্ষেত্রে বাইরের রিংটি অবশ্যই ঘড়ির কাঁটার বিপরীতে হওয়া উচিত (ধনাত্মক ক্ষেত্রের ফলনশীল) এবং অভ্যন্তরীণ রিংগুলি (গর্তগুলি) ঘড়ির কাঁটার দিকে ঘুরে বেড়াচ্ছে (নেতিবাচক অঞ্চলটি মূল অঞ্চল থেকে সরানো হবে)।
এলিজ এল'ম

4

জাভাস্ক্রিপ্টে শানের উত্তরের একটি বাস্তবায়ন :

function calcArea(poly) {
    if(!poly || poly.length < 3) return null;
    let end = poly.length - 1;
    let sum = poly[end][0]*poly[0][1] - poly[0][0]*poly[end][1];
    for(let i=0; i<end; ++i) {
        const n=i+1;
        sum += poly[i][0]*poly[n][1] - poly[n][0]*poly[i][1];
    }
    return sum;
}

function isClockwise(poly) {
    return calcArea(poly) > 0;
}

let poly = [[352,168],[305,208],[312,256],[366,287],[434,248],[416,186]];

console.log(isClockwise(poly));

let poly2 = [[618,186],[650,170],[701,179],[716,207],[708,247],[666,259],[637,246],[615,219]];

console.log(isClockwise(poly2));

খুব নিশ্চিত যে এটি ঠিক। মনে হচ্ছে এটি কাজ করছে :-)

আপনি যদি ভাবছেন তবে এই বহুভুজগুলি দেখতে এমন দেখাচ্ছে:


3

এটি ওপেনলায়ার্স 2 এর জন্য বাস্তবায়িত ফাংশন । ঘড়ির কাঁটার দিকের বহুভুজ থাকার শর্তটি area < 0এটি এই রেফারেন্স দ্বারা নিশ্চিত করা হয়েছে

function IsClockwise(feature)
{
    if(feature.geometry == null)
        return -1;

    var vertices = feature.geometry.getVertices();
    var area = 0;

    for (var i = 0; i < (vertices.length); i++) {
        j = (i + 1) % vertices.length;

        area += vertices[i].x * vertices[j].y;
        area -= vertices[j].x * vertices[i].y;
        // console.log(area);
    }

    return (area < 0);
}

ওপেনলায়াররা গুগল্যাপস এর মতো জাভাস্ক্রিপ্ট ভিত্তিক মানচিত্র পরিচালনা গ্রন্থাগার এবং এটি ওপেনলেয়ার ২
এমএসএস

আপনার কোডটি কী করে আপনি কিছুটা ব্যাখ্যা করতে পারেন এবং আপনি এটি কেন করছেন?
এনবিরো

@nbro এই কোডটি lhf উত্তর প্রয়োগ করে । এটা তোলে থাকার একটি বিশুদ্ধ জাভাস্ক্রিপ্ট ফাংশন অ OpenLayer অংশ রাখা সহজ হয় ছেদচিহ্ন সরাসরি প্যারামিটার হিসাবে। এটি ভালভাবে কাজ করে এবং মাল্টিপলিগন ক্ষেত্রে এটি খাপ খাইয়ে নিতে পারে ।
এলিজ এল'ম

2

যদি আপনি মতলব ব্যবহার করেন ispolycwতবে বহুভুজের অনুভূমিকগুলি ঘড়ির কাঁটার ক্রমে থাকলে ফাংশনটি সত্য হয়।


1

আর এই Wikipedia নিবন্ধটি ব্যাখ্যা কার্ভ স্থিতিবিন্যাস , 3 পয়েন্ট দেওয়া p, qএবং rসমতল (অর্থাত x এবং y স্থানাঙ্ক সঙ্গে), তখন আপনি নিম্নলিখিত নির্ধারক চিহ্ন নিরূপণ করতে পারেন

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

যদি নির্ণায়কটি নেতিবাচক হয় (যেমন Orient(p, q, r) < 0), তবে বহুভুজটি ঘড়ির কাঁটা (সিডাব্লু) হয়। যদি নির্ধারকটি ধনাত্মক (যেমন Orient(p, q, r) > 0) হয় তবে বহুভুজটি ঘড়ির কাঁটার বিপরীতে (সিসিডাব্লু) হয়। নির্ধারক শূন্য (অর্থাত হয় Orient(p, q, r) == 0) পয়েন্ট যদি p, qএবং rহয় সমরৈখিক

সূত্র উপরে, আমরা এর স্থানাঙ্ক সামনে বেশী পূর্বে লিখুন p, q এবং rকারণ আমরা ব্যবহার করছেন সজাতি স্থানাঙ্ক


@tibetty বহুভুজ অবতল থাকলে এই পদ্ধতিটি কেন অনেক পরিস্থিতিতে কাজ করবে না তা আপনি ব্যাখ্যা করতে পারেন?
nbro

1
আপনার পোস্টে উইকি আইটেম রেফারেন্সে শেষ সারণি দেখুন। আমার পক্ষে একটি ভুল উদাহরণ দেওয়া সহজ তবে এটি প্রমাণ করা শক্ত hard
তিব্বতি

1
আপনার পোস্টে উইকি আইটেম রেফারেন্সে শেষ সারণি দেখুন। আমার পক্ষে একটি ভুল উদাহরণ দেওয়া সহজ তবে এটি প্রমাণ করা শক্ত hard
তিব্বতি

1
@ টিবিটিটি সঠিক। বহুভুজের সাথে আপনি কেবল তিনটি পয়েন্ট নিতে পারবেন না; আপনি সেই বহুভুজের কোনও উত্তল বা অবতল অঞ্চলে থাকতে পারেন। উইকিটি সাবধানে পড়ার জন্য, বহুভুজকে ঘিরে থাকা উত্তল হলের পাশাপাশি একটিকে অবশ্যই তিনটি পয়েন্ট নিতে হবে । "ব্যবহারিক বিবেচনাগুলি" থেকে: "উপযুক্ত বামদিক সন্ধানের জন্য একটি বহুভুজের উত্তল হাল তৈরি করার দরকার নেই A একটি সাধারণ পছন্দটি সবচেয়ে ছোট এক্স-স্থানাঙ্কের সাথে বহুভুজের প্রান্তবিন্দু them যদি সেগুলির বেশ কয়েকটি থাকে তবে একটি সবচেয়ে ছোট Y- স্থানাঙ্কের সাহায্যে বাছাই করা হয়েছে It এটি বহুভুজের উত্তল হলের শীর্ষস্থানীয় [একটি] গ্যারান্টিযুক্ত ""
টুলমেকারস্টেভ

1
সুতরাং lhf এর পূর্ববর্তী উত্তর , যা অনুরূপ, এবং একই উইকির নিবন্ধটি উল্লেখ করে তবে এ জাতীয় পয়েন্টটি নির্দিষ্ট করে। [স্পষ্টতই এটি যতক্ষণ না কেউ মাঝখানে থাকা এড়ানো যায় ততক্ষণ কোনও ছোট বা বৃহত্তম, এক্স বা ওয়াই নেয় তা বিবেচনা করে না; একটি অবতল অঞ্চলে গ্যারান্টি দেওয়ার জন্য কার্যকরভাবে বহুভুজের চারদিকে বাউন্ডিং বক্সের এক প্রান্ত থেকে কাজ করা হচ্ছে]]
টুলমেকারস্টেভ

0

আমি মনে করি কিছু পয়েন্টকে ঘড়ির কাঁটার দিকে দেওয়ার জন্য সমস্ত প্রান্তগুলি কেবলমাত্র প্রান্তের যোগফলই নয় ধনাত্মক হওয়া দরকার। যদি একটি প্রান্তটি কমপক্ষে 3 পয়েন্টের চেয়ে নেতিবাচক হয় তবে ঘড়ির কাঁটার বিপরীতে দেওয়া হয়।


সত্য, তবে আপনি বহুভুজের ঘূর্ণিত শৃঙ্খলা (ঘড়ির কাঁটার বিপরীতে বা ঘড়ির কাঁটার বিপরীতে) ধারণাটি ভুল বুঝেছেন। সম্পূর্ণ উত্তল বহুভুজের মধ্যে, সমস্ত পয়েন্টের কোণটি ঘড়ির কাঁটার দিকে হবে বা সমস্তগুলি ঘড়ির কাঁটার বিপরীতে [আপনার প্রথম বাক্যে যেমন হবে]। অবতল অঞ্চল (গুলি) সহ বহুভুজের মধ্যে, "গুহাগুলি" বিপরীত দিকে থাকবে, তবে সামগ্রিকভাবে বহুভুজের এখনও একটি সুসংজ্ঞাযুক্ত অভ্যন্তর রয়েছে, এবং সেই অনুসারে ঘড়ির কাঁটা বা ঘড়ির কাঁটার দিক হিসাবে বিবেচিত হয়। En.wikedia.org/wiki/…
নির্মাতা স্টিভ

0

আমার সি # / লিনকিউ সমাধানটি @ চারলেসব্রেটানার ক্রস প্রোডাক্ট পরামর্শের উপর ভিত্তি করে নীচে রয়েছে। আপনি ঘুর জন্য একটি রেফারেন্স সাধারণ নির্দিষ্ট করতে পারেন। এটি যতক্ষণ না বক্ররেখা বেশিরভাগ আপ ভেক্টর দ্বারা সংজ্ঞায়িত সমতলে থাকে ততক্ষণ কাজ করা উচিত।

using System.Collections.Generic;
using System.Linq;
using System.Numerics;

namespace SolidworksAddinFramework.Geometry
{
    public static class PlanePolygon
    {
        /// <summary>
        /// Assumes that polygon is closed, ie first and last points are the same
        /// </summary>
       public static bool Orientation
           (this IEnumerable<Vector3> polygon, Vector3 up)
        {
            var sum = polygon
                .Buffer(2, 1) // from Interactive Extensions Nuget Pkg
                .Where(b => b.Count == 2)
                .Aggregate
                  ( Vector3.Zero
                  , (p, b) => p + Vector3.Cross(b[0], b[1])
                                  /b[0].Length()/b[1].Length());

            return Vector3.Dot(up, sum) > 0;

        } 

    }
}

ইউনিট পরীক্ষা দিয়ে

namespace SolidworksAddinFramework.Spec.Geometry
{
    public class PlanePolygonSpec
    {
        [Fact]
        public void OrientationShouldWork()
        {

            var points = Sequences.LinSpace(0, Math.PI*2, 100)
                .Select(t => new Vector3((float) Math.Cos(t), (float) Math.Sin(t), 0))
                .ToList();

            points.Orientation(Vector3.UnitZ).Should().BeTrue();
            points.Reverse();
            points.Orientation(Vector3.UnitZ).Should().BeFalse();



        } 
    }
}

0

অন্যান্য উত্তরের ব্যাখ্যাগুলি ব্যবহার করে এটি আমার সমাধান:

def segments(poly):
    """A sequence of (x,y) numeric coordinates pairs """
    return zip(poly, poly[1:] + [poly[0]])

def check_clockwise(poly):
    clockwise = False
    if (sum(x0*y1 - x1*y0 for ((x0, y0), (x1, y1)) in segments(poly))) < 0:
        clockwise = not clockwise
    return clockwise

poly = [(2,2),(6,2),(6,6),(2,6)]
check_clockwise(poly)
False

poly = [(2, 6), (6, 6), (6, 2), (2, 2)]
check_clockwise(poly)
True

1
এই উত্তরটির উপর ভিত্তি করে অন্য কোন উত্তর নির্দিষ্ট করতে পারেন?
nbro

0

একটি বহুসংখ্যক সহজ পদ্ধতি, যদি আপনি ইতিমধ্যে বহুভুজের ভিতরে একটি বিন্দুটি জানেন :

  1. মূল বহুভুজ, বিন্দু এবং সেই স্থানে তাদের স্থানাঙ্কগুলি থেকে যে কোনও লাইন বিভাগ বেছে নিন।

  2. একটি "অভ্যন্তরীণ" পয়েন্ট যুক্ত করুন এবং একটি ত্রিভুজ গঠন করুন।

  3. CW বা CCW গণনা করুন এখানে তিনটি পয়েন্ট সহ পরামর্শ দেওয়া ।


বহুভুজ পুরোপুরি উত্তল হলে সম্ভবত এটি কাজ করে। কোনও অবতল অঞ্চল থাকলে এটি অবশ্যই নির্ভরযোগ্য নয় - গুহার এক প্রান্তের "ভুল" পাশে থাকা একটি পয়েন্ট বাছাই করা তার পক্ষে সহজ, তারপরে এটিকে প্রান্তটিতে সংযুক্ত করুন। ভুল উত্তর পাবেন।
নির্মাতা স্টিভ

বহুভুজ অবতল থাকলেও এটি কাজ করে। পয়েন্টটি সেই অবতল বহুভুজের ভিতরে থাকা দরকার। তবে আমি জটিল বহুভুজ সম্পর্কে নিশ্চিত নই (পরীক্ষা করিনি))
ভেঙ্কটা গোলি

"বহুভুজ অবতল থাকলেও এটি কাজ করে।" - পাল্টা নমুনা: পলি (0,0), (1,1), (0,2), (2,2), (2,0)। লাইন বিভাগ (1,1), (0, 2) আপনি যদি ত্রিভুজ গঠনের জন্য (1,1), (0,2), (1,2) -> (1,1), (0,2), (0.5,1.5) এর অভ্যন্তরীণ বিন্দুটি চয়ন করেন তবে আপনি পাবেন আপনি যদি (0,0), (1,1), (1,0)> (1,1), (0,2), (0.5,0.5) এর মধ্যে কোনও অভ্যন্তরীণ বিন্দু বাছাই করে তার চেয়ে বিপরীত বাতাস ঘোরানো। এগুলি উভয়ই মূল বহুভুজের অভ্যন্তর, তবু বিপরীত উইন্ডিং রয়েছে। সুতরাং, তাদের মধ্যে একটি ভুল উত্তর দেয়।
টুলমেকারস্টেভ

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

0

বেশ কয়েকটি অবিশ্বাস্য বাস্তবায়ন পরীক্ষার পরে, সিগা / সিসিডাব্লু অভিমুখে বক্সের বাইরে সন্তোষজনক ফলাফল সরবরাহকারী অ্যালগরিদম হ'ল এই থ্রেডে ওপি পোস্ট করেছেন ( shoelace_formula_3)।

সর্বদা হিসাবে, একটি ধনাত্মক সংখ্যা একটি সিডব্লিউ অরিয়েন্টেশন প্রতিনিধিত্ব করে, যেখানে একটি নেতিবাচক সংখ্যা সিসিডাব্লু।


0

উপরের উত্তরের ভিত্তিতে এখানে দ্রুত 3.0 সমাধান রয়েছে:

    for (i, point) in allPoints.enumerated() {
        let nextPoint = i == allPoints.count - 1 ? allPoints[0] : allPoints[i+1]
        signedArea += (point.x * nextPoint.y - nextPoint.x * point.y)
    }

    let clockwise  = signedArea < 0

0

এর আর একটি সমাধান;

const isClockwise = (vertices=[]) => {
    const len = vertices.length;
    const sum = vertices.map(({x, y}, index) => {
        let nextIndex = index + 1;
        if (nextIndex === len) nextIndex = 0;

        return {
            x1: x,
            x2: vertices[nextIndex].x,
            y1: x,
            y2: vertices[nextIndex].x
        }
    }).map(({ x1, x2, y1, y2}) => ((x2 - x1) * (y1 + y2))).reduce((a, b) => a + b);

    if (sum > -1) return true;
    if (sum < 0) return false;
}

সমস্ত অনুভূমিকাকে এটির মতো অ্যারে হিসাবে নিয়ে যান;

const vertices = [{x: 5, y: 0}, {x: 6, y: 4}, {x: 4, y: 5}, {x: 1, y: 5}, {x: 1, y: 0}];
isClockwise(vertices);

0

দিকনির্দেশ নির্ধারণের জন্য সমাধান এবং ঘড়ির কাঁটার বিপরীতে যদি বিপরীত হয় (আউওন অবজেক্টগুলির জন্য এটি প্রয়োজনীয় মনে হয়েছে):

coords <- cbind(x = c(5,6,4,1,1),y = c(0,4,5,5,0))
a <- numeric()
for (i in 1:dim(coords)[1]){
  #print(i)
  q <- i + 1
  if (i == (dim(coords)[1])) q <- 1
  out <- ((coords[q,1]) - (coords[i,1])) * ((coords[q,2]) + (coords[i,2]))
  a[q] <- out
  rm(q,out)
} #end i loop

rm(i)

a <- sum(a) #-ve is anti-clockwise

b <- cbind(x = rev(coords[,1]), y = rev(coords[,2]))

if (a>0) coords <- b #reverses coords if polygon not traced in anti-clockwise direction

0

এই উত্তরগুলি সঠিক হলেও এগুলি প্রয়োজনের চেয়ে গাণিতিকভাবে তীব্র। মানচিত্রের স্থানাঙ্কগুলি ধরে রাখুন, যেখানে সর্বাধিক উত্তর পয়েন্টটি মানচিত্রে সর্বোচ্চ পয়েন্ট। সর্বাধিক উত্তর পয়েন্টটি সন্ধান করুন এবং যদি 2 পয়েন্ট টাই হয় তবে এটি সর্বাধিক উত্তরের তবে সবচেয়ে পূর্ব দিকে (এই উত্তরটি lhf তার উত্তরটিতে ব্যবহার করে)। আপনার পয়েন্টগুলিতে,

পয়েন্ট [0] = (5,0)

বিন্দু [১] = (,,৪)

পয়েন্ট [২] = (৪,৫)

পয়েন্ট [3] = (1,5)

পয়েন্ট [4] = (1,0)

যদি আমরা ধরে নিই যে পি 2 সবচেয়ে উত্তরের তবে পূর্ব বা পরবর্তী বিন্দুটি ঘড়ির কাঁটা, সিডাব্লু, বা সিসিডাব্লু নির্ধারণ করে। যেহেতু সর্বাধিক উত্তর পয়েন্টটি উত্তর মুখের দিকে রয়েছে, পি 1 (পূর্ববর্তী) থেকে পি 2 পূর্ব দিকে অগ্রসর হলে দিকটি সিডব্লু হয়। এই ক্ষেত্রে, এটি পশ্চিমে চলে যায়, সুতরাং গৃহীত উত্তর যেমন বলেছে সেক্ষেত্রে দিকটি সিসিডাব্লু। যদি পূর্বের পয়েন্টটির কোনও অনুভূমিক গতিবিধি না থাকে, তবে একই সিস্টেমটি পরবর্তী পয়েন্ট, পি 3 এ প্রযোজ্য। পি 3 যদি পি 2 এর পশ্চিমে হয়, তবে এটি চলাচল সিসিডাব্লু হয়। যদি পি 2 থেকে পি 3 আন্দোলনটি পূর্ব দিকে হয় তবে এটি পশ্চিমে, আন্দোলনটি সিডব্লিউ। অনুমান করুন যে আপনার ডেটাতে এনটি, পি 2, সবচেয়ে উত্তরের পরে পূর্ব পয়েন্ট এবং প্রাইভটি পূর্বের পয়েন্ট, আপনার ডেটাতে পি 1, এবং এনএসটি পরবর্তী পয়েন্ট, আপনার ডেটাতে পি 3, এবং [0] অনুভূমিক বা পূর্ব / পশ্চিম যেখানে পশ্চিমে পূর্বের চেয়ে কম এবং [1] উল্লম্ব।

if (nte[0] >= prv[0] && nxt[0] >= nte[0]) return(CW);
if (nte[0] <= prv[0] && nxt[0] <= nte[0]) return(CCW);
// Okay, it's not easy-peasy, so now, do the math
if (nte[0] * nxt[1] - nte[1] * nxt[0] - prv[0] * (nxt[1] - crt[1]) + prv[1] * (nxt[0] - nte[0]) >= 0) return(CCW); // For quadrant 3 return(CW)
return(CW) // For quadrant 3 return (CCW)

আইএমএইচও, এলএইচএফ এর উত্তরে প্রদর্শিত মৌলিক গণিতকে আটকে রাখা আরও নিরাপদ হবে - তাঁর উল্লেখ করার জন্য আপনাকে ধন্যবাদ। এটি চতুর্ভুজগুলিতে হ্রাস করার ক্ষেত্রে চ্যালেঞ্জ হ'ল আপনার সূত্রটি সব ক্ষেত্রেই সঠিক তা প্রমাণ করার জন্য এটি যথেষ্ট পরিমাণের কাজ work আপনি সঠিকভাবে "আরও পশ্চিম" গণনা করেছেন? অবতল বহুভুজের যেখানে [2] এবং [3] উভয়ই [2] এর "পশ্চিম এবং দক্ষিণ"? আপনি কি সেই পরিস্থিতিতে [1] এবং [3] এর বিভিন্ন দৈর্ঘ্যের সঠিকভাবে পরিচালনা করেছিলেন? আমার কোনও ধারণা নেই, আমি যদি সরাসরি সেই কোণটি (বা এর নির্ধারক) গণনা করি তবে আমি সুপরিচিত সূত্রগুলি ব্যবহার করছি।
টুলমেকারস্টেভ

@ টুলমেকারস্টেটিভ করুন যদি 3 পয়েন্ট উত্তল থাকে তবে বিবৃতি সর্বদা কাজ করে। যদি বিবৃতিগুলি ফিরে আসে তবে আপনি সঠিক উত্তর পাবেন get যদি বিবৃতিটি আর ফিরে আসবে না, যদি আকারটি অবতল এবং চরম হয়। আপনি যখন গণিত করতে হবে। বেশিরভাগ চিত্রের একটি চতুর্ভুজ থাকে, সুতরাং সেই অংশটি সহজ। আমার সাব্রুটিন কলগুলির 99% এর বেশি কল যদি বিবৃতি দ্বারা পরিচালিত হয়।
ভেক্টরভোরটেক

এটি আমার উদ্বেগের সমাধান করে না। সেই সূত্রটি কী? এলএইচএফ এর উত্তর থেকে উইকি লিঙ্কে দেওয়া হিসাবে এটি কি ওরিয়েন্টেশন নির্ধারক? যদি তাই হয়, তবে তাই বলুন। ব্যাখ্যা করুন যে আপনি যা করছেন তা স্ট্যান্ডার্ড গণিত এড়ানোর জন্য, বেশিরভাগ ক্ষেত্রে পরিচালিত দ্রুত চেকগুলি করছেন। যদি তা হয় তবে আপনার উত্তরটি এখন আমার কাছে বোধগম্য। (মাইনর নিট: পড়ার জন্য সহজ হবে যদি আপনি ব্যবহার .xএবং .yএকটি struct পরিবর্তে [0]এবং [1]আমি জানি না কি আপনার কোড বলছিলেন, প্রথমবার আমি এটাকে glanced।।)
ToolmakerSteve

যেহেতু আপনার পদ্ধতির প্রতি আমার আস্থা নেই, তাই আমি lhf এর পদ্ধতির প্রয়োগ করেছি ; তার লিঙ্ক থেকে সূত্র। স্লো অংশ হয় খোঁজার উপযুক্ত প্রান্তবিন্দু - হে (ঢ) অনুসন্ধান। একবার খুঁজে পাওয়া গেলে, নির্ধারকটি একটি ও (1) অপারেশন হয়, 5 যোগের সাথে 6 গুণক ব্যবহার করে। এই শেষ অংশটি আপনি অনুকূলিত করেছেন; তবে আপনি অতিরিক্ত if- টেস্ট যোগ করে এটি করেছেন। আমি ব্যক্তিগতভাবে একটি অ-মানক পদ্ধতির গ্রহণকে ন্যায়সঙ্গত করতে পারি না - প্রতিটি পদক্ষেপটি সঠিক কিনা তা যাচাই করা দরকার - তবে চতুর্ভুজগুলির একটি আকর্ষণীয় বিশ্লেষণের জন্য আপনাকে ধন্যবাদ!
টুলমেকারস্টেভ

0

সিএইচএফের উত্তরটি কার্যকর করতে কোড :

// https://en.wikipedia.org/wiki/Curve_orientation#Orientation_of_a_simple_polygon
public static WindingOrder DetermineWindingOrder(IList<Vector2> vertices)
{
    int nVerts = vertices.Count;
    // If vertices duplicates first as last to represent closed polygon,
    // skip last.
    Vector2 lastV = vertices[nVerts - 1];
    if (lastV.Equals(vertices[0]))
        nVerts -= 1;
    int iMinVertex = FindCornerVertex(vertices);
    // Orientation matrix:
    //     [ 1  xa  ya ]
    // O = | 1  xb  yb |
    //     [ 1  xc  yc ]
    Vector2 a = vertices[WrapAt(iMinVertex - 1, nVerts)];
    Vector2 b = vertices[iMinVertex];
    Vector2 c = vertices[WrapAt(iMinVertex + 1, nVerts)];
    // determinant(O) = (xb*yc + xa*yb + ya*xc) - (ya*xb + yb*xc + xa*yc)
    double detOrient = (b.X * c.Y + a.X * b.Y + a.Y * c.X) - (a.Y * b.X + b.Y * c.X + a.X * c.Y);

    // TBD: check for "==0", in which case is not defined?
    // Can that happen?  Do we need to check other vertices / eliminate duplicate vertices?
    WindingOrder result = detOrient > 0
            ? WindingOrder.Clockwise
            : WindingOrder.CounterClockwise;
    return result;
}

public enum WindingOrder
{
    Clockwise,
    CounterClockwise
}

// Find vertex along one edge of bounding box.
// In this case, we find smallest y; in case of tie also smallest x.
private static int FindCornerVertex(IList<Vector2> vertices)
{
    int iMinVertex = -1;
    float minY = float.MaxValue;
    float minXAtMinY = float.MaxValue;
    for (int i = 0; i < vertices.Count; i++)
    {
        Vector2 vert = vertices[i];
        float y = vert.Y;
        if (y > minY)
            continue;
        if (y == minY)
            if (vert.X >= minXAtMinY)
                continue;

        // Minimum so far.
        iMinVertex = i;
        minY = y;
        minXAtMinY = vert.X;
    }

    return iMinVertex;
}

// Return value in (0..n-1).
// Works for i in (-n..+infinity).
// If need to allow more negative values, need more complex formula.
private static int WrapAt(int i, int n)
{
    // "+n": Moves (-n..) up to (0..).
    return (i + n) % n;
}

1
এটি ডাউন-ই-পজিটিভ ওয়াই কোঅর্ডিনেটের জন্য বলে মনে হচ্ছে। স্ট্যান্ডার্ড স্থানাঙ্কের জন্য সিডাব্লু / সিসিডাব্লু ফ্লিপ করুন।
ওয়ারউইক অ্যালিসন

0

এই উত্তরের উপর ভিত্তি করে এখানে একটি সাধারণ পাইথন 3 বাস্তবায়ন রয়েছে (যা পরিবর্তিতভাবে গৃহীত উত্তরের প্রস্তাবিত সমাধানের উপর ভিত্তি করে )

def is_clockwise(points):
    # points is your list (or array) of 2d points.
    assert len(points) > 0
    s = 0.0
    for p1, p2 in zip(points, points[1:] + [points[0]]):
        s += (p2[0] - p1[0]) * (p2[1] + p1[1])
    return s > 0.0

-4

এই পয়েন্টগুলির ভর কেন্দ্রে সন্ধান করুন।

ধরুন আপনার বিন্দু থেকে এই বিন্দু থেকে রেখা আছে।

লাইন 0 লাইন 1 এর জন্য দুটি লাইনের মধ্যবর্তী কোণটি সন্ধান করুন

লাইন 1 এবং লাইন 2 এর চেয়ে এটি করুন

...

...

যদি এই কোণটি ঘড়ির কাঁটার বিপরীতে একতরফাভাবে বাড়ছে,

অন্যথায় যদি একঘেয়েমি হ্রাস হয় এটি ঘড়ির কাঁটার দিকে

অন্যথায় (এটি একঘেয়ে নয়)

আপনি সিদ্ধান্ত নিতে পারবেন না, সুতরাং এটি বুদ্ধিমানের কাজ নয়


"ভর কেন্দ্র" দ্বারা আমি মনে করি আপনি "সেন্ট্রয়েড" বলতে চান?
ভিকি চিজওয়ানি

বহুভুজ পুরোপুরি উত্তল হলে সম্ভবত কাজ করে। তবে উত্তরের পরিবর্তে বহুভুজগুলির জন্য কাজ করবে এমন কোনও উত্তর ব্যবহার করা আরও ভাল for
টুলমেকারস্টেভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.