मैं आर्कगिस 10.1 का उपयोग कैसे कर सकता हूं ताकि तीन बिंदुओं द्वारा परिभाषित एक जियोडेसिक समबाहु बिंदु मिल सके?


12

उदाहरण के लिए, मेरे पास एक समुद्र तट पर तीन आधार बिंदुओं के लिए निर्देशांक हैं और मुझे तट से दूर बिंदु के निर्देशांक खोजने की आवश्यकता है जो तीनों से समान है। यह ज्यामिति में एक सरल अभ्यास है, लेकिन सभी मापों को भूगणित को ध्यान में रखना चाहिए।

यदि मैं एक यूक्लिडियन तरीके से यह संपर्क कर रहा था, तो मैं बेस पॉइंट्स को जोड़ने वाले जियोडेसिक रास्तों को माप सकता था, परिणामस्वरूप त्रिकोण के पक्षों के मध्य बिंदुओं को खोजता था और उन प्रत्येक रास्तों के लंबवत ऑर्थोड्रोमों का निर्माण करता था। तीन loxodromes संभवतः समवर्ती बिंदु पर अभिसरण करेंगे। यदि यह सही तरीका है, तो आर्क में इसे करने का एक आसान तरीका है।

मुझे ओ खोजने की जरूरत है


क्या 3 बिंदुओं के सापेक्ष पदों पर अड़चनें हैं? चित्र पूर्वी तट, मध्य बिंदु सबसे सुदूर पूर्व है। आपका समाधान काम नहीं करेगा क्योंकि लम्बे समय तक अपतटीय नहीं होगा। मुझे यकीन है कि हम अन्य बुरे मामलों के साथ आ सकते हैं!
mkennedy

मुझे आश्चर्य है कि यदि आप एक दूरी संरक्षण प्रक्षेपण का उपयोग कर सकते हैं और वहां से गणना चला सकते हैं? progonos.com/furuti/MapProj/Normal/CartProp/DistPres/… एल्गोरिथ्म को सुनिश्चित करने के लिए ऐसा नहीं है, वहाँ एक होना चाहिए ... शायद यह barycentre है: en.wikipedia.org/hi/Barycentric_coordinate_system
एलेक्स लेथ

बारीकी से संबंधित समस्या के समाधान के लिए, हमारी साइट को "ट्रिलाटेशन" के लिए खोजें । इसके अलावा, gis.stackexchange.com/questions/10332/… एक डुप्लिकेट है, लेकिन इसका कोई पर्याप्त उत्तर नहीं है (सबसे अधिक संभावना है क्योंकि प्रश्न एक उलझन में पूछा गया था)।
whuber

@mkennedy, सिद्धांत रूप में, कोई बुरे मामले नहीं हैं, केवल संख्यात्मक रूप से अस्थिर हैं। ये तब होते हैं जब तीन आधार बिंदु टकराते हैं; दो समाधान (एक गोलाकार मॉडल पर) आम जियोडेसिक के दो ध्रुवों पर होते हैं; एक दीर्घवृत्त मॉडल में वे पास होते हैं जहां उन ध्रुवों की अपेक्षा की जाती है।
whuber

यहाँ लॉक्सोड्रोम का उपयोग सही नहीं होगा: वे लम्बवत द्विभाजक नहीं हैं। गोले पर, ये रेखाएं महान मंडलियों (जियोडेसिक्स) के हिस्से होंगे, लेकिन दीर्घवृत्त पर, वे भूगणित होने से थोड़ा हटेंगे।
whuber

जवाबों:


10

यह उत्तर कई वर्गों में विभाजित है:

  • विश्लेषण और समस्या को कम करना , यह दर्शाता है कि "कैन्ड" रूटीन के साथ वांछित बिंदु कैसे खोजना है।

  • उदाहरण: वर्किंग प्रोटोटाइप , वर्किंग कोड।

  • उदाहरण , समाधान के उदाहरण दिखाते हुए।

  • नुकसान , संभावित समस्याओं पर चर्चा और उन्हें कैसे से निपटने के लिए।

  • ArcGIS कार्यान्वयन , एक कस्टम ArcGIS उपकरण बनाने के बारे में टिप्पणी करता है और जहां आवश्यक रूटीन प्राप्त करना है।


विश्लेषण और समस्या को कम करना

आइए यह देखते हुए शुरू करें कि (पूरी तरह से गोल) गोलाकार मॉडल में हमेशा एक समाधान होगा - वास्तव में, दो समाधान। आधार अंक ए, बी और सी को देखते हुए, प्रत्येक जोड़ी अपने "लंबवत द्विभाजक" को निर्धारित करती है, जो दो दिए गए बिंदुओं से समान बिंदुओं का समूह है। यह द्विभाजक एक भूगणित (महान वृत्त) है। गोलाकार ज्यामिति अण्डाकार है : कोई भी दो भूगणित प्रतिच्छेद (दो विशिष्ट बिंदुओं में)। इस प्रकार, एबी के द्विभाजक और बीसी के द्विभाजक के चौराहे बिंदु हैं - परिभाषा के अनुसार - ए, बी और सी से समतुल्य, जिससे समस्या का समाधान होता है। (नीचे पहला आंकड़ा देखें।)

एक दीर्घवृत्त पर चीजें अधिक जटिल लगती हैं, लेकिन क्योंकि यह गोले का एक छोटा छिद्र है, हम समान व्यवहार की उम्मीद कर सकते हैं। (इसका विश्लेषण हमें बहुत दूर तक ले जाएगा।) एक दीर्घवृत्त पर सटीक दूरी की गणना करने के लिए उपयोग किए जाने वाले जटिल सूत्र (आंतरिक रूप से एक जीआईएस) एक वैचारिक जटिलता नहीं है, हालांकि: समस्या मूल रूप से समान है। यह देखने के लिए कि समस्या वास्तव में कितनी सरल है, आइए इसे कुछ हद तक अमूर्त रूप से बताएं। इस कथन में, "d (U, V)" बिंदु U और V के बीच की सही, पूरी तरह से सटीक दूरी को संदर्भित करता है।

एक दीर्घवृत्त पर A, B, C (लैट-लोन जोड़े के रूप में) तीन बिंदुओं को देखते हुए एक बिंदु X खोजें जिसके लिए (1) d (X, A) = d (X, B) = d (X, C) और ( 2) यह आम दूरी यथासंभव छोटी है।

ये तीनों दूरियां अज्ञात X पर निर्भर करती हैं । इस प्रकार अंतर u (X) = d (X, A) - d (X, B) और v (X) = d (X, B) - d (X, C) X के वास्तविक-मूल्यवान कार्य हैं। फिर, कुछ हद तक, हम इन मतभेदों को एक आदेशित जोड़ी में इकट्ठा कर सकते हैं। हम X के लिए निर्देशांक के रूप में (lat, lon) का भी उपयोग करेंगे, जिससे हमें इसे एक ऑर्डर की गई जोड़ी के रूप में विचार करने की अनुमति मिलती है, X = (phi, lambda)। इस सेटअप में, फ़ंक्शन

एफ (फी, लंबा) = (यू (एक्स), वी (एक्स))

दो-आयामी अंतरिक्ष में मान लेने वाले दो-आयामी अंतरिक्ष के एक हिस्से से एक कार्य है और हमारी समस्या कम हो जाती है

सभी संभव (phi, lambda) खोजें, जिसके लिए F (phi, lambda) = (0,0) है।

यहाँ वह जगह है जहाँ अमूर्त भुगतान करता है: इस को हल करने के लिए बहुत सारे महान सॉफ्टवेयर मौजूद हैं (विशुद्ध रूप से संख्यात्मक बहुआयामी मूल-खोज समस्या)। जिस तरह से यह काम करता है वह यह है कि आप एफ की गणना करने के लिए एक रूटीन लिखते हैं , फिर आप सॉफ्टवेयर के साथ-साथ इसके इनपुट पर प्रतिबंध के बारे में किसी भी जानकारी के साथ इसे पास करते हैं ( phi -90 और 90 डिग्री के बीच झूठ और लैम्ब्डा -180 और 180 के बीच झूठ होना चाहिए डिग्री)। यह एक सेकंड के एक अंश के लिए दूर हो जाता है और रिटर्न (आम तौर पर) का केवल एक मान ( फी , लैम्ब्डा ) होता है, अगर यह एक मिल सकता है।

संभाल करने के लिए विवरण हैं, क्योंकि इसमें एक कला है: एफ "व्यवहार" के आधार पर चुनने के लिए विभिन्न समाधान विधियां हैं ; यह सॉफ्टवेयर को उसकी खोज के लिए एक उचित प्रारंभिक बिंदु देकर "स्टीयर" करने में मदद करता है (यह एक तरीका है जिससे हम किसी अन्य के बजाय निकटतम समाधान प्राप्त कर सकते हैं); और आपको आमतौर पर यह निर्दिष्ट करने की आवश्यकता होती है कि आप कितना सटीक समाधान चाहते हैं (इसलिए यह पता है कि खोज को कब रोकना है)। (अधिक जानकारी के लिए जीआईएस विश्लेषकों को ऐसे विवरणों के बारे में जानने की आवश्यकता है, जो जीआईएस समस्याओं में बहुत ऊपर आते हैं, कृपया सिफारिश करें कि विषयों को भू-स्थानिक प्रौद्योगिकी पाठ्यक्रम के लिए एक कंप्यूटर विज्ञान में शामिल किया जाए और अंत में "मिसटेलनी" अनुभाग देखें। )


चित्रण: एक कार्य प्रोटोटाइप

विश्लेषण से पता चलता है कि हमें दो चीजों को प्रोग्राम करने की आवश्यकता है: समाधान का एक कच्चा प्रारंभिक अनुमान और एफ की गणना ।

प्रारंभिक अनुमान तीन आधार बिंदुओं के "गोलाकार औसत" द्वारा किया जा सकता है। यह भूस्थैतिक कार्टेशियन (x, y, z) निर्देशांक में उनका प्रतिनिधित्व करके, उन निर्देशांक के औसत से, और उस औसत को गोले में वापस लाकर और अक्षांश और देशांतर में पुनः व्यक्त करके प्राप्त किया जाता है। गोले का आकार सारहीन है और गणना इस प्रकार सीधी की जाती है: क्योंकि यह सिर्फ एक प्रारंभिक बिंदु है, हमें दीर्घवृत्त गणना की आवश्यकता नहीं है।

इस कार्यशील प्रोटोटाइप के लिए मैंने Mathematica 8 का उपयोग किया ।

sphericalMean[points_] := Module[{sToC, cToS, cMean},
  sToC[{f_, l_}] := {Cos[f] Cos[l], Cos[f] Sin[l], Sin[f]};
  cToS[{x_, y_, z_}] := {ArcTan[x, y], ArcTan[Norm[{x, y}], z]};
  cMean = Mean[sToC /@ (points Degree)];
  If[Norm[Most@cMean] < 10^(-8), Mean[points], cToS[cMean]] / Degree
  ]

(अंतिम Ifस्थिति परीक्षण करती है कि क्या औसत स्पष्ट रूप से एक देशांतर को इंगित करने में विफल हो सकता है; यदि हां, तो यह अक्षांश और इसके इनपुट के अनुदैर्ध्य के सीधे अंकगणित माध्य पर गिरता है - शायद एक बढ़िया विकल्प नहीं है, लेकिन कम से कम एक वैध है। कार्यान्वयन मार्गदर्शन के लिए इस कोड का उपयोग करने वालों के लिए, ध्यान दें कि गणितज्ञों के तर्क ArcTanअधिकांश अन्य कार्यान्वयनों की तुलना में उलटे हैं: इसका पहला तर्क x-निर्देशांक है, इसका दूसरा भाग y-निर्देशांक है, और यह वेक्टर द्वारा बनाए गए कोण को लौटाता है एक्स, वाई)।)

जहाँ तक दूसरे भाग में जाता है, क्योंकि गणितज्ञ - अरकगिस और लगभग सभी अन्य जीआईएस - में दीर्घवृत्त पर सटीक दूरी की गणना करने के लिए कोड है, लिखने के लिए लगभग कुछ भी नहीं है। हम रूट-रूटिंग रूटीन कहते हैं:

tri[a_, b_, c_] := Block[{d = sphericalMean[{a, b, c}], sol, f, q},
   sol = FindRoot[{GeoDistance[{Mod[f, 180, -90], Mod[q, 360, -180]}, a] == 
                   GeoDistance[{Mod[f, 180, -90], Mod[q, 360, -180]}, b] ==
                   GeoDistance[{Mod[f, 180, -90], Mod[q, 360, -180]}, c]}, 
           {{f, d[[1]]}, {q, d[[2]]}}, 
           MaxIterations -> 1000, AccuracyGoal -> Infinity, PrecisionGoal -> 8];
   {Mod[f, 180, -90], Mod[q, 360, -180]} /. sol
   ];

इस कार्यान्वयन का सबसे उल्लेखनीय पहलू यह है कि यह कैसे क्रमशः 180 और 360 डिग्री की गणना करके अक्षांश ( f) और देशांतर ( q) को कम करने के लिए विवश करता है। यह समस्या (जो अक्सर जटिलताएं पैदा करता है) को बाधित करने से बचता है। MaxIterationsइस कोड को बनाने के लिए कंट्रोल पैरामीटर आदि को ट्वीक किया जाता है जो इसे सबसे बड़ी संभव सटीकता प्रदान करता है।

इसे कार्रवाई में देखने के लिए, आइए इसे संबंधित प्रश्न में दिए गए तीन आधार बिंदुओं पर लागू करें :

sol = tri @@ (bases = {{-6.28530175, 106.9004975375}, {-6.28955287, 106.89573839}, {-6.28388865789474, 106.908087643421}})

{-6.29692, 106.907}

इस समाधान और तीन बिंदुओं के बीच की गणना दूरी है

{1450.23206979, 1450.23206979, 1450.23206978}

(ये मीटर हैं)। वे ग्यारहवें महत्वपूर्ण अंक के माध्यम से सहमत होते हैं (जो कि बहुत सटीक है, वास्तव में, चूंकि दूरी शायद ही कभी मिलीमीटर या तो बेहतर से सटीक होती है)। यहां इन तीन बिंदुओं (काले), उनके तीन पारस्परिक द्विभाजकों और समाधान (लाल) की एक तस्वीर दी गई है:

आकृति 1


उदाहरण

इस कार्यान्वयन का परीक्षण करने के लिए और यह समझने के लिए कि समस्या कैसे व्यवहार करती है, की एक बेहतर समझ प्राप्त करें, यहां तीन व्यापक रूप से दूरी के आधार बिंदुओं के लिए दूरी में रूट माध्य वर्ग विसंगति का एक समोच्च साजिश है। (RMS विसंगति सभी तीन अंतर d (X, A) -d (X, B), d (X, B) -d (X, C) और d (X, C) -d (X) की गणना करके प्राप्त की जाती है , ए), उनके वर्गों का औसत, और वर्गमूल लेना। यह शून्य के बराबर होता है जब एक्स समस्या को हल करता है और अन्यथा एक्स एक समाधान से दूर हो जाता है, और इसलिए मापता है कि हम किसी भी स्थान पर समाधान के कितने "करीब" हैं। )

चित्र 2

बेस प्लेट (60, -120), (10, -40), और (45,10) इस प्लेट कार्निशन प्रक्षेपण में लाल रंग में दिखाए गए हैं; समाधान (49.2644488, -49.9052992) - जिसकी गणना करने के लिए 0.03 सेकंड की आवश्यकता है - पीले रंग में है। इसकी आरएमएस विसंगति तीन नैनोमीटर से कम है , सभी प्रासंगिक दूरी हजारों किलोमीटर होने के बावजूद। अंधेरे क्षेत्र RMS के छोटे मान दिखाते हैं और प्रकाश क्षेत्र उच्च मान दिखाते हैं।

यह मानचित्र स्पष्ट रूप से एक और समाधान दर्शाता है (-49.2018206, 130.0297177) (पहले समाधान के विपरीत डायनामिक रूप से प्रारंभिक खोज मूल्य सेट करके दो नैनोमीटर के आरएमएस की गणना)।


नुकसान

संख्यात्मक अस्थिरता

जब बेस पॉइंट लगभग एक साथ टकराते हैं और एक साथ बंद होते हैं, तो सभी समाधान लगभग आधी दुनिया से दूर होंगे और सटीक रूप से पिन करने के लिए बेहद मुश्किल होंगे। कारण यह है कि दुनिया भर में एक स्थान में छोटे बदलाव - इसे आधार बिंदुओं से दूर या दूर ले जाना - दूरियों के अंतर में केवल अविश्वसनीय रूप से छोटे बदलावों को प्रेरित करेगा। परिणाम को पिन करने के लिए जियोडैटिक दूरियों की सामान्य गणना में निर्मित पर्याप्त सटीकता और सटीकता नहीं है।

उदाहरण के लिए, बेस पॉइंट्स (45.001, 0), (45, 0), और (44.999,0) के साथ शुरू करना, जो प्रत्येक जोड़ी के बीच केवल 111 मीटर की दूरी पर प्राइम मेरिडियन के साथ अलग हो जाते हैं, triसमाधान (11.8213, 77.745) प्राप्त करता है )। इसके आधार बिंदुओं से दूरी 8,127,964.998 77 है; 8,127,964.998 41; और 8,127,964.998 65 मीटर, क्रमशः। वे निकटतम मिलीमीटर के लिए सहमत हैं! मुझे यकीन नहीं है कि यह परिणाम कितना सही हो सकता है, लेकिन कम से कम आश्चर्यचकित नहीं होगा अगर अन्य कार्यान्वयन इस एक से दूर के स्थानों को वापस कर देते हैं, जो तीन दूरी की लगभग समान समानता दिखा रहा है।

अभिकलन का समय

ये गणना, क्योंकि वे जटिल दूरी की गणनाओं का उपयोग करके काफी खोज शामिल करते हैं, तेज नहीं होते हैं, आमतौर पर एक दूसरे के ध्यान देने योग्य अंश की आवश्यकता होती है। वास्तविक समय के अनुप्रयोगों के बारे में पता होना चाहिए।


ArcGIS कार्यान्वयन

पाइथन आर्कजीआईएस (संस्करण 9 के साथ शुरुआत) के लिए पसंदीदा स्क्रिप्टिंग वातावरण है। Scipy.optimize पैकेज बहुविविध rootfinder है rootजो क्या करना चाहिए FindRootमें करता है मेथेमेटिका कोड। बेशक ArcGIS ही सटीक दीर्घवृत्ताभ दूरी गणना प्रदान करता है। बाकी, फिर, सभी कार्यान्वयन विवरण हैं: तय करें कि आधार बिंदु निर्देशांक कैसे प्राप्त किया जाएगा (एक परत से? उपयोगकर्ता द्वारा टाइप किया गया; एक पाठ फ़ाइल से; माउस से?) और आउटपुट कैसे प्रस्तुत किया जाएगा (समन्वय के रूप में) स्क्रीन पर प्रदर्शित किया जाता है? एक ग्राफिक बिंदु के रूप में? एक परत में एक नई बिंदु वस्तु के रूप में?), उस इंटरफ़ेस को लिखें, यहां दिखाया गया मैथमेटिका कोड पोर्ट करें (सीधा), और आप सभी सेट हो जाएंगे।


3
+1 बहुत गहन। मुझे लगता है कि आपको इसके लिए चार्ज करना शुरू करना पड़ सकता है, @whuber।
रडार

2
@ राडार धन्यवाद मुझे उम्मीद है कि लोग मेरी किताब खरीदेंगे जब (कभी) यह अंततः दिखाई देगा :-)।
whuber

1
बिल करेंगे ... ड्राफ्ट भेजिए !!!

अति उत्कृष्ट! फिर भी, ऐसा लगता है कि एक विश्लेषणात्मक समाधान संभव होगा। 3 अंक ए, बी, सी और ई के साथ 3 डी कार्टेशियन स्पेस में समस्या को बहाल करके जहां ई पृथ्वी का केंद्र है। अगला दो प्लेन 1 और प्लेन 2 खोजें। प्लेन 1 प्लेन होगा जो प्लेनएबी के लिए सामान्य है और ई, मिडपॉइंट (ए, बी) से गुजर रहा है। इसी तरह, प्लेन 2 प्लेन के लिए सामान्य और ई, मिडपॉइंट (सी, ई) से गुजरने वाला विमान होगा। प्लेन 1 और प्लेन 2 के प्रतिच्छेदन द्वारा गठित लाइनओ 3 बिंदुओं के समतुल्य बिंदुओं का प्रतिनिधित्व करता है। ए (या बी या सी) के दो बिंदुओं के सबसे करीब जहां लाइनओ इंटरसेक्ट्स होता है वह पॉइंटो है।
कर्क कुक्केंडल

उस विश्लेषणात्मक समाधान, @Kirk, केवल क्षेत्र पर लागू होता है। (दीर्घवृत्त के साथ विमानों के
अंतर्विभाग

3

जैसा कि आप ध्यान दें, यह समस्या समुद्री सीमाओं को निर्धारित करने में उत्पन्न होती है; इसे अक्सर "त्रिकोणीय बिंदु" समस्या के रूप में संदर्भित किया जाता है और आप इसे Google कर सकते हैं और इसे संबोधित करने वाले कई कागजात पा सकते हैं। इन पत्रों में से एक मेरे द्वारा (!) है और मैं एक सटीक और तेजी से अभिसरण समाधान प्रदान करता हूं। Http://arxiv.org/abs/1102.1215 की धारा 14 देखें

विधि में निम्नलिखित चरण होते हैं:

  1. त्रि-बिंदु O का अनुमान लगाएं
  2. O का उपयोग अज़ीमुथल विषुवत प्रक्षेपण के केंद्र के रूप में करें
  3. इस प्रक्षेपण के लिए प्रोजेक्ट ए, बी, सी
  4. इस प्रक्षेपण में त्रि-बिंदु ज्ञात करें, O '
  5. प्रक्षेपण के नए केंद्र के रूप में O 'का उपयोग करें
  6. O ’और O के संयोग तक दोहराएं

प्रक्षेपण में त्रिकोणीय समाधान के लिए आवश्यक सूत्र कागज में दिया गया है। जब तक आप एक सटीक अज़ीमुथल समतुल्य प्रक्षेपण का उपयोग कर रहे हैं, तब तक उत्तर सटीक होगा। अभिसरण द्विघात अर्थ है कि केवल कुछ पुनरावृत्तियों की आवश्यकता है। यह लगभग निश्चित रूप से @whuber द्वारा सुझाए गए सामान्य रूट-खोज के तरीकों को बेहतर बनाएगा।

मैं सीधे ArcGIS के साथ आपकी मदद नहीं कर सकता। आप https://pypi.python.org/pypi/geographiclib से जियोडेसिक गणना करने के लिए मेरे अजगर पैकेज को पकड़ सकते हैं और इसके आधार पर प्रोजेक्शन को सरल बना सकते हैं।


संपादित करें

@ व्हिबर के पतित मामले (45 + एप्स, 0) (45,0) (45-ईपीएस, 0) में त्रिकोणीय बिंदु को खोजने की समस्या को केली द्वारा एक तिरछे गोलाकार , फिल पर जियोडेसिक लाइनों में माना गया था । पत्रिका। (1870), http://books.google.com/books?id=4XGIOoCMYYAC&pg=PA15

इस मामले में, त्रिकोणीय बिंदु को azimuth 90 के साथ (45,0) से जियोडेसिक का अनुसरण करके प्राप्त किया जाता है और उस बिंदु को खोजते हैं जिस पर जियोडेसिक स्केल गायब हो जाता है। WGS84 दीर्घवृत्त के लिए, यह बिंदु है (-0.10690908732248, 89.89291072793167)। इस बिंदु से प्रत्येक की दूरी (45.001,0), (45,0), (44.999) 10010287.665788943 मीटर (एक नैनोमीटर या तो के भीतर) है। यह व्हिबर के अनुमान से लगभग 1882 किमी अधिक है (जो कि यह बताता है कि यह मामला कितना अस्थिर है)। एक गोलाकार पृथ्वी के लिए, त्रिकोणीय बिंदु (0,90) या (0, -90) होगा, बिल्कुल।

ADDENDUM: यहाँ Matlab का उपयोग करके azimuthal विषुवतीय विधि का कार्यान्वयन किया गया है

function [lat, lon] = tripoint(lat1, lon1, lat2, lon2, lat3, lon3)
% Compute point equidistant from arguments
% Requires:
%   http://www.mathworks.com/matlabcentral/fileexchange/39108
%   http://www.mathworks.com/matlabcentral/fileexchange/39366
  lats = [lat1, lat2, lat3];
  lons = [lon1, lon2, lon3];
  lat0 = lat1;  lon0 = lon1; % feeble guess for tri point
  for i = 1:6
    [x, y] = eqdazim_fwd(lat0, lon0, lats, lons);
    a = [x(1), y(1), 0];
    b = [x(2), y(2), 0];
    c = [x(3), y(3), 0];
    z = [0, 0, 1];
    % Eq. (97) of http://arxiv.org/abs/1102.1215
    o = cross((a*a') * (b - c) + (b*b') * (c - a) + (c*c') * (a - b), z) ...
        / (2 * dot(cross(a - b, b - c), z));
    [lat0, lon0] = eqdazim_inv(lat0, lon0, o(1), o(2))
  end
  % optional check
  s12 = geoddistance(lat0, lon0, lats, lons); ds12 = max(s12) - min(s12)
  lat = lat0; lon = lon0;
end

ऑक्टेव I का उपयोग करके इसका परीक्षण करना

सप्तक: 1> प्रारूप लंबा
सप्तक: २> [अव्य ०, लोन ०] = त्रिशूल (४१, -36४,३६,१४०, -४१,१४४)
lat0 = 15.4151378380375
lon0 = -162.479314381144
lat0 = 15.9969703299812
lon0 = -147.046790722192
lat0 = 16.2232960167545
lon0 = -147.157646039471
lat0 = 16.2233394851560
lon0 = -147.157748279290
lat0 = 16.2233394851809
lon0 = -147.157748279312
lat0 = 16.2233394851809
lon0 = -147.157748279312
ds12 = 3.72529029846191e-09
lat0 = 16.2233394851809
lon0 = -147.157748279312

न्यूयॉर्क, टोक्यो और वेलिंगटन के लिए त्रिकोणीय बिंदु के रूप में।

यह विधि पड़ोसी कॉलिनियर बिंदुओं के लिए गलत है, उदाहरण के लिए, [45.001,0], [45,0], [44.999,0]। उस स्थिति में, आपको M 12 = 0 के लिए हल करना चाहिए, []५०,०] से अजीमुत ० पर निकलने वाली एक भू-आकृति पर। निम्न कार्य चाल (न्यूटन की विधि का उपयोग करके) करता है:

function [lat2,lon2] = semiconj(lat1, lon1, azi1)
% Find the point where neighboring parallel geodesics emanating from
% close to [lat1, lon1] with azimuth azi1 intersect.

  % First guess is 90 deg on aux sphere
  [lat2, lon2, ~, ~, m12, M12, M21, s12] = ...
      geodreckon(lat1, lon1, 90, azi1, defaultellipsoid(), true);
  M12
  % dM12/ds2 = - (1 - M12*M21/m12)
  for i = 1:3
    s12 = s12 - M12 / ( -(1 - M12*M21)/m12 ); % Newton
    [lat2, lon2, ~, ~, m12, M12, M21] = geodreckon(lat1, lon1, s12, azi1);
    M12
  end
end

उदाहरण के लिए, यह देता है:

[lat2, lon2] = अर्धचाल (45, 0, 90)
एम 12 = 0.00262997817649321
एम 12 = -6.08402492665097e-09
एम 12 = 4.38017677684144e-17
एम 12 = 4.38017677684144e-17
lat2 = -0.106909087322479
lon2 = 89.8929107279317

+1। हालांकि, यह स्पष्ट नहीं है कि एक सामान्य रूट खोजक किसी भी कम अच्छा प्रदर्शन करेगा: फ़ंक्शन को अपने इष्टतम और न्यूटन की विधि के पास अच्छी तरह से व्यवहार किया जाता है, उदाहरण के लिए, द्विघात रूप से भी परिवर्तित होगा। ( गणितज्ञ आम तौर पर अभिसरण के लिए लगभग चार कदम उठा रहे हैं; प्रत्येक चरण के लिए जैकोबियन का अनुमान लगाने के लिए चार मूल्यांकन की आवश्यकता होती है।) आपकी विधि को देखने का असली फायदा यह है कि इसे रूट खोजक के उपयोग का सहारा लिए बिना जीआईएस में आसानी से स्क्रिप्ट किया जा सकता है।
whuber

मैं सहमत हूँ। मेरी विधि न्यूटन के समतुल्य है और इसलिए, मैथेमेटिका की जड़ खोजने की विधि के विपरीत, मतभेदों को लेते हुए ढाल का अनुमान लगाने की आवश्यकता नहीं है।
cffk

सही - लेकिन आपको प्रत्येक बार प्रतिक्षेप करना पड़ता है, जो दिखता है कि यह समान कार्य के बारे में है। मैं आपके दृष्टिकोण की सादगी और लालित्य की सराहना करता हूं, हालांकि: यह तुरंत स्पष्ट है कि यह काम करना चाहिए और जल्दी से जुटेगा।
whuber

मैंने अपने उत्तर में एक ही परीक्षा अंक के लिए परिणाम पोस्ट किए हैं।
किर्क कुएकेन्डल

3

मैं यह देखने के लिए उत्सुक था कि एक समाधान पर @ cffk का दृष्टिकोण कितनी जल्दी परिवर्तित होता है, इसलिए मैंने आर्कोबजेक्ट्स का उपयोग करके एक परीक्षण लिखा, जिसने इस आउटपुट का उत्पादन किया। दूरी मीटर में हैं:

0 longitude: 0 latitude: 90
    Distances: 3134.05443974188 2844.67237777542 3234.33025754997
    Diffs: 289.382061966458 -389.657879774548 -100.27581780809
1 longitude: 106.906152157596 latitude: -6.31307123035178
    Distances: 1450.23208989615 1450.23208089398 1450.23209429293
    Diffs: 9.00216559784894E-06 -1.33989510686661E-05 -4.39678547081712E-06
2 longitude: 106.906583669013 latitude: -6.29691590176649
    Distances: 1450.23206976414 1450.23206976408 1450.23206976433
    Diffs: 6.18456397205591E-11 -2.47382558882236E-10 -1.85536919161677E-10
3 longitude: 106.906583669041 latitude: -6.29691590154641
    Distances: 1450.23206976438 1450.23206976423 1450.23206976459
    Diffs: 1.47565515362658E-10 -3.61751517630182E-10 -2.14186002267525E-10
4 longitude: 106.906583669041 latitude: -6.29691590154641
    Distances: 1450.23206976438 1450.23206976423 1450.23206976459
    Diffs: 1.47565515362658E-10 -3.61751517630182E-10 -2.14186002267525E-10

यहाँ स्रोत कोड है। (संपादित करें) FindCircleCenter को चौराहों (केंद्र बिंदु) को संभालने के लिए बदल दिया जो अज़िमुथल प्रक्षेपण के किनारे से गिरते हैं:

public static void Test()
{
    var t = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");
    var srf = Activator.CreateInstance(t) as ISpatialReferenceFactory2;
    var pcs = srf.CreateProjectedCoordinateSystem((int)esriSRProjCSType.esriSRProjCS_WGS1984N_PoleAziEqui)
        as IProjectedCoordinateSystem2;

    var pntA = MakePoint(106.9004975375, -6.28530175, pcs.GeographicCoordinateSystem);
    var pntB = MakePoint(106.89573839, -6.28955287, pcs.GeographicCoordinateSystem);
    var pntC = MakePoint(106.908087643421, -6.28388865789474, pcs.GeographicCoordinateSystem);

    int maxIter = 5;
    for (int i = 0; i < maxIter; i++)
    {
        var msg = string.Format("{0} longitude: {1} latitude: {2}", i, pcs.get_CentralMeridian(true), pcs.LatitudeOfOrigin);
        Debug.Print(msg);
        var newCenter = FindCircleCenter(ProjectClone(pntA, pcs), ProjectClone(pntB, pcs), ProjectClone(pntC, pcs));
        newCenter.Project(pcs.GeographicCoordinateSystem); // unproject
        var distA = GetGeodesicDistance(newCenter, pntA);
        var distB = GetGeodesicDistance(newCenter, pntB);
        var distC = GetGeodesicDistance(newCenter, pntC);
        Debug.Print("\tDistances: {0} {1} {2}", distA, distB, distC);
        var diffAB = distA - distB;
        var diffBC = distB - distC;
        var diffAC = distA - distC;
        Debug.Print("\tDiffs: {0} {1} {2}", diffAB, diffBC, diffAC);

        pcs.set_CentralMeridian(true, newCenter.X);
        pcs.LatitudeOfOrigin = newCenter.Y;
    }
}
public static IPoint FindCircleCenter(IPoint a, IPoint b, IPoint c)
{
    // from http://blog.csharphelper.com/2011/11/08/draw-a-circle-through-three-points-in-c.aspx
    // Get the perpendicular bisector of (x1, y1) and (x2, y2).
    var x1 = (b.X + a.X) / 2;
    var y1 = (b.Y + a.Y) / 2;
    var dy1 = b.X - a.X;
    var dx1 = -(b.Y - a.Y);

    // Get the perpendicular bisector of (x2, y2) and (x3, y3).
    var x2 = (c.X + b.X) / 2;
    var y2 = (c.Y + b.Y) / 2;
    var dy2 = c.X - b.X;
    var dx2 = -(c.Y - b.Y);

    // See where the lines intersect.
    var cx = (y1 * dx1 * dx2 + x2 * dx1 * dy2 - x1 * dy1 * dx2 - y2 * dx1 * dx2)
        / (dx1 * dy2 - dy1 * dx2);
    var cy = (cx - x1) * dy1 / dx1 + y1;

    // make sure the intersection point falls
    // within the projection.
    var earthRadius = ((IProjectedCoordinateSystem)a.SpatialReference).GeographicCoordinateSystem.Datum.Spheroid.SemiMinorAxis;

    // distance is from center of projection
    var dist = Math.Sqrt((cx * cx) + (cy * cy));
    double factor = 1.0;
    if (dist > earthRadius * Math.PI)
    {
        // apply a factor so we don't fall off the edge
        // of the projection
        factor = earthRadius / dist;
    }
    var outPoint = new PointClass() as IPoint;
    outPoint.PutCoords(cx * factor, cy* factor);
    outPoint.SpatialReference = a.SpatialReference;
    return outPoint;
}

public static double GetGeodesicDistance(IPoint pnt1, IPoint pnt2)
{
    var pc = new PolylineClass() as IPointCollection;
    var gcs = pnt1.SpatialReference as IGeographicCoordinateSystem;
    if (gcs == null)
        throw new Exception("point does not have a gcs");
    ((IGeometry)pc).SpatialReference = gcs;
    pc.AddPoint(pnt1);
    pc.AddPoint(pnt2);
    var t = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");
    var srf = Activator.CreateInstance(t) as ISpatialReferenceFactory2;
    var unit = srf.CreateUnit((int)esriSRUnitType.esriSRUnit_Meter) as ILinearUnit;
    var pcGeodetic = pc as IPolycurveGeodetic;
    return pcGeodetic.get_LengthGeodetic(esriGeodeticType.esriGeodeticTypeGeodesic, unit);
}

public static IPoint ProjectClone(IPoint pnt, ISpatialReference sr)
{
    var clone = ((IClone)pnt).Clone() as IPoint;
    clone.Project(sr);
    return clone;
}

public static IPoint MakePoint(double longitude, double latitude, ISpatialReference sr)
{
    var pnt = new PointClass() as IPoint;
    pnt.PutCoords(longitude, latitude);
    pnt.SpatialReference = sr;
    return pnt;
}

MSDN मैगज़ीन के जून 2013 अंक में वैकल्पिक दृष्टिकोण भी है, C # का उपयोग करके अमीबा विधि अनुकूलन


संपादित करें

पहले से पोस्ट किया कोड कुछ मामलों में एंटीपोड में परिवर्तित हो गया। मैंने कोड को बदल दिया है ताकि यह @ cffk के परीक्षण बिंदुओं के लिए यह आउटपुट उत्पन्न करे।

यहां अब इसका उत्पादन होता है:

0 0
0 longitude: 0 latitude: 0
    MaxDiff: 1859074.90170379 Distances: 13541157.6493561 11682082.7476523 11863320.2116807
1 longitude: 43.5318402621384 latitude: -17.1167429904981
    MaxDiff: 21796.9793742411 Distances: 12584188.7592282 12588146.4851222 12566349.505748
2 longitude: 32.8331167578493 latitude: -16.2707976739314
    MaxDiff: 6.05585224926472 Distances: 12577536.3369782 12577541.3560203 12577542.3928305
3 longitude: 32.8623898057665 latitude: -16.1374156408507
    MaxDiff: 5.58793544769287E-07 Distances: 12577539.6118671 12577539.6118666 12577539.6118669
4 longitude: -147.137582018133 latitude: 16.1374288796667
    MaxDiff: 1.12284109462053 Distances: 7441375.08265703 7441376.12671342 7441376.20549812
5 longitude: -147.157742373074 latitude: 16.2233413614432
    MaxDiff: 7.45058059692383E-09 Distances: 7441375.70752843 7441375.70752842 7441375.70752842
5 longitude: -147.157742373074 latitude: 16.2233413614432 Distance 7441375.70752843
iterations: 5

यहाँ संशोधित कोड है:

class Program
{
    private static LicenseInitializer m_AOLicenseInitializer = new tripoint.LicenseInitializer();

    [STAThread()]
    static void Main(string[] args)
    {
        //ESRI License Initializer generated code.
        m_AOLicenseInitializer.InitializeApplication(new esriLicenseProductCode[] { esriLicenseProductCode.esriLicenseProductCodeStandard },
        new esriLicenseExtensionCode[] { });
        try
        {
            var t = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");
            var srf = Activator.CreateInstance(t) as ISpatialReferenceFactory2;
            var pcs = srf.CreateProjectedCoordinateSystem((int)esriSRProjCSType.esriSRProjCS_World_AzimuthalEquidistant)
                as IProjectedCoordinateSystem2;
            Debug.Print("{0} {1}", pcs.get_CentralMeridian(true), pcs.LatitudeOfOrigin);
            int max = int.MinValue;
            for (int i = 0; i < 1; i++)
            {
                var iterations = Test(pcs);
                max = Math.Max(max, iterations);
                Debug.Print("iterations: {0}", iterations);
            }
            Debug.Print("max number of iterations: {0}", max);
        }
        catch (Exception ex)
        {
            Debug.Print(ex.Message);
            Debug.Print(ex.StackTrace);
        }
        //ESRI License Initializer generated code.
        //Do not make any call to ArcObjects after ShutDownApplication()
        m_AOLicenseInitializer.ShutdownApplication();
    }
    public static int Test(IProjectedCoordinateSystem2 pcs)
    {
        var pntA = MakePoint(-74.0, 41.0, pcs.GeographicCoordinateSystem);
        var pntB = MakePoint(140.0, 36.0, pcs.GeographicCoordinateSystem);
        var pntC = MakePoint(175.0, -41.0, pcs.GeographicCoordinateSystem);


        //var r = new Random();
        //var pntA = MakeRandomPoint(r, pcs.GeographicCoordinateSystem);
        //var pntB = MakeRandomPoint(r, pcs.GeographicCoordinateSystem);
        //var pntC = MakeRandomPoint(r, pcs.GeographicCoordinateSystem);

        int maxIterations = 100;
        for (int i = 0; i < maxIterations; i++)
        {
            var msg = string.Format("{0} longitude: {1} latitude: {2}", i, pcs.get_CentralMeridian(true), pcs.LatitudeOfOrigin);
            Debug.Print(msg);
            var newCenter = FindCircleCenter(ProjectClone(pntA, pcs), ProjectClone(pntB, pcs), ProjectClone(pntC, pcs));
            var c = ((IClone)newCenter).Clone() as IPoint;
            newCenter.Project(pcs.GeographicCoordinateSystem); // unproject
            //newCenter = MakePoint(-147.1577482, 16.2233394, pcs.GeographicCoordinateSystem);
            var distA = GetGeodesicDistance(newCenter, pntA);
            var distB = GetGeodesicDistance(newCenter, pntB);
            var distC = GetGeodesicDistance(newCenter, pntC);
            var diffAB = Math.Abs(distA - distB);
            var diffBC = Math.Abs(distB - distC);
            var diffAC = Math.Abs(distA - distC);
            var maxDiff = GetMax(new double[] {diffAB,diffAC,diffBC});
            Debug.Print("\tMaxDiff: {0} Distances: {1} {2} {3}",maxDiff, distA, distB, distC);
            if (maxDiff < 0.000001)
            {
                var earthRadius = pcs.GeographicCoordinateSystem.Datum.Spheroid.SemiMinorAxis;
                if (distA > earthRadius * Math.PI / 2.0)
                {
                    newCenter = AntiPode(newCenter);
                }
                else
                {
                    Debug.Print("{0} longitude: {1} latitude: {2} Distance {3}", i, pcs.get_CentralMeridian(true), pcs.LatitudeOfOrigin, distA);
                    return i;
                }
            }
            //Debug.Print("\tDiffs: {0} {1} {2}", diffAB, diffBC, diffAC);

            pcs.set_CentralMeridian(true, newCenter.X);
            pcs.LatitudeOfOrigin = newCenter.Y;
        }
        return maxIterations;
    }

    public static IPoint FindCircleCenter(IPoint a, IPoint b, IPoint c)
    {
        // from http://blog.csharphelper.com/2011/11/08/draw-a-circle-through-three-points-in-c.aspx
        // Get the perpendicular bisector of (x1, y1) and (x2, y2).
        var x1 = (b.X + a.X) / 2;
        var y1 = (b.Y + a.Y) / 2;
        var dy1 = b.X - a.X;
        var dx1 = -(b.Y - a.Y);

        // Get the perpendicular bisector of (x2, y2) and (x3, y3).
        var x2 = (c.X + b.X) / 2;
        var y2 = (c.Y + b.Y) / 2;
        var dy2 = c.X - b.X;
        var dx2 = -(c.Y - b.Y);

        // See where the lines intersect.
        var cx = (y1 * dx1 * dx2 + x2 * dx1 * dy2 - x1 * dy1 * dx2 - y2 * dx1 * dx2)
            / (dx1 * dy2 - dy1 * dx2);
        var cy = (cx - x1) * dy1 / dx1 + y1;

        // make sure the intersection point falls
        // within the projection.
        var earthRadius = ((IProjectedCoordinateSystem)a.SpatialReference).GeographicCoordinateSystem.Datum.Spheroid.SemiMinorAxis;

        // distance is from center of projection
        var dist = Math.Sqrt((cx * cx) + (cy * cy));
        double factor = 1.0;
        if (dist > earthRadius * Math.PI)
        {
            // apply a factor so we don't fall off the edge
            // of the projection
            factor = earthRadius / dist;
        }
        var outPoint = new PointClass() as IPoint;
        outPoint.PutCoords(cx * factor, cy* factor);
        outPoint.SpatialReference = a.SpatialReference;
        return outPoint;
    }

    public static IPoint AntiPode(IPoint pnt)
    {
        if (!(pnt.SpatialReference is IGeographicCoordinateSystem))
            throw new Exception("antipode of non-gcs projection not supported");
        var outPnt = new PointClass() as IPoint;
        outPnt.SpatialReference = pnt.SpatialReference;
        if (pnt.X < 0.0)
            outPnt.X = 180.0 + pnt.X;
        else
            outPnt.X = pnt.X - 180.0;
        outPnt.Y = -pnt.Y;
        return outPnt;
    }

    public static IPoint MakeRandomPoint(Random r, IGeographicCoordinateSystem gcs)
    {
        var latitude = (r.NextDouble() - 0.5) * 180.0;
        var longitude = (r.NextDouble() - 0.5) * 360.0;
        //Debug.Print("{0} {1}", latitude, longitude);
        return MakePoint(longitude, latitude, gcs);
    }
    public static double GetMax(double[] dbls)
    {
        var max = double.MinValue;
        foreach (var d in dbls)
        {
            if (d > max)
                max = d;
        }
        return max;
    }
    public static IPoint MakePoint(IPoint[] pnts)
    {
        double sumx = 0.0;
        double sumy = 0.0;
        foreach (var pnt in pnts)
        {
            sumx += pnt.X;
            sumy += pnt.Y;
        }
        return MakePoint(sumx / pnts.Length, sumy / pnts.Length, pnts[0].SpatialReference);
    }
    public static double GetGeodesicDistance(IPoint pnt1, IPoint pnt2)
    {
        var pc = new PolylineClass() as IPointCollection;
        var gcs = pnt1.SpatialReference as IGeographicCoordinateSystem;
        if (gcs == null)
            throw new Exception("point does not have a gcs");
        ((IGeometry)pc).SpatialReference = gcs;
        pc.AddPoint(pnt1);
        pc.AddPoint(pnt2);
        var t = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment");
        var srf = Activator.CreateInstance(t) as ISpatialReferenceFactory2;
        var unit = srf.CreateUnit((int)esriSRUnitType.esriSRUnit_Meter) as ILinearUnit;
        var pcGeodetic = pc as IPolycurveGeodetic;
        return pcGeodetic.get_LengthGeodetic(esriGeodeticType.esriGeodeticTypeGeodesic, unit);
    }

    public static IPoint ProjectClone(IPoint pnt, ISpatialReference sr)
    {
        var clone = ((IClone)pnt).Clone() as IPoint;
        clone.Project(sr);
        return clone;
    }

    public static IPoint MakePoint(double longitude, double latitude, ISpatialReference sr)
    {
        var pnt = new PointClass() as IPoint;
        pnt.PutCoords(longitude, latitude);
        pnt.SpatialReference = sr;
        return pnt;
    }
}

संपादित करें

यहां मुझे esriSRProjCS_WGS1984N_PoleAziEqui के साथ परिणाम मिले हैं

0 90
0 longitude: 0 latitude: 90
    MaxDiff: 1275775.91880553 Distances: 8003451.67666723 7797996.2370572 6727675.7578617
1 longitude: -148.003774863594 latitude: 9.20238223616225
    MaxDiff: 14487.6784785809 Distances: 7439006.46128994 7432752.45732905 7447240.13580763
2 longitude: -147.197808459106 latitude: 16.3073233548167
    MaxDiff: 2.32572609744966 Distances: 7441374.94409209 7441377.26981819 7441375.90768183
3 longitude: -147.157734641831 latitude: 16.2233338760411
    MaxDiff: 7.72997736930847E-08 Distances: 7441375.70752842 7441375.70752848 7441375.7075284
3 longitude: -147.157734641831 latitude: 16.2233338760411 Distance 7441375.70752842

यह प्रभावशाली त्वरित अभिसरण है! (+1)
whuber

आपको न्यूकेंटर पर केंद्रित एक ईमानदार-टू-गुडनेस अज़ीमुथल इक्विडिस्टेंट प्रोजेक्शन का उपयोग करना चाहिए। इसके बजाय आप एन पोल पर केंद्रित प्रक्षेपण का उपयोग कर रहे हैं और मूल को नए केंद्र में स्थानांतरित कर रहे हैं। इसलिए यह आकस्मिक हो सकता है कि आप इस मामले में एक सभ्य समाधान प्राप्त करें (शायद क्योंकि अंक एक साथ करीब हैं?)। अच्छा होगा कि इसे 3 बिंदुओं के साथ हजारों किमी अलग से आज़माएं।
अजीमुथल समकालिक

@cffk एक अन्य बिंदु पर एक विशेष बिंदु पर केंद्रित एक अजीमथल इक्विडिस्टेंट प्रोजेक्शन बनाने का एकमात्र तरीका मुझे एक ही विधि का उपयोग करना है लेकिन esriSRProjCS_WGS1984N_PoleAziEqui (- esriSRProjCS_World_AzimuthalEquididant) के बजाय एक ही विधि का उपयोग करना है। हालांकि एकमात्र अंतर यह है कि यह 0,90 (या 0, -90) के बजाय 0,0 पर केंद्रित है। क्या आप यह देखने के लिए मैथवर्क्स के साथ एक परीक्षण चलाने में मेरा मार्गदर्शन कर सकते हैं कि क्या यह "ईमानदारी-से-अच्छाई" के प्रक्षेपण से अलग परिणाम पैदा करता है?
कर्क कुक्केंडल

@KirkKuykendall: मेरे पहले उत्तर के लिए परिशिष्ट देखें।
cffk

1
@KirkKuykendall शायद ईएसआरआई ने "ईमानदारी-से-अच्छाई" प्रक्षेपण लागू किया है? इस एल्गोरिदम को काम करने के लिए आवश्यक प्रमुख संपत्ति यह है कि "केंद्र बिंदु" से मापी गई दूरी सही है। और यह संपत्ति जांचना आसान है। (केंद्र बिंदु के सापेक्ष अज़ीमुथल संपत्ति माध्यमिक है और केवल अभिसरण की दर को प्रभावित कर सकती है।)
cffk
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.