एक त्वरित और गंदा तरीका एक पुनरावर्ती गोलाकार उपखंड का उपयोग करता है । पृथ्वी की सतह के त्रिभुज के साथ शुरुआत करते हुए, प्रत्येक त्रिकोण को एक शिखर से उसके सबसे लंबे पक्ष के बीच में विभाजित करें। (आदर्श रूप से आप त्रिभुज को दो समान-व्यास वाले भागों या समान-क्षेत्र भागों में विभाजित करेंगे, लेकिन क्योंकि उनमें कुछ काल्पनिक गणना शामिल है, मैं सिर्फ पक्षों को आधे हिस्से में विभाजित करता हूं: इसके कारण विभिन्न त्रिकोण अंततः आकार में थोड़ा भिन्न होते हैं, लेकिन इस एप्लिकेशन के लिए यह महत्वपूर्ण नहीं लगता है।)
बेशक आप इस उपखंड को एक डेटा संरचना में बनाए रखेंगे जो उस त्रिकोण को जल्दी से पहचानने की अनुमति देता है जिसमें कोई भी मनमाना बिंदु निहित है। एक बाइनरी ट्री (पुनरावर्ती कॉल के आधार पर) अच्छी तरह से काम करता है: हर बार जब एक त्रिकोण विभाजित होता है, तो पेड़ उस त्रिकोण के नोड पर विभाजित होता है। बंटवारे के विमान से संबंधित डेटा को बनाए रखा जाता है, ताकि आप जल्दी से किसी भी मनमाने बिंदु पर विमान के किस पक्ष पर निर्धारित कर सकें: यह निर्धारित करेगा कि पेड़ के नीचे बाएं या दाएं यात्रा करना है या नहीं।
(क्या मैंने "विमान" को विभाजित करते हुए कहा? हां - यदि पृथ्वी की सतह को एक गोले के रूप में मॉडल करें और भू-भाग (x, y, z) का समन्वय करें, तो हमारी अधिकांश गणना तीन आयामों में होती है, जहाँ त्रिभुजों के किनारे टुकड़े होते हैं) अपने मूल के माध्यम से विमानों के साथ गोले के चौराहों । यह गणना तेज और आसान बनाता है।
मैं एक क्षेत्र के एक अष्टक पर प्रक्रिया दिखा कर वर्णन करूंगा; अन्य सात अष्टक समान तरीके से संसाधित किए जाते हैं। ऐसा अष्टक 90-90-90 त्रिभुज है। अपने ग्राफिक्स में मैं यूक्लिडियन त्रिकोणों को एक ही कोनों में फैलाऊंगा: वे बहुत अच्छे नहीं लगते जब तक कि वे छोटे न हो जाएं, लेकिन वे आसानी से और जल्दी से तैयार हो सकते हैं। यहां अष्टक के अनुरूप यूक्लिडियन त्रिभुज है: यह प्रक्रिया की शुरुआत है।
सभी पक्षों की लंबाई समान होने पर, किसी को "सबसे लंबा" और उप-विभाजित के रूप में यादृच्छिक रूप से चुना जाता है:
प्रत्येक नए त्रिकोण के लिए इसे दोहराएं:
N चरणों के बाद हमारे पास 2 ^ n त्रिकोण होंगे। 10 चरणों के बाद यहां स्थिति है, ओकटेंट में 1024 त्रिकोण दिखाते हैं (और कुल मिलाकर 8192 क्षेत्र):
एक और दृष्टांत के रूप में, मैंने इस अष्टक के भीतर एक यादृच्छिक बिंदु उत्पन्न किया और उपखंड वृक्ष की यात्रा की, जब तक कि त्रिकोण का सबसे लंबा पक्ष 0.05 रेडियन से कम नहीं हो गया। लाल रंग में जांच बिंदु के साथ (कार्टेशियन) त्रिकोण दिखाए जाते हैं।
संयोग से, किसी बिंदु के स्थान को अक्षांश (लगभग) के एक डिग्री तक सीमित करने के लिए, आप ध्यान देंगे कि यह लगभग 1/60 रेडियन है और इसलिए लगभग (1/60) ^ 2 / (Pi / 2) = 1/6000 कुल सतह। चूंकि प्रत्येक उपखंड लगभग त्रिकोण आकार को आधा कर देता है, अष्टकूट के लगभग 13 से 14 उपखंड चाल करेंगे। यह अधिक संगणना नहीं है - जैसा कि हम नीचे देखेंगे - यह कुशल बनाता है कि पेड़ को बिल्कुल भी न रखें, लेकिन मक्खी पर उपखंड का प्रदर्शन करें। शुरुआत में आप ध्यान देंगे कि बिंदु किसमें निहित है - यह उसके तीन निर्देशांक के संकेतों से निर्धारित होता है, जिसे तीन अंकों के बाइनरी नंबर के रूप में दर्ज किया जा सकता है - और प्रत्येक चरण में आप यह याद रखना चाहते हैं कि बिंदु झूठ है या नहीं त्रिभुज के बाएँ (0) या दाएँ (1)। यह एक और 14-अंकीय बाइनरी नंबर देता है। आप इन कोड का उपयोग मनमाने ढंग से करने के लिए कर सकते हैं।
(आम तौर पर, जब दो कोड वास्तविक द्विआधारी संख्या के रूप में करीब होते हैं, तो संबंधित बिंदु करीब होते हैं; हालांकि, अंक अभी भी करीब और काफी अलग कोड हो सकते हैं। उदाहरण के लिए, अलग किए गए दो बिंदुओं को एक मीटर अलग करें। बाइनरी पॉइंट से पहले, क्योंकि वे अलग-अलग ऑक्टेंट्स में हैं। अंतरिक्ष के किसी भी निश्चित विभाजन के साथ इस तरह की बात अपरिहार्य है।)
मैंने इसे लागू करने के लिए Mathematica 8 का उपयोग किया है : आप इसे अपने प्रोग्रामिंग प्रोग्राम के वातावरण में क्रियान्वयन के लिए या-स्यूडोकोड के रूप में ले सकते हैं।
निर्धारित करें कि 0-ab बिंदु p के समतल किस तरफ है :
side[p_, {a_, b_}] := If[Det[{p, a, b}] >= 0, left, right];
बिंदु p पर आधारित त्रिभुज abc को परिष्कृत करें।
refine[p_, {a_, b_, c_}] := Block[{sides, x, y, z, m},
sides = Norm /@ {b - c, c - a, a - b} // N;
{x, y, z} = RotateLeft[{a, b, c}, First[Position[sides, Max[sides]]] - 1];
m = Normalize[Mean[{y, z}]];
If[side[p, {x, m}] === right, {y, m, x}, {x, m, z}]
]
अंतिम आंकड़ा ओक्टेंट को प्रदर्शित करके और उसके ऊपर, निम्न सूची को बहुभुज के एक सेट के रूप में प्रस्तुत करके तैयार किया गया था:
p = Normalize@RandomReal[NormalDistribution[0, 1], 3] (* Random point *)
{a, b, c} = IdentityMatrix[3] . DiagonalMatrix[Sign[p]] // N (* First octant *)
NestWhileList[refine[p, #] &, {a, b, c}, Norm[#[[1]] - #[[2]]] >= 0.05 &, 1, 16]
NestWhileList
बार-बार एक ऑपरेशन ( refine
) लागू होता है, जबकि एक स्थिति से संबंधित है (त्रिकोण बड़ा है) या जब तक एक अधिकतम ऑपरेशन गिनती (16) तक नहीं पहुंच गया है।
अष्टक के पूर्ण त्रिकोण को प्रदर्शित करने के लिए, मैंने पहले अष्टक के साथ शुरुआत की और दस बार शोधन किया। यह एक मामूली संशोधन के साथ शुरू होता है refine
:
split[{a_, b_, c_}] := Module[{sides, x, y, z, m},
sides = Norm /@ {b - c, c - a, a - b} // N;
{x, y, z} = RotateLeft[{a, b, c}, First[Position[sides, Max[sides]]] - 1];
m = Normalize[Mean[{y, z}]];
{{y, m, x}, {x, m, z}}
]
अंतर यह है कि अपने इनपुट त्रिकोण के दोनों हिस्सों को एक के बजाय split
लौटाता है जिसमें एक दिया बिंदु निहित है। इसे पूरा करने के द्वारा पूर्ण त्रिभुज प्राप्त होता है:
triangles = NestList[Flatten[split /@ #, 1] &, {IdentityMatrix[3] // N}, 10];
जांच करने के लिए, मैंने हर त्रिकोण के आकार का एक माप लिया और सीमा को देखा। (यह "आकार" प्रत्येक त्रिभुज और गोलाकार केंद्र द्वारा संयोजित पिरामिड के आकार की आकृति के लिए आनुपातिक है, इन जैसे छोटे त्रिकोणों के लिए, यह आकार अनिवार्य रूप से इसके गोलाकार क्षेत्र के लिए आनुपातिक है।)
Through[{Min, Max}[Map[Round[Det[#], 0.00001] &, triangles[[10]] // N, {1}]]]
{0.00523, 0.00739}
इस प्रकार आकार उनके औसत से लगभग 25% भिन्न या कम होता है: जो कि समूह बिंदुओं के लिए लगभग समान तरीके से प्राप्त करने के लिए उचित लगता है।
इस कोड को स्कैन करने पर, आप बिना किसी त्रिकोणमिति को नोटिस करेंगे : केवल उसी स्थान की आवश्यकता होगी, यदि बिल्कुल भी, गोलाकार और कार्टेशियन निर्देशांक के बीच आगे और पीछे परिवर्तित करने में होगा। कोड किसी भी नक्शे पर पृथ्वी की सतह को प्रोजेक्ट नहीं करता है, जिससे परिचर विकृतियों से बचा जा सकता है। अन्यथा, यह केवल औसत ( Mean
), पाइथोगोरियन प्रमेय ( Norm
) और एक 3 बाय 3 निर्धारक ( Det
) सभी काम करने के लिए उपयोग करता है। ( प्रत्येक त्रिकोण की सबसे लंबी ओर की खोज के साथ, कुछ सरल सूची-जोड़-तोड़ आदेश भी हैं RotateLeft
और Flatten
, भी।)