paint-brush
गैर-जीआईएस डेटाबेस पर जीआईएस संगणना कैसे करेंद्वारा@joellopes
1,662 रीडिंग
1,662 रीडिंग

गैर-जीआईएस डेटाबेस पर जीआईएस संगणना कैसे करें

द्वारा Joel Lopes9m2024/06/15
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

यदि आपका बैकएंड स्टोरेज मूल रूप से स्थानिक क्वेरी का समर्थन नहीं करता है, तो यह लेख आपके लिए तैयार किया गया है। आप स्थानिक डेटा को संभालने के लिए हमेशा एक और माइक्रोसर्विस बना सकते हैं, लेकिन इस विकल्प में अक्सर एक अतिरिक्त एप्लिकेशन को बनाए रखने का ओवरहेड शामिल होता है। एक अन्य दृष्टिकोण S2 और H3 जैसी जियो-इंडेक्सिंग लाइब्रेरी का उपयोग करना है। S2 गोले को कोशिकाओं में विभाजित करता है, जिनमें से प्रत्येक में एक अद्वितीय 64-बिट पहचानकर्ता होता है। उच्च स्तर बेहतर रिज़ॉल्यूशन और छोटे सेल क्षेत्रों के अनुरूप होते हैं।
featured image - गैर-जीआईएस डेटाबेस पर जीआईएस संगणना कैसे करें
Joel Lopes HackerNoon profile picture

परिचय:

कभी-कभी, आपको अपने एप्लिकेशन के भीतर भू-स्थानिक कार्य करने की आवश्यकता पड़ सकती है, जैसे कि उपयोगकर्ता स्थानों को मैप करना या भौगोलिक डेटा का विश्लेषण करना। इन कार्यों के लिए कई भाषा-विशिष्ट लाइब्रेरी उपलब्ध हैं, जैसे कि GDAL, Shapely और Python के लिए Geopandas।


वैकल्पिक रूप से, भू-स्थानिक कार्यक्षमता को डेटाबेस के माध्यम से क्रियान्वित किया जा सकता है; उदाहरण के लिए, आप PostgreSQL जैसे रिलेशनल डेटाबेस के साथ PostGIS एक्सटेंशन का उपयोग कर सकते हैं, या Azure CosmosDB जैसे वितरित डेटाबेस में स्थानिक डेटा प्रकारों के लिए मूल समर्थन का लाभ उठा सकते हैं।


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

मेरे पास क्या विकल्प हैं?

आप स्थानिक डेटा को संभालने के लिए हमेशा एक और माइक्रोसर्विस बना सकते हैं, लेकिन इस विकल्प में अक्सर एक अतिरिक्त एप्लिकेशन को बनाए रखने का ओवरहेड शामिल होता है। एक अन्य दृष्टिकोण S2 और H3 जैसी जियो-इंडेक्सिंग लाइब्रेरी का उपयोग करना है। Google द्वारा विकसित S2, हिल्बर्ट वक्र पर आधारित है, जबकि Uber द्वारा विकसित H3, एक जियोडेसिक असतत वैश्विक ग्रिड प्रणाली पर आधारित है। S2 और H3 में कई समानताएँ हैं: दोनों किसी दिए गए क्षेत्र को कोशिकाओं में विभाजित करते हैं और इन कोशिकाओं को अनुक्रमित करने के लिए 64-बिट पूर्णांक का उपयोग करते हैं।


हालाँकि, मुख्य अंतर कोशिकाओं के आकार में है; S2 वर्गाकार कोशिकाओं का उपयोग करता है, जबकि H3 षट्भुज आकार की कोशिकाओं का उपयोग करता है। कुछ अनुप्रयोगों के लिए, H3 बेहतर प्रदर्शन प्रदान कर सकता है। हालाँकि, कुल मिलाकर, दोनों में से कोई भी लाइब्रेरी पर्याप्त होनी चाहिए। इस लेख में, हम S2 का उपयोग करेंगे, लेकिन आप H3 का उपयोग करके समान कार्य कर सकते हैं।

गूगल S2 लाइब्रेरी की मूल अवधारणाएँ

  • कोशिकाएँ: S2 गोले को कोशिकाओं में विभाजित करता है, जिनमें से प्रत्येक में एक अद्वितीय 64-बिट पहचानकर्ता होता है।


  • सेल स्तर: पदानुक्रम बड़े क्षेत्रों से लेकर छोटे सटीक क्षेत्रों तक, विवरण के विभिन्न स्तरों की अनुमति देता है। प्रत्येक स्तर एक अलग रिज़ॉल्यूशन का प्रतिनिधित्व करता है:


    • स्तर 0: सबसे बड़ी कोशिकाएँ, जो पृथ्वी की सतह के एक महत्वपूर्ण हिस्से को कवर करती हैं।


    • उच्चतर स्तर: कोशिकाओं को क्रमिक रूप से छोटे-छोटे चतुर्थांशों में विभाजित किया जाता है। उदाहरण के लिए, स्तर 1 की प्रत्येक कोशिका को चार स्तर 2 कोशिकाओं में विभाजित किया जाता है, और इसी तरह आगे भी।


    • रिज़ॉल्यूशन और क्षेत्र: उच्च स्तर बेहतर रिज़ॉल्यूशन और छोटे सेल क्षेत्रों के अनुरूप हैं। यह पदानुक्रम अलग-अलग स्तरों पर सटीक अनुक्रमण और क्वेरी करने की अनुमति देता है।


नीचे दी गई तालिका विभिन्न कोशिका स्तरों को उनके संगत क्षेत्रों के साथ दर्शाती है।

स्तर

न्यूनतम क्षेत्र

अधिकतम क्षेत्र

औसत क्षेत्र

इकाइयां

कोशिकाओं की संख्या

00

85011012.19

85011012.19

85011012.19

किमी2

6

01

21252753.05

21252753.05

21252753.05

किमी2

24

02

4919708.23

6026521.16

5313188.26

किमी2

96

03

1055377.48

1646455.50

1328297.07

किमी2

384

04

231564.06

413918.15

332074.27

किमी2

1536

05

53798.67

104297.91

83018.57

किमी2

6के

06

12948.81

26113.30

20754.64

किमी2

24के

07

3175.44

6529.09

5188.66

किमी2

98के

08

786.20

1632.45

1297.17

किमी2

393के

09

195.59

408.12

324.29

किमी2

1573के

10

48.78

102.03

81.07

किमी2

6

11

12.18

25.51

20.27

किमी2

25एम

12

3.04

6.38

5.07

किमी2

100 मीटर

१३

0.76

1.59

1.27

किमी2

402एम

14

0.19

0.40

0.32

किमी2

1610एम

15

47520.30

99638.93

79172.67

एम2

6बी

16

11880.08

24909.73

19793.17

एम2

25बी

17

2970.02

6227.43

4948.29

एम2

103बी

18

742.50

1556.86

1237.07

एम2

412बी

19

185.63

389.21

309.27

एम2

1649बी

20

46.41

97.30

77.32

एम2

7टी

21

11.60

24.33

19.33

एम2

26टी

22

2.90

6.08

4.83

एम2

105टी

23

0.73

1.52

1.21

एम2

422टी

24

0.18

0.38

0.30

एम2

1689टी

25

453.19

950.23

755.05

सेमी 2

7ई15

26

113.30

237.56

188.76

सेमी 2

27ई15

27

28.32

59.39

47.19

सेमी 2

108ई15

28

7.08

14.85

11.80

सेमी 2

432ई15

29

1.77

3.71

2.95

सेमी 2

1729ई15

30

0.44

0.93

0.74

सेमी 2

7ई18



दी गई तालिका से यह स्पष्ट है कि आप S2 का उपयोग करके 0.44 cm^2 तक की मैपिंग परिशुद्धता प्राप्त कर सकते हैं। S2 सेल के प्रत्येक वर्ग के भीतर, एक चाइल्ड सेल मौजूद होता है जो एक ही पैरेंट को साझा करता है, जो एक पदानुक्रमित संरचना को दर्शाता है। सेल का स्तर एक स्थिर मान हो सकता है (सभी कोशिकाओं पर समान स्तर लागू होता है) या गतिशील हो सकता है जहाँ S2 तय करता है कि कौन सा रिज़ॉल्यूशन सबसे अच्छा काम करता है।

निकटतम पड़ोसियों की गणना

आइए एक उदाहरण से शुरू करते हैं। मान लीजिए कि हम एक ऐसा एप्लिकेशन लिख रहे हैं जो सिएटल क्षेत्र के लिए निकटता सेवा जैसी सुविधाएँ प्रदान करता है। हम दिए गए क्षेत्र में कॉफी की दुकानों की एक सूची लौटाना चाहते हैं। इन कार्यों को करने के लिए, हम इस कार्य को 4 उप-कार्यों में विभाजित करेंगे:


  • सिएटल मानचित्र लोड हो रहा है
  • सिएटल मानचित्र पर S2 कोशिकाओं को देखें
  • डेटाबेस में कुछ कॉफ़ी शॉप के स्थान संग्रहीत करें
  • निकटतम कॉफी शॉप के लिए पूछताछ

सिएटल मानचित्र लोड हो रहा है

Google मानचित्र लोड करने के लिए, हम gmplot लाइब्रेरी का उपयोग करेंगे। इस लाइब्रेरी को लोड करने के लिए Google मैप्स API कुंजी की आवश्यकता होती है। API कुंजी जनरेट करने के लिए, यहाँ दिए गए निर्देशों का पालन करें।

 import gmplot import const # plot seattle with zoom level 13 gmap = gmplot.GoogleMapPlotter(47.6061, -122.3328, 13, apikey=const.API_KEY) # Draw the map to an HTML file: gmap.draw('map.html')


उपरोक्त कोड एक map.html फ़ाइल उत्पन्न करता है जैसा कि नीचे दिखाया गया है:


सिएटल मानचित्र पर S2 कोशिकाओं को देखें

अब जब हमारे पास मानचित्र है, तो आइए मानचित्रों के लिए कुछ S2 कोशिकाएं बनाएं:

 from s2 import * import gmplot # plot seattle with zoom level 13 gmap = gmplot.GoogleMapPlotter(47.6061, -122.3328, 13, apikey=const.API_KEY) areatobeplotted = [ (47.64395531736767,-122.43597221319135), (47.51369277846956,-122.43597221319135), (47.51369277846956,-122.24156866779164), (47.64395531736767,-122.24156866779164), (47.64395531736767,-122.43597221319135) ] region_rect = S2LatLngRect( S2LatLng.FromDegrees(47.51369277846956,-122.43597221319135), S2LatLng.FromDegrees(47.64395531736767, -122.24156866779164)) coverer = S2RegionCoverer() coverer.set_min_level(8) coverer.set_max_level(15) covering = coverer.GetCovering(region_rect) geoms = 0 for cellid in covering: new_cell = S2Cell(cellid) vertices = [] for i in range(0, 4): vertex = new_cell.GetVertex(i) latlng = S2LatLng(vertex) vertices.append((latlng.lat().degrees(), latlng.lng().degrees())) gmap.polygon(*zip(*vertices), face_color='pink', edge_color='cornflowerblue', edge_width=5) geoms+=1 gmap.polygon(*zip(*areatobeplotted), face_color='red', edge_color='green', edge_width=5) print(f"Total Geometries: {geoms}") gmap.draw('/tmp/map.html')


 Output: Total Geometries: 273


ऊपर दिए गए कोड में, हम सबसे पहले सिएटल क्षेत्र के चारों ओर Google मैप प्लॉटर को केन्द्रित करते हैं। S2RegionCoverer में, हम क्षेत्र कवरर को न्यूनतम स्तर 8 और अधिकतम स्तर 15 के बीच गतिशील स्तर रखने के लिए आरंभ करते हैं। यह S2 को सभी कोशिकाओं को सर्वोत्तम फिट के लिए विशिष्ट सेल आकारों में गतिशील रूप से फ़िट करने की अनुमति देता है। GetCovering विधि सिएटल क्षेत्र के चारों ओर एक आयत के लिए कवरिंग लौटाती है।


फिर, हम प्रत्येक सेल पर पुनरावृत्ति करते हैं, कोशिकाओं के लिए शीर्षों की गणना करते हैं और उन्हें मानचित्र पर प्लॉट करते हैं। हम उत्पन्न कोशिकाओं की संख्या को लगभग 273 तक रखते हैं। अंत में, हम इनपुट आयत को लाल रंग में प्लॉट करते हैं। यह कोड सिएटल मानचित्र पर /tmp/map.html पर S2 कोशिकाओं को प्लॉट करेगा, जैसा कि नीचे दिखाया गया है:


डेटाबेस में कुछ कॉफ़ी शॉप के स्थान संग्रहीत करें

आइए कॉफी शॉप्स का डेटाबेस उनके S2 सेल पहचानकर्ताओं के साथ बनाएं। आप इन सेल को अपनी पसंद के किसी भी डेटाबेस में स्टोर कर सकते हैं। इस ट्यूटोरियल के लिए, हम SQLite डेटा डेटाबेस का उपयोग करेंगे। नीचे दिए गए कोड सैंपल में, हम 3 फ़ील्ड Id , name और cell_id के साथ CoffeeShops टेबल बनाने के लिए SQLite डेटाबेस से कनेक्ट करते हैं।


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


 import sqlite3 from s2 import S2CellId,S2LatLng,S2RegionCoverer # Connect to SQLite database conn = sqlite3.connect('/tmp/sqlite_cells.db') cursor = conn.cursor() # Create a table to store cell IDs cursor.execute('''CREATE TABLE IF NOT EXISTS CoffeeShops ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, cell_id TEXT )''') coverer = S2RegionCoverer() # Function to generate S2 cell ID for a given latitude and longitude def generate_cell_id(latitude, longitude, level=16): cell=S2CellId(S2LatLng.FromDegrees(latitude, longitude)) return str(cell.parent(level)) # Function to insert cell IDs into the database def insert_cell_ids(name,lat,lng): cell_id = generate_cell_id(lat, lng) cursor.execute("INSERT INTO CoffeeShops (name, cell_id) VALUES (?, ?)", (name, cell_id)) conn.commit() # Insert cell IDs into the database insert_cell_ids("Overcast Coffee", 47.616656277302155, -122.31156460382837) insert_cell_ids("Seattle Sunshine", 47.67366852914391, -122.29051997415843) insert_cell_ids("Sip House", 47.6682364706238, -122.31328618043693) insert_cell_ids("Victoria Coffee",47.624408595334536, -122.3117362652041) # Close connection conn.close()


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

निकटतम कॉफी शॉप के लिए पूछताछ

अंत में, आइए यूनिवर्सिटी डिस्ट्रिक्ट क्षेत्र में कॉफी की दुकानों के बारे में जानकारी प्राप्त करें।


 import sqlite3 from s2 import S2RegionCoverer,S2LatLngRect, S2LatLng # Connect to SQLite database conn = sqlite3.connect('/tmp/sqlite_cells.db') cursor = conn.cursor() # Function to query database for cells intersecting with the given polygon def query_intersecting_cells(start_x,start_y,end_x,end_y): # Create S2RegionCoverer region_rect = S2LatLngRect( S2LatLng.FromDegrees(start_x,start_y), S2LatLng.FromDegrees(end_x,end_y)) coverer = S2RegionCoverer() coverer.set_min_level(8) coverer.set_max_level(15) covering = coverer.GetCovering(region_rect) # Query for intersecting cells intersecting_cells = set() for cell_id in covering: cursor.execute("SELECT name FROM CoffeeShops WHERE cell_id >= ? and cell_id<=?", (str(cell_id.range_min()),str(cell_id.range_max()),)) intersecting_cells.update(cursor.fetchall()) return intersecting_cells # Query for intersecting cells intersecting_cells = query_intersecting_cells(47.6527847,-122.3286438,47.6782181, -122.2797203) # Print intersecting cells print("Intersecting cells:") for cell_id in intersecting_cells: print(cell_id[0]) # Close connection conn.close()
 Output: Intersecting cells: Sip House Seattle Sunshine

नीचे कोशिकाओं का एक दृश्य प्रतिनिधित्व है। संक्षिप्तता बनाए रखने के लिए, नीचे दिए गए विज़ुअलाइज़ेशन कोड को नहीं जोड़ा गया है।



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

निष्कर्ष:

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


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

संदर्भ: