संपादित करें: एल्गोरिदम को बेहतर बनाने के लिए सुझाए गए नकारात्मक गोलाकार बाउंड चेक की दक्षता के बारे में ओपी टिप्पणी संदेहपूर्ण रही है कि क्या जांच करता है कि एक मनमाना 2 डी बिंदु एक घुमाया और / या चलती आयत के भीतर है। अपने 2D गेम इंजन (OpenGL / C ++) पर थोड़ा सा चक्कर लगाते हुए, मैं OPs वर्तमान बिंदु-इन-आयत-चेक एल्गोरिदम (और रूपांतरों) के खिलाफ अपने एल्गोरिथ्म का प्रदर्शन बेंचमार्क प्रदान करके अपने उत्तर को पूरक करता हूं।
मैंने मूल रूप से एल्गोरिथ्म को जगह में छोड़ने का सुझाव दिया (जैसा कि यह लगभग इष्टतम है), लेकिन मात्र खेल तर्क के माध्यम से सरल करें: (1) मूल आयत के चारों ओर एक पूर्व-संसाधित सर्कल का उपयोग करके; (2) एक दूरी की जाँच करें और यदि बिंदु दिए गए सर्कल के भीतर है; (3) ओपी या अन्य किसी भी सरल एल्गोरिथ्म का उपयोग करें (मैं एक अन्य उत्तर में प्रदान की गई आइलेट एल्गोरिथ्म की सलाह देता हूं)। मेरे सुझाव के पीछे तर्क यह है कि एक बिंदु के घेरे के भीतर की जाँच यह है कि घुमाए गए आयत या किसी अन्य बहुभुज की सीमा जाँच की तुलना में काफी अधिक कुशल है।
बेंचमार्क टेस्ट के लिए मेरा प्रारंभिक परिदृश्य एक विवश स्थान में बड़ी संख्या में दिखने और गायब होने वाले डॉट्स (जिनकी स्थिति प्रत्येक गेम-लूप में बदल जाती है) को चलाने के लिए है, जो लगभग 20 घूर्णन / मूविंग वर्गों से भरा होगा। मैंने चित्रण प्रयोजनों के लिए एक वीडियो ( यूट्यूब लिंक ) प्रकाशित किया है। मापदंडों पर ध्यान दें: बेतरतीब ढंग से दिखने वाले डॉट्स, संख्या या आयतों की संख्या। मैं निम्नलिखित मानकों के साथ बेंचमार्क करूंगा:
बंद : ओपी द्वारा प्रदान किए गए सीधे सरल एल्गोरिथ्म बिना सर्कल बाउंड्री नेगेटिव चेक के
चालू : पहले बहिष्करण जाँच के रूप में आयतों के आसपास प्रति-संसाधित (सीमा) हलकों का उपयोग करना
ON + Stack : स्टैक पर लूप के भीतर रन-टाइम पर सर्कल की सीमाएँ बनाना
ON + स्क्वायर डिस्टेंस : अधिक महंगी स्क्वायर रूट एल्गोरिथ्म (Pieter Geerkens) लेने से बचने के लिए एक और अनुकूलन के रूप में स्क्वायर डिस्टेंस का उपयोग करना।
यहाँ विभिन्न एल्गोरिदम के विभिन्न प्रदर्शनों का एक सारांश है जो लूप के माध्यम से पुनरावृति में लगने वाले समय को दर्शाता है।
एक्स-अक्ष अधिक डॉट्स जोड़कर बढ़ी हुई जटिलता दिखाता है (और इस तरह लूप को धीमा कर रहा है)। (उदाहरण के लिए, 1000 आयत बिंदुओं पर एक परिसीमित स्थान में 20 आयतों के साथ 1000 बार, लूप पुनरावृत्ति करता है और एल्गोरिथ्म को 20000 बार कॉल करता है।) y- अक्ष एक उच्च रिज़ॉल्यूशन का उपयोग करके पूरे लूप को पूरा करने में लगने वाले समय (ms) को दिखाता है। प्रदर्शन टाइमर। 20 से अधिक एमएस एक सभ्य खेल के लिए समस्याग्रस्त होगा क्योंकि यह उच्च एफपीएस का लाभ नहीं उठाएगा ताकि एक चिकनी एनीमेशन को प्रक्षेपित किया जा सके और खेल कई बार 'बीहड़' दिखाई दे सकता है।
परिणाम 1 : लूप के भीतर एक तेज नकारात्मक जांच के साथ एक पूर्व-संसाधित परिपत्र बाध्य एल्गोरिदम नियमित एल्गोरिदम की तुलना में 1900% द्वारा प्रदर्शन में सुधार करता है (चेक के बिना मूल लूप समय का 5%)। परिणाम एक लूप के भीतर पुनरावृत्तियों की संख्या के लिए लगभग आनुपातिक रखता है, इस प्रकार यह कोई फर्क नहीं पड़ता कि हम 10 या 10000 यादृच्छिक रूप से प्रदर्शित अंक की जांच करते हैं। इस प्रकार, इस चित्रण में प्रदर्शन हानि महसूस किए बिना वस्तुओं की संख्या सुरक्षित रूप से 10k तक बढ़ सकती है।
परिणाम 2 : यह पिछली टिप्पणी द्वारा सुझाया गया है कि एल्गोरिथ्म तेज हो सकता है, लेकिन स्मृति गहन। हालाँकि, ध्यान दें कि पूर्व-संसाधित सर्कल आकार के लिए एक फ़्लोटिंग को केवल 4 बाइट्स लेता है। यह तब तक कोई वास्तविक मुद्दा नहीं होना चाहिए जब तक कि ओपी एक साथ 100000+ ऑब्जेक्ट को चलाने की योजना नहीं बनाता है। एक वैकल्पिक और स्मृति कुशल दृष्टिकोण लूप के भीतर स्टैक पर सर्कल के अधिकतम आकार की गणना करना है और इसे हर पुनरावृत्ति के साथ दायरे से बाहर जाने देना है और इस प्रकार गति के कुछ अज्ञात मूल्य के लिए व्यावहारिक रूप से कोई स्मृति उपयोग नहीं है। वास्तव में, परिणाम से पता चलता है कि यह दृष्टिकोण वास्तव में एक पूर्व-संसाधित सर्कल आकार का उपयोग करने की तुलना में धीमा है, लेकिन यह अभी भी लगभग 1150% (मूल प्रसंस्करण समय का 8%) के काफी प्रदर्शन में सुधार दिखाता है।
परिणाम 3 : मैं आगे वास्तविक दूरी के बजाय चुकता दूरी का उपयोग करके परिणाम 1 एल्गोरिथ्म में सुधार करता हूं और इस प्रकार एक कम्प्यूटेशनल रूप से महंगा वर्गमूल संचालन ले रहा हूं। यह केवल sligthtly प्रदर्शन को बढ़ाता है (2400%)। (नोट: मैं भी इसी तरह के लेकिन थोड़ा खराब परिणाम के साथ वर्गमूल सन्निकटन के लिए पूर्व-संसाधित सरणियों के लिए हैश टेबल की कोशिश करता हूं)
परिणाम 4 : मैं आगे आयतों को हिलाने / टकराने की जाँच करता हूँ; हालाँकि, यह मूल परिणामों (जैसी कि अपेक्षित है) को बदलता नहीं है क्योंकि तार्किक जाँच अनिवार्य रूप से समान है।
परिणाम 5 : मैं आयतों की संख्या को अलग-अलग करता हूं और पाता हूं कि एल्गोरिथ्म और भी अधिक कुशल हो जाता है, कम भीड़ वाला स्थान भर जाता है (डेमो में नहीं दिखाया गया है)। परिणाम भी कुछ हद तक अपेक्षित है, क्योंकि किसी बिंदु के लिए एक सर्कल और ऑब्जेक्ट की सीमाओं के बीच छोटे स्थान के भीतर संभावना कम हो जाती है। दूसरे चरम पर, मैं एक ही सीमित छोटे स्थान के भीतर आयतों की संख्या को भी 100 तक बढ़ाने की कोशिश करता हूं और उन्हें लूप (पापी (पुनरावृत्ति)) के भीतर रन टाइम पर डायनामिक रूप से भिन्न करता हूं। यह अभी भी 570% (या मूल लूप समय के 15%) के प्रदर्शन में वृद्धि के साथ बहुत अच्छा प्रदर्शन करता है।
परिणाम 6 : मैं यहाँ पर सुझाए गए वैकल्पिक एल्गोरिदम का परीक्षण करता हूँ और प्रदर्शन में बहुत मामूली लेकिन महत्वपूर्ण अंतर नहीं पाता (2%)। दिलचस्प और अधिक सरल IsLeft एल्गोरिथ्म 17% (मूल गणना समय का 85%) द्वारा प्रदर्शन को बढ़ावा देने के साथ बहुत अच्छा प्रदर्शन करता है, लेकिन एक त्वरित नकारात्मक चेक एल्गोरिथ्म की दक्षता के पास कहीं नहीं है।
मेरा कहना है कि पहले लीन डिजाइन और गेम लॉजिक पर विचार करें, खासकर जब सीमाओं और टकराव की घटनाओं से निपटें। ओपीएस वर्तमान एल्गोरिथ्म पहले से ही काफी कुशल है और एक और अनुकूलन अंतर्निहित अवधारणा को अनुकूलित करने के रूप में महत्वपूर्ण नहीं है। इसके अलावा, खेल के दायरे और उद्देश्य को संप्रेषित करना अच्छा है, क्योंकि एल्गोरिथ्म की दक्षता गंभीर रूप से उन पर निर्भर करती है।
मेरा सुझाव है कि हमेशा गेम डिज़ाइन चरण के दौरान किसी भी जटिल एल्गोरिदम को बेंचमार्क करने का प्रयास करें क्योंकि केवल सादे कोड को देखने से वास्तविक रन-टाइम प्रदर्शन के बारे में सच्चाई का पता नहीं चल सकता है। सुझाव दिया एल्गोरिथ्म यहां भी आवश्यक नहीं हो सकता है, यदि, उदाहरण के लिए, एक व्यक्ति केवल यह परखना चाहता है कि माउस कर्सर एक आयत में निहित है या नहीं, या, जब वस्तुओं का बहुमत पहले से ही छू रहा हो। यदि आयतों के अधिकांश बिंदु आयत के भीतर हैं, तो एल्गोरिथ्म कम कुशल होगा। (हालांकि, तब एक माध्यमिक नकारात्मक जाँच के रूप में एक 'आंतरिक वृत्त' सीमा को स्थापित करना संभव होगा।) बड़ी संख्या में किसी भी वस्तु के स्वाभाविक टकराव का पता लगाने के लिए वृत्त / गोलाकार सीमा जाँच बहुत उपयोगी होती है, जिनके बीच स्वाभाविक रूप से कुछ जगह होती है। ।
Rec Points Iter OFF ON ON_Stack ON_SqrDist Ileft Algorithm (Wondra)
(ms) (ms) (ms) (ms) (ms) (ms)
20 10 200 0.29 0.02 0.04 0.02 0.17
20 100 2000 2.23 0.10 0.20 0.09 1.69
20 1000 20000 24.48 1.25 1.99 1.05 16.95
20 10000 200000 243.85 12.54 19.61 10.85 160.58