首页 > 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
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板