लपेटे हुए किनारों के साथ दुनिया में यात्रा की दिशा का पता लगाना


20

मुझे अपनी 2 डी दुनिया में एक बिंदु से दूसरे बिंदु तक कम से कम दूरी की दिशा खोजने की आवश्यकता है जहां किनारों को लपेटा जाता है (जैसे क्षुद्रग्रह आदि)। मुझे पता है कि सबसे कम दूरी कैसे पता करें लेकिन मैं यह पता लगाने के लिए संघर्ष कर रहा हूं कि यह किस दिशा में है।

सबसे कम दूरी किसके द्वारा दी गई है:

int rows = MapY;
int cols = MapX;

int d1 = abs(S.Y - T.Y);
int d2 = abs(S.X - T.X);
int dr = min(d1, rows-d1);
int dc = min(d2, cols-d2);

double dist = sqrt((double)(dr*dr + dc*dc));

दुनिया का उदाहरण

                   :         
                   :  T    
                   :         
    :--------------:---------
    :              :
    :           S  :
    :              :
    :              :
    :  T           :
    :              :
    :--------------:

आरेख में किनारों को इसके साथ दिखाया गया है: और -। मैंने शीर्ष दाईं ओर भी दुनिया का एक लिपटा हुआ दोहराव दिखाया है। मैं S से T तक की दिशा में दिशा खोजना चाहता हूं। इसलिए सबसे छोटी दूरी T के शीर्ष दाएं दोहराना है। लेकिन मैं S से नीचे की ओर दोहराए जाने वाले दिशा में शीर्ष दाएं में कैसे गणना करूं?

मैं S और T दोनों की स्थिति जानता हूं, लेकिन मुझे लगता है कि मुझे दोहराया T की स्थिति का पता लगाने की जरूरत है, हालांकि 1 से अधिक है।

दुनिया निर्देशांक प्रणाली 0,0 से ऊपर बाईं ओर शुरू होती है और दिशा के लिए 0 डिग्री पश्चिम में शुरू हो सकती है।

ऐसा लगता है कि यह बहुत कठिन नहीं होना चाहिए, लेकिन मैं एक समाधान नहीं कर पा रहा हूं। मुझे उम्मीद है कि सोमोन मदद कर सकता है? किसी भी वेबसाइट की सराहना की जाएगी।


शीर्ष दाईं ओर T के लिए निर्देशांक क्या हैं?

मैंने कभी विकर्ण लपेटने वाला खेल नहीं देखा। आमतौर पर आपके पास प्रत्येक दिशा (एन, ई, एस, डब्ल्यू) के लिए एक रैप होता है।

5
कोई भी गेम जिसमें क्षैतिज और ऊर्ध्वाधर दोनों रैपिंग होती है, डिफ़ॉल्ट रूप से विकर्ण रैपिंग होती है।

एक सर्कल पर रहने वाले प्रत्येक समन्वय के बारे में सोचें, और व्यक्तिगत रूप से समन्वय के लिए दो संभावित दूरी के छोटे को समझें।
केरेक एसबी

1
@ क्रेजी: विकिपीडिया पर "टोरस" देखें ...
केरेक एसबी

जवाबों:


8

आपको कोण की गणना करने के लिए अपने एल्गोरिथ्म को थोड़ा मोड़ना होगा - वर्तमान में आप केवल स्थिति में पूर्ण अंतर रिकॉर्ड करते हैं, लेकिन आपको सापेक्ष अंतर की आवश्यकता होती है (यानी स्थिति के आधार पर सकारात्मक या नकारात्मक हो सकती है)।

int dx = T.X - S.X; // difference in position
int dy = T.Y - S.Y;

if (dx > MapX / 2) // if distance is bigger than half map width, then looping must be closer
    dx = (dx - MapX) * -1; // reduce distance by map width, reverse 
else if (dx < -MapX / 2) // handle the case that dx is negative
    dx = (dx + MapX) * -1;

//Do the same for dy
if (dy > MapY / 2)
    dy = (dy - MapY) * -1;
else if (dy < -MapY / 2)
    dy = (dy + MapY) * -1;

double dist = sqrt(dy*dy+dx*dx); // same as before
double angle = atan2(dy,dx) * 180 / PI; // provides angle in degrees

1
आपको dx और dy के संकेतों पर कुछ काम करने की आवश्यकता है क्योंकि कोड टूट जाएगा यदि TX SX से कम है या TY XY से कम है तो अन्य की तुलना में यह सबसे अच्छा समाधान IMHO है।
स्कॉट चैंबरलेन

ठीक है तो मैं ठीक कर दूँगा।

1
फिर भी कुछ त्रुटियां मिलीं कि dx और dy का संकेत क्या होगा जब सभी को कहा जाता है और किया जाता है, अगर मैं संपादित करता हूं तो मन?
स्कॉट चैंबरलेन

यह स्वीकृत उत्तर क्यों है ?? यह भी काम नहीं करता है । मान लीजिए MapXकि 100 है, T.X90 है और S.X10. dxस्पष्ट रूप से 20 होना चाहिए, लेकिन यह एल्गोरिथ्म 30 को लौटेगा!
सैम होसेवर

उह यह तब होता है जब आपको पोस्ट करने से पहले कोड का परीक्षण करने का अवसर नहीं देना पड़ता है। ठीक कर देंगे। अगर किसी को इसके साथ एक और त्रुटि मिलती है, तो शायद मैं इसे हटा दूं इससे पहले कि बहुत से लोग गुमराह हो जाएं।
टोमाई

11

ऐसी दुनिया में S से T तक के अनंत मार्ग हैं। आइए T (Tx, Ty)के निर्देशांक, S के निर्देशांक (Sx, Sy)और दुनिया के आकार के अनुसार निरूपित करें (Wx, Wy)। टी के लिपटे निर्देशांक पूर्णांक, (Tx + i * Wx, Ty + j * Wy)जहां iऔर jसेट के तत्व हैं, हैं {..., -2, -1, 0, 1, 2, ...}। S से T को जोड़ने वाले वैक्टर हैं (Dx, Dy) := (Tx + i * Wx - Sx, Ty + j * Wy - Sy)। दी गई (i, j)जोड़ी के लिए, दूरी वेक्टर की लंबाई है sqrt(Dx * Dx + Dy * Dy), और रेडियन में दिशा है atan(Dy / Dx)कम से कम पथ 9 पथ, जहां से एक है iऔर jकर रहे हैं {-1, 0, 1}: यहां छवि विवरण दर्ज करें

iऔर jके लिए मान कम से कम पथ सीधे निर्धारित किया जा सकता:

int i = Sx - Tx > Wx / 2 ? 1 : Sx - Tx < -Wx / 2 ? -1 : 0;
int j = Sy - Ty > Wy / 2 ? 1 : Sy - Ty < -Wy / 2 ? -1 : 0;

आपकी मदद के लिए, @IlmariKaronen, @SamHocevar और @romkyns धन्यवाद!


1
आप इससे बेहतर कर सकते हैं: यदि abs(Tx-Sx) < Wx/2, तो i=0इष्टतम है; अन्यथा इष्टतम विकल्प i=-1या i=1, के संकेत पर निर्भर करता है Tx-Sx। उसी के लिए चला जाता है Ty-Syऔर j
इल्मरी करोनन

1
ऐसी सरल समस्या के लिए यह उत्तर अविश्वसनीय रूप से जटिल है। जब न्यूनतम मूल्य की सीधे गणना की जा सकती है तो रैखिक खोज का उपयोग करने की कोई आवश्यकता नहीं है।
सैम होसेवर

अच्छा चित्र, लेकिन एल्गोरिथ्म ने सुझाव दिया कि इस उत्तर को प्राप्त होने वाले किसी भी उत्थान के लायक नहीं है।
रोमनस्टैंड

5

एक संभव दिशा सदिश की गणना करें, भले ही यह सबसे छोटा न हो, फिर अपने एक्स को समन्वयित करें ताकि वह [-MapX/2,MapX/2]सीमा में हो, और वाई के लिए भी:

int DirX = (T.X - S.X + 3 * MapX / 2) % MapX) - MapX / 2;
int DirY = (T.Y - S.Y + 3 * MapY / 2) % MapY) - MapY / 2;

बस! आपको आगे की गणना के बिना भी दूरी मिलती है:

double dist = sqrt((double)(DirX*DirX + DirY*DirY));

धन्यवाद! GLSL संस्करण:vec2 toroidalNearestWay (vec2 from, vec2 to, vec2 mapSize) { return (mod((to - from + 3.0 * mapSize / 2.0), mapSize)) - mapSize / 2.0; }
1j01

0

मुझे लगता है कि ऐसा करने के कई तरीके हैं। यहाँ 2 हैं मैं अपने सिर के ऊपर से सोच सकता हूँ:

# 1: मैन्युअल रूप से मामलों को संभालें

ठीक 10 मामले हो सकते हैं:

  • यह उसी टाइल के रूप में है S
  • यह आसपास की 8 टाइलों में से किसी में है
  • यह बिल्कुल नहीं पाया जाता है।

आसपास की प्रत्येक टाइल के लिए हालांकि, वे एक्स या वाई दूरी घटक के लिए अलग-अलग गणना के क्रमपरिवर्तन हैं। क्योंकि यह मामलों की एक सीमित संख्या है, आप केवल हार्ड-कोड कर सकते हैं कि उनकी गणना कैसे करें, और उन सभी के बीच सबसे कम दूरी का पता लगाएं।

खोजने के लिए यहां 2 मामलों का चित्रण है dx। केस 1, जहां Tएक ही टाइल में है S, dx बस है S.x - T.x। टाइल्स के दाईं ओर, के dxरूप में गणना की जाएगी TileWidth - S.x + T.x

               :         
               :  T    
               :         
:--------------:---------
:              :
:           S  :
:  |--------|--:--|
:dx=(S.x-T.x) dx=(TileWidth-S.x+T.x)
:  T           :
:              :
:--------------:

एक छोटे अनुकूलन के रूप में, एक वर्गमूल लेने से पहले न्यूनतम दूरी का पता लगाएं। तब आप अपने आप को 7 sqrtकॉल तक बचा लेते हैं।

# 2: निर्देशांक को सार

यदि आपको पथ-खोजने वाले एल्गोरिथ्म की तरह कुछ अधिक स्थानिक रूप से "तरल पदार्थ" करने की आवश्यकता है, तो निर्देशांक को अमूर्त करें ताकि आपके पथ को खोजने वाला एल्गोरिदम भी महसूस न करे कि दुनिया पुनरावृत्ति करने वाली टाइलों से बनी है। पथ-खोज एल्गोरिथ्म सैद्धांतिक रूप से किसी भी दिशा में असीम रूप से जा सकता है (ठीक है आप संख्यात्मक सीमा तक सीमित होंगे, लेकिन आपको बिंदु मिलता है)।

साधारण दूरी की गणना के लिए, ऐसा करने से परेशान न हों।


वर्गर्ट लेने से पहले चुकता दूरी के मूल्य की तुलना करने के बारे में स्मार्ट विचार!
स्कॉट चैंबरलेन

आह मैं देख रहा हूँ, @Kol का एक और गणितीय स्पष्टीकरण के साथ एक समान उत्तर है, धन्यवाद इससे मुझे काम करने के लिए कुछ मिलता है

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

0

"9 दिशाओं" से परेशान न हों। इसका कारण यह है कि उन 9 में से 5 पतित मामले हैं: "सीधे उत्तर", "स्ट्रैजीट वेस्ट", "स्ट्रेट साउथ", "स्ट्रेट ईस्ट" और "समरूप"। उदाहरण के लिए, सीधा उत्तर पतित है क्योंकि यह उस मामले का प्रतिनिधित्व करता है जहां उत्तर-पश्चिम और उत्तर-पूर्व जुड़ते हैं और एक ही परिणाम उत्पन्न करते हैं।

इस प्रकार, आपके पास गणना करने के लिए 4 दिशाएं हैं, और बस न्यूनतम उठा सकते हैं।


मुझे नहीं लगता कि यह सही है, या मैंने आपको पूरी तरह से गलत समझा है। इन दो में से एक।

-1

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

मैंने मामले में किसी और को इस पेज को ढूंढने के लिए पोस्ट किया है और इसमें उल्टा y सिस्टम है।

  int dx = T.X - S.X; // difference in position
int dy = S.Y - T.Y;

if (dx > MapX / 2) // if distance is bigger than half map width, then looping must be closer
    dx = (dx - (MapX / 2)) * -1; // reduce distance by half map width, reverse 
else if (dx < -MapX / 2) // handle the case that dx is negative
    dx = (dx + (MapX / 2)) * -1;

//Do the same for dy
if (dy > MapY / 2)
    dy = (MapY - dy)) * -1;
else if (dy < -MapY / 2)
    dy = (dy + MapY);

double angle = atan2(dy,dx) * 180 / PI; // provides angle in degrees

angle = 180 - angle; //convert to 360 deg

यह कोड टोमाई से थोड़ा बेहतर है, लेकिन काम नहीं करता है।
सैम होसेवर

1
साथ ही, आपको यह समझने की आवश्यकता है कि आपको ये बदलाव क्यों करने थे। ऐसा नहीं है क्योंकि आपका समन्वय प्रणाली yसबसे ऊपर से शुरू होती है । ऐसा इसलिए है क्योंकि वांछित व्यवहार को दुनिया के किनारे पर निर्देशांक लपेटने के लिए माना जाता है , जबकि आपके द्वारा पुन: उपयोग किए गए कोड ने प्रत्येक सीमा पर निर्देशांक को प्रतिबिंबित किया है।
सैम होसेवर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.