MySQL में भौगोलिक बिंदुओं के बीच की दूरी का निर्धारण

आधुनिक साइट विकसित करते समय, पास के भौगोलिक बिंदुओं के आउटपुट की कार्यक्षमता को लागू करना अक्सर आवश्यक होता है। इस समस्या को हल करने का सबसे इष्टतम तरीका MySQL कंधों पर बिंदु परिभाषाओं को लागू करने के काम को स्थानांतरित करना है। विशेष रूप से, हमें MySQL के स्थानिक एक्सटेंशन (5.0.16 संस्करण से पहले) की क्षमताओं की आवश्यकता होगी, ये एक्सटेंशन केवल MyISAM के लिए उपलब्ध थे, बाद में MySQL के संस्करण InnoDB, NDB, BDB और ARCHIVE के साथ स्थानिक एक्सटेंशन का समर्थन करते हैं)।

अंक के बीच की दूरी की गणना हेवेरसिन सूत्र का उपयोग करके की जाएगी। सूत्र आपको बहुत कम त्रुटि वाले अंकों के बीच की दूरी प्राप्त करने की अनुमति देता है (अंकों के बीच की दूरी के लिए त्रुटि मान सीधे आनुपातिक है, और बहुत बड़ी दूरी की गणना करते समय 10-20 किलोमीटर से अधिक नहीं होता है, उदाहरण के लिए कैलिफोर्निया में Google मुख्यालय के बीच (37.422045, -122.084347) और ओपेरा हाउस सिडनी, ऑस्ट्रेलिया (-33.856553, 151.214696))।


दूरी के साथ पास के बिंदुओं की सही गणना करने के लिए, आपको निम्नलिखित संग्रहीत कार्य और प्रक्रियाएँ बनाने की आवश्यकता होगी:

जिओदिस्ट फ़ंक्शन

भूविज्ञानी () अपने निर्देशांक द्वारा बिंदुओं के बीच की दूरी निर्धारित करता है।

--  6371 -     ,       ,         DELIMITER $$ DROP FUNCTION IF EXISTS geodist $$ CREATE FUNCTION geodist ( src_lat DECIMAL(9,6), src_lon DECIMAL(9,6), dst_lat DECIMAL(9,6), dst_lon DECIMAL(9,6) ) RETURNS DECIMAL(6,2) DETERMINISTIC BEGIN SET @dist := 6371 * 2 * ASIN(SQRT( POWER(SIN((src_lat - ABS(dst_lat)) * PI()/180 / 2), 2) + COS(src_lat * PI()/180) * COS(ABS(dst_lat) * PI()/180) * POWER(SIN((src_lon - dst_lon) * PI()/180 / 2), 2) )); RETURN @dist; END $$ DELIMITER ; 


geodist_pt फ़ंक्शन

geodist_pt () भूविज्ञानी () के लिए एक आवरण है, और प्रकार के ऑब्जेक्ट के रूप में बिंदुओं के निर्देशांक के साथ काम करता है।
 DELIMITER $$ DROP FUNCTION IF EXISTS geodist_pt $$ CREATE FUNCTION geodist_pt (src POINT, dst POINT) RETURNS DECIMAL(6,2) DETERMINISTIC BEGIN RETURN geodist(X(src), Y(src), X(dst), Y(dst)); END $$ DELIMITER ; 


geobox_pt प्रक्रिया

जियोबॉक्स () प्रक्रिया का उपयोग करके खोज क्षेत्र के ऊपरी बाएं और निचले दाएं कोनों के निर्देशांक की गणना करता है, फिर परिणामस्वरूप निर्देशांक को POINT ऑब्जेक्ट में परिवर्तित करता है।

 -- pt ->     -- dist ->      -- top_lft ->      (  POINT) -- bot_rgt ->      (  POINT) DELIMITER $$ DROP PROCEDURE IF EXISTS geobox_pt $$ CREATE PROCEDURE geobox_pt ( IN pt POINT, IN dist DECIMAL(6,2), OUT top_lft POINT, OUT bot_rgt POINT ) DETERMINISTIC BEGIN CALL geobox(X(pt), Y(pt), dist, @lat_top, @lon_lft, @lat_bot, @lon_rgt); SET top_lft := POINT(@lat_top, @lon_lft); SET bot_rgt := POINT(@lat_bot, @lon_rgt); END $$ DELIMITER ; 


जियोबॉक्स प्रक्रिया

खोज क्षेत्र के निर्देशांक की गणना करता है।

 -- src_lat, src_lon ->     -- dist ->      -- lat_top, lon_lft ->       -- lat_bot, lon_rgt ->       DELIMITER $$ DROP PROCEDURE IF EXISTS geobox $$ CREATE PROCEDURE geobox ( IN src_lat DECIMAL(9,6), IN src_lon DECIMAL(9,6), IN dist DECIMAL(6,2), OUT lat_top DECIMAL(9,6), OUT lon_lft DECIMAL(9,6), OUT lat_bot DECIMAL(9,6), OUT lon_rgt DECIMAL(9,6) ) DETERMINISTIC BEGIN SET lat_top := src_lat + (dist / 69); SET lon_lft := src_lon - (dist / ABS(COS(RADIANS(src_lat)) * 69)); SET lat_bot := src_lat - (dist / 69); SET lon_rgt := src_lon + (dist / ABS(COS(RADIANS(src_lat)) * 69)); END $$ DELIMITER ; 


उपयोग उदाहरण:

मान लीजिए कि एक तालिका है जिसमें भौगोलिक डेटा संग्रहीत है। तालिका में निम्न संरचना है:
 CREATE TABLE geo ( id INT, name VARCHAR(100), x DECIMAL(9,6), y DECIMAL (9,6) ); 

फिर, शुरुआती बिंदु से 200 किलोमीटर की दूरी पर स्थित सभी बस्तियों को प्राप्त करने के लिए, आपको निम्नलिखित कार्य करने होंगे:
 --   src        POINT (  Point()    POINT    ) SELECT @src := Point(x,y) FROM geo WHERE name = ''; --  " "    CALL geobox_pt(@src, 200.0, @top_lft, @bot_rgt); --   SELECT g.name, geodist(X(@src), Y(@src), x, y) AS dist FROM geo g WHERE x BETWEEN X(@top_lft) AND X(@bot_rgt) AND y BETWEEN Y(@top_lft) AND Y(@bot_rgt) HAVING dist < 200.0 ORDER BY dist desc; 

Source: https://habr.com/ru/post/In179157/


All Articles