3

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

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

其次,一旦我创建了那个网格表,我需要设计一个 fxn,它需要一个 long/lat 对,然后确定它在哪个逻辑“区域”。我不知道该怎么做。

任何帮助,将不胜感激。

谢谢。

4

5 回答 5

3

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

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

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

如果我们绕赤道走一圈,每3公里做一个标记,大约会有(2 * pi * R) / 3 = 13343.3912。“关于”,因为您决定如何处理额外的 0.3912。

从 (0, 0),我们向北步行 3 公里到 (lat, long) (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 公里,那么顶部应该短一点,形成梯形带。

有很多方法可以做出接近理想方形网格的折衷方案。 这篇关于保留度量属性的地图投影的维基百科文章,链接到几十个这样的策略。

您的应用程序的细节可能会让您大大简化事情,特别是如果您真的不需要绘制整个地球的地图。

于 2009-11-01T21:09:09.557 回答
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

于 2009-11-01T20:13:02.867 回答
1

你确实意识到,因为地球是一个球体,“3 平方公里”在两极附近的度数与赤道附近的度数不同,对吧?在地图的顶部和底部,您的方格实际上将代表世界的饼状部分,对吗?

我对我的数据库做了类似的事情——我把它分成了四个单元格。所以我所做的就是把地球分成四等分(-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 不为空。我可以通过查找具有等于其 id 的替代项来找到它的孩子。我可以从上到下向下挖掘,直到找到覆盖我关注的区域的区域,方法是查找具有 supercedeson null 且其矩形与我感兴趣的区域重叠的区域(使用 PostGIS '&' 运算符)。

于 2009-11-01T20:11:21.640 回答
1

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

多年前,我为地形映射服务器创建了一个与此类似的网格。我刚刚记录了每个区域左上角编码器的坐标。我还使用了 UTM 坐标而不是纬度/经度。如果您知道每个区域覆盖 3 平方公里,并且由于 UTM 是基于米的,那么直接进行范围查询以发现正确的区域。

于 2009-11-01T20:13:06.580 回答
0

你不可能用矩形单元格来做到这一点,但我刚刚完成了一个 R 包dggridR,这将使使用六边形单元格的网格很容易做到这一点。但是,3 公里的单元要求可能会产生如此多的单元,从而使您的机器过载。

您可以使用 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 和边顶点坐标。

网格看起来有点像这样:

离散全球网格

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

于 2016-07-12T22:48:01.823 回答