根据经度和纬度设计网格叠加

时间:2009-11-01 20:03:58

标签: geocoding algorithm

我正试图找出解决以下问题的最佳方法:

说我对地球有一个平面的表示。我想创建一个网格,将网格覆盖在网格上的每个方格对应约3平方公里。每个方块都有一个唯一的区域ID。这个网格只存储在一个数据库表中,该表有一个区域id,然后可能是该区域四个角的长/纬度坐标,对吗?有关如何轻松生成此表的任何建议?我知道我首先需要找出这个“扁平地球”的宽度和高度,以公里为单位,计算区域的数量,然后以某种方式将长/拉分配给每个垂直/水平线的交点;然而,这听起来像很多手工作品。

其次,一旦我创建了网格表,我需要设计一个fxn,它接受一个长/ lat对,然后确定它所在的逻辑“区域”。我不知道该怎么做。< / p>

任何帮助将不胜感激。

感谢。

5 个答案:

答案 0 :(得分:3)

假设地球是半径为R = 6371 km的球体。

从(lat,long)=(0,0)deg开始。在赤道附近,3公里对应经度的变化

dlong = 3 / (2 * pi * R) * 360 
      = 0.0269796482 degrees

如果我们在赤道附近走动并且每3公里放一个标记,那么它们将大约有(2 * pi * R) / 3 = 13343.3912个。 “关于”,因为你决定如何处理额外的0.3912。

从(0,0)开始,向北走3公里到(纬度,长度)(0.0269796482,0)。我们将在一条与我们行走的第一条路径平行的路径上再次绕地球行走。因为它离N极更近一点,所以这个圆的半径比我们走过的第一个圆的半径小一点。让我们使用小写r来表示这个半径

r = R * cos(lat)
  = 6371 * cos(0.0269796482)
  = 6 368.68141 km

我们使用较小的半径

再次计算dlong
dlong = 3 / (2 * pi * r) * 360
      = 0.0269894704 deg

我们放下了第二组标志。这次约有(2 * pi * r) / 3 = 13 338.5352个。之前有13,343,但现在有13,338。那是什么?少了五个。

当顶线有五个角落时,我们如何绘制正方形带?事实上,当我们在地球上行走时,我们发现我们从相当不错的方块开始,但是这些区域的形状被剪切成非常极端的平行四边形。

我们需要一种不同的策略,为我们提供相同数量的角落。如果下边界(SW-SE)长3公里,那么顶部应该稍短,以制作梯形带。

有很多方法可以制定出与理想方格相近的折衷方案。 This wikipedia article用于保留指标属性的地图投影,链接到数十种此类策略。

您的应用的细节可能会让您大大简化,特别是如果您不需要映射整个地球。

答案 1 :(得分:2)

Microsoft一直在SQL Server 2008产品中投资空间数据类型。它可以帮助你在这里。因为它具有表示展平地球区域的数据类型,所以操作员可以确定一组坐标何时位于几何体内等。即使您选择不使用它,也可以考虑检查以下链接。第二个特别是关于这个问题有很多很好的背景信息,并讨论了一些空间数据的行业标准数据格式。

http://www.microsoft.com/sqlserver/2008/en/us/spatial-data.aspx

http://jasonfollas.com/blog/archive/2008/03/14/sql-server-2008-spatial-data-part-1.aspx

答案 2 :(得分:1)

你确实意识到,因为地球是一个球体,“三平方公里”的极点附近的度数将不是赤道附近,对吗?在地图的顶部和底部,你的网格方块实际上代表了世界上的饼形部分,对吗?

我已经用我的数据库做了类似的事情 - 我把它分解成了四元组。所以我所做的就是将地球划分为四个季度(-180,-90) - (0,0),(-180,0) - (0,90),依此类推。当我将点实体添加到我的数据库中时,如果“单元格”超过X个条目,我将单元格拆分为4.这意味着在世界上有很多点实体的区域,我有很多四元组,但是在世界其他地方我很少。

我的四叉树数据库如下所示:

\d areaids;
                 Table "public.areaids"
    Column    |            Type             | Modifiers 
--------------+-----------------------------+-----------
 areaid       | integer                     | not null
 supercededon | timestamp without time zone | 
 supercedes   | integer                     | 
 numpoints    | integer                     | not null
 rectangle    | geometry                    | 
Indexes:
    "areaids_pk" PRIMARY KEY, btree (areaid)
    "areaids_rect_idx" gist (rectangle)
Check constraints:
    "enforce_dims_rectangle" CHECK (ndims(rectangle) = 2)
    "enforce_geotype_rectangle" CHECK (geometrytype(rectangle) = 'POLYGON'::text OR rectangle IS NULL)
    "enforce_srid_rectangle" CHECK (srid(rectangle) = 4326)

我正在使用PostGIS帮助查找单元格中的点。如果我看一个单元格,我可以判断它是否被拆分,因为supercededon不是null。我可以通过寻找具有等于其id的supercedes的孩子来找到它的孩子。我可以从上到下挖掘,直到找到覆盖我所关注的区域的那些,通过寻找具有supercedeson null并且其矩形与我感兴趣的区域重叠的区域(使用PostGIS'&amp;'运算符)。 / p>

答案 3 :(得分:1)

首先,保罗是对的。不幸的是,地球是圆形的,这真的使这些东西变得复杂。

多年前,我为地形测绘服务器创建了一个与此类似的网格。我只记得每个区域左上角编码器的坐标。我还使用UTM坐标而不是lat / long。如果您知道每个区域覆盖3平方公里,并且因为UTM基于米,则可以直接进行范围查询以发现正确的区域。

答案 4 :(得分:0)

你无法用矩形单元格做到这一点,但我刚刚完成了一个R包dggridR,这样可以很容易地使用网格六角形细胞但是,3km的电池要求可能会产生如此多的电池,从而使机器过载。

您可以使用R生成网格:

install.packages('devtools')
install.packages('rgdal')
library(devtools)
devools.install_github('r-barnes/dggridR')
library(dggridR)
library(rgdal)

#Construct a discrete global grid (geodesic) with cells of ~3 km^2
dggs <- dgconstruct(area=100000, metric=FALSE, resround='nearest')

#Get a hexagonal grid for the whole earth based on this dggs
grid <- dgearthgrid(dggs,frame=FALSE)

#Save the grid
writeOGR(grid, "grid_3km_cells.kml", "cells", "KML")

然后,KML文件包含每个单元格的ID和边缘顶点坐标。

网格看起来有点像这样:

Discrete Global Grid

我的软件包基于Kevin Sahr的DGGRID,它可以直接为KML生成相同的网格,但您需要自己弄清楚如何编译它。