我最近做了一個練習,假裝自己是極簡主義者,試圖建立一個應用程式。這要求我能夠在不使用我久經考驗的朋友 PostGIS 的情況下過濾 GPS 點。
我快速瀏覽了三種最受歡迎的空間資料索引方法:Geohash、H3 和 S2。
所有這 3 個工具的工作原理都是將地球分割成形狀,當您放大時,這些形狀會細分為越來越小的單位。
探索這些類型的索引如何運作的一個好方法是 https://geohash.softeng.co/。當您單擊每個單元格時,它會放大並顯示更深層的內容。世界上我最喜歡的地方之一是 GeoHash ddk6p5
使用這些來「索引」GPS 資料就像為您感興趣的每個層級添加文字列一樣簡單。例如,我可以建立一個如下表:
CREATE TABLE IF NOT EXISTS places ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, latitude REAL, longitude REAL, geohash_level_2 TEXT, geohash_level_4 TEXT ); INSERT INTO places (name,latitude,longitude,geohash_level_2,geohash_level_4) VALUES('mt shavano', 38.618840, -106.239364, '9w', '9wu7'); INSERT INTO places (name,latitude,longitude,geohash_level_2,geohash_level_4) VALUES('blanca peak', 37.578047, -105.485796, '9w', '9wsv'); INSERT INTO places (name,latitude,longitude,geohash_level_2,geohash_level_4) VALUES('mt princeton', 38.749148, -106.242578, '9w', '9wuk'); INSERT INTO places (name,latitude,longitude,geohash_level_2,geohash_level_4) VALUES('la soufriere', 13.336299, -61.177146, 'dd', 'ddk7');
Sqlime 是嘗試這些查詢的好地方。
然後要查找科羅拉多州南部的地方,我會找到哪個哈希覆蓋了地圖上的“9w”部分:
SELECT * FROM places WHERE geohash_level_2 = '9w';
要找加勒比海南部的地方,我可以使用:
SELECT * FROM places WHERE geohash_level_2 = 'dd';
這種方法確實需要預先規劃您需要在資料庫中保留哪些層級的索引。 否則,它非常適合需要快速查找特定區域或地圖視窗中找到的物件的簡單應用程式。
擁有支援 LIKE 查詢的資料庫可以幫助減少使用多列的情況。另請注意,H3 儲存格編號並不完全重疊,因此「開頭為」類型查詢不適用於 H3。
最後,這些索引的一個巧妙功能是,單元格數量將成為很棒的即時事件主題。 因此,在上面的範例中,我可以為科羅拉多州南部創建一個名為“9w”的事件主題。然後,隨著新地點的添加,我會在每個新地點的「9w」主題中發出事件。
以下是每個索引類型的一些範例 JavaScript (deno) 程式碼:
請注意,可以在此處查看 GeoJSON 輸出:https://geojson.io/
import { geocoordinateToGeohash } from 'npm:geocoordinate-to-geohash' import { geohashToPolygonFeature } from 'npm:geohash-to-geojson' import geohash from 'npm:ngeohash' const lat = 38.618840 const lng = -106.239364 const hash2 = geohash.encode(lat, lng, 2) console.log('mt shavano hash at level 2', hash2) const feat2 = geohashToPolygonFeature(hash2) console.log('mt shavano hash at level 2 bounds', JSON.stringify(feat2)) // About a city block in size in CO (size changes as you head towards poles) const hash7 = geohash.encode(lat, lng, 7) console.log('mt shavano hash at level 4', hash7) const feat7 = geohashToPolygonFeature(hash7) console.log('mt shavano hash at level 4 bounds', JSON.stringify(feat7))
import h3 from 'npm:h3-js' import geojson2h3 from "npm:geojson2h3" const lat = 38.618840 const lng = -106.239364 // Level 2 (~1/3 Colorado Size) const h3IndexL2 = h3.latLngToCell(lat, lng, 2); console.log('mt shavano cell at level 2', h3IndexL2) const featureL2 = geojson2h3.h3ToFeature(h3IndexL2) console.log('mt shavano cell at level 2 bounds', JSON.stringify(featureL2)) // Level 4 (~City of Salida Size) const h3IndexL4 = h3.latLngToCell(lat, lng, 4); console.log('mt shavano cell at level 4', h3IndexL4) const featureL4 = geojson2h3.h3ToFeature(h3IndexL4) console.log('mt shavano cell at level 4 bounds', JSON.stringify(featureL4))
// This might be a better choice : https://www.npmjs.com/package/@radarlabs/s2 import s2 from 'npm:s2-geometry' const S2 = s2.S2 const lat = 38.618840 const lng = -106.239364 const key2 = S2.latLngToKey(lat, lng, 2) const id2 = S2.keyToId(key2) const feature2 = cellCornersToFeatureCollection(lat, lng, 2) console.log('mt shavano key at level 2', key2) console.log('mt shavano cell id at level 2', id2) console.log('mt shavano cell at level 2 corners', JSON.stringify(feature2)) const key4 = S2.latLngToKey(lat, lng, 4) const id4 = S2.keyToId(key4) const feature4 = cellCornersToFeatureCollection(lat, lng, 4) console.log('mt shavano key at level 4', key4) console.log('mt shavano cell id at level 4', id4) console.log('mt shavano cell at level 4 corners', JSON.stringify(feature4)) function cellCornersToFeatureCollection(lat, lng, level) { const ll = S2.L.LatLng(lat, lng) const cell = S2.S2Cell.FromLatLng(ll, level) const corners = cell.getCornerLatLngs() const coordinates = corners.map((pair) => { return [pair.lng, pair.lat] }) return { "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Polygon", "coordinates": [coordinates] }, "properties": {} } ] } }
以上是地理空間索引取樣器的詳細內容。更多資訊請關注PHP中文網其他相關文章!