首頁 > web前端 > js教程 > 地理空間索引取樣器

地理空間索引取樣器

Barbara Streisand
發布: 2024-12-30 09:48:22
原創
819 人瀏覽過

Geospatial Indexing Sampler

我最近做了一個練習,假裝自己是極簡主義者,試圖建立一個應用程式。這要求我能夠在不使用我久經考驗的朋友 PostGIS 的情況下過濾 GPS 點。

我快速瀏覽了三種最受歡迎的空間資料索引方法:Geohash、H3 和 S2。

所有這 3 個工具的工作原理都是將地球分割成形狀,當您放大時,這些形狀會細分為越來越小的單位。

  • GeoHash 使用長方形
  • H3 使用六邊形
  • S2是狂野的,使用空間填充曲線

探索這些類型的索引如何運作的一個好方法是 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))
登入後複製

H3

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))
登入後複製

S2

// 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中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板