标签

PostgreSQL , vector grid , polygon grid , square grid , Hexagon grid , 矢量网格 , 几何网格 , 线段网格 , 多边形网格 , 四边形网格 , 六边形网格 , 蜂巢 , PostGIS , 地图 , 转换


背景

人们为了更好的描述一个东西,有一种将大化小的思路,比如时钟被分为了12个区域,每个区域表示一个小时,然后每个小的区域又被划分为更小的区域表示分钟。

在GIS系统中,也有类似的思想,比如将地图划分成网格。通过编码来简化地理位置的判断(比如相交,包含,距离计算等),但是请注意使用网格带来的问题,比如精度的问题,网格的大小决定了精度,又比如相对坐标的问题,可能无法描述清楚边界的归属。

PS:

1. 在PostGIS中虽然也支持网格对象的描述方式,但是并不是使用这种方法来进行几何运算(比如相交,包含,距离计算等),所以不存在类似的精度问题,个人建议没有强需求的话,不必做这样的网格转换。

PostgreSQL GIS索引的原理请参考

《从难缠的模糊查询聊开 - PostgreSQL独门绝招之一 GIN , GiST , SP-GiST , RUM 索引原理与技术背景》

2. 如果是多种精度地图的切换(比如多个图层,每个图层代表一种地图精度),建议使用辐射的方式逐渐展开更精细的图层,以点为中心,逐渐辐射。(很多专业的地图软件是这样做的)

回到主题,还记得最强大脑的蜂巢迷宫吗?

还有勤劳的蜜蜂兄弟

我们接下来要做的就是如何将几何图形转换为网格对象。

回忆一下六边形的几何特性

首先要了解一下六边形的几何特性,提供转换的计算基础。

六边形可以切分为6个等边三角形

所以它的边长关系如下

面积计算

更多细节详见

https://hexnet.org/content/hexagonal-geometry

将几何图形(sharp)转换为六边形网格

比如要将澳大利亚的版图,转换为六边形网格,

有两种方法,一种使用geotools的JAVA 类(在程序中转换),另一种是使用PostGIS插件的UDF(在数据库中转换)。

当然,如果PostgreSQL安装了pljava插件的话,那么也可以在PostgreSQL中调用geotools提供的java类进行转换。

下面是例子

1 geotools Vector grids class

http://docs.geotools.org/latest/userguide/extension/grid.html

使用geotools vector grids class生成网格,返回 SimpleFeatureSource 类型。

geotools Vector grids class支持将几何图形转换为 polygon网格 或者 line网格 。

1 Polygon grids

举几个例子

1. 将澳大利亚地图转换为10度边长的正方形网格

输入澳大利亚的经纬度范围,转换

    ReferencedEnvelope gridBounds = new ReferencedEnvelope(  110.0, 150.0, -45.0, -5.0, DefaultGeographicCRS.WGS84);  SimpleFeatureSource grid = Grids.createSquareGrid(gridBounds, 10.0);

2. 将澳大利亚地图转换为最大20度边长的扇形网格

    ReferencedEnvelope gridBounds = new ReferencedEnvelope(  110, 160, -45, -8, DefaultGeographicCRS.WGS84);  double squareWidth = 20.0;  // max distance between vertices  double vertexSpacing = squareWidth / 20;  SimpleFeatureSource grid = Grids.createSquareGrid(gridBounds, squareWidth, vertexSpacing);

3. 创建纵横宽100,变长为5.0的六边形网格

    ReferencedEnvelope gridBounds = new ReferencedEnvelope(0, 100, 0, 100, null);  // length of each hexagon edge  double sideLen = 5.0;  SimpleFeatureSource grid = Grids.createHexagonalGrid(gridBounds, sideLen);

4. 导入图形、将澳大利亚地图转换为边长1度的六边形网格

自定义图形边界判断的类

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import java.io.IOException;
import java.util.Map;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;  public class IntersectionBuilder extends GridFeatureBuilder {  final FilterFactory2 ff2 = CommonFactoryFinder.getFilterFactory2();  final GeometryFactory gf = JTSFactoryFinder.getGeometryFactory();  final SimpleFeatureSource source;  int id = 0;  public IntersectionBuilder(SimpleFeatureType type, SimpleFeatureSource source) {  super(type);  this.source = source;  }  public void setAttributes(GridElement el, Map<String, Object> attributes) {  attributes.put("id", ++id);  }  @Override  public boolean getCreateFeature(GridElement el) {  Coordinate c = ((PolygonElement) el).getCenter();  Geometry p = gf.createPoint(c);  Filter filter = ff2.intersects(ff2.property("the_geom"), ff2.literal(p));  boolean result = false;  try {  result = !source.getFeatures(filter).isEmpty();  } catch (IOException ex) {  throw new IllegalStateException(ex);  }  return result;  }
}

导入地图,在createHexagonalGrid中使用边界判断的类,生成六边形网格

    // Load the outline of Australia from a shapefile  URL url = getClass().getResource("oz.shp");  FileDataStore dataStore = FileDataStoreFinder.getDataStore(url);  SimpleFeatureSource ozMapSource = dataStore.getFeatureSource();  // Set the grid size (1 degree) and create a bounding envelope  // that is neatly aligned with the grid size  double sideLen = 1.0;  ReferencedEnvelope gridBounds =  Envelopes.expandToInclude(ozMapSource.getBounds(), sideLen);  // Create a feature type  SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();  tb.setName("grid");  tb.add(GridFeatureBuilder.DEFAULT_GEOMETRY_ATTRIBUTE_NAME,  Polygon.class, gridBounds.getCoordinateReferenceSystem());  tb.add("id", Integer.class);  SimpleFeatureType TYPE = tb.buildFeatureType();  // Build the grid the custom feature builder class  GridFeatureBuilder builder = new IntersectionBuilder(TYPE, ozMapSource);  SimpleFeatureSource grid = Grids.createHexagonalGrid(gridBounds, sideLen, -1, builder);

5. 生成的六边形网格的摆放参数,横(flat)的还是竖(angled)的?

默认为flat网格,如果要生成angled网格,如下

    ReferencedEnvelope gridBounds = new ReferencedEnvelope(0, 100, 0, 100, null);  double sideLen = 5.0;  GridFeatureBuilder builder = new DefaultGridFeatureBuilder();  SimpleFeatureSource grid = Hexagons.createGrid(  gridBounds, sideLen, HexagonOrientation.ANGLED, builder);

2 line grids

转换为line 网格

例子

    ReferencedEnvelope gridBounds = new ReferencedEnvelope(  110.0, 150.0, -45.0, -5.0, DefaultGeographicCRS.WGS84);  /*  * Line definitions:   * major lines at 10 degree spacing are indicated by level = 2  * minor lines at 2 degree spacing are indicated by level = 1  * (level values are arbitrary; only rank order matters)  */  List<OrthoLineDef> lineDefs = Arrays.asList(  // vertical (longitude) lines  new OrthoLineDef(LineOrientation.VERTICAL, 2, 10.0),  new OrthoLineDef(LineOrientation.VERTICAL, 1, 2.0),  // horizontal (latitude) lines  new OrthoLineDef(LineOrientation.HORIZONTAL, 2, 10.0),  new OrthoLineDef(LineOrientation.HORIZONTAL, 1, 2.0));  // Specify vertex spacing to get "densified" polygons  double vertexSpacing = 0.1;  SimpleFeatureSource grid = Lines.createOrthoLines(gridBounds, lineDefs, vertexSpacing);

2 PostGIS UDF hex-grid

https://github.com/minus34/postgis-scripts/tree/master/hex-grid

PostGIS不需要多介绍了,几十年的老牌GIS插件,在军方、科研、民用等各个领域有着非常广泛对应用。

如果你使用了PostGIS插件的话,在里面存储了不管是geometry, polygon还是其他的地图类型,都可以转换为六边形网格。

转换时使用这些定义好的UDF即可。

UDF使用方法

See the 2 sample usage scripts to see how to create a national hex grid, using the function.

UDF输入参数

Parameter Description
areakm2 Area of each hexagon in square km. Note: output hexagon sizes can be off slightly due to coordinate rounding in the calcs.
xmin,ymin Minimum coordinates of the grid extents (i.e. bottom, left).
xmax,ymax Maximum coordinates of the grid extents (i.e. top, right).
inputsrid The coordinate system (SRID) of the min/max coordinates.
workingsrid The SRID used to process the hexagons:
- SRID must be a projected coord sys (i.e. in metres) as the calcs require ints. Degrees are out.
- Should be an equal area SRID - i.e. Albers or Lambert Azimuthal (e.g. Australia = 3577, US = 2163).
- Using a Mercator projection will NOT return hexagons of equal area (don't try it in Greenland).
ouputsrid The SRID of the output hexagons.

输出

A set of hexagonal polygons as PostGIS geometries

转换基础,参考如下

https://trac.osgeo.org/postgis/wiki/UsersWikiGenerateHexagonalGrid

小结

1. 在PostGIS中虽然也支持网格对象的描述方式,但是并不是使用网格编码的方法来进行几何运算(比如相交,包含,距离计算等),而是类似矢量的计算方法,因此不存在网格的精度问题,个人建议没有强需求的话,不必将几何图形转换为网格。

PostgreSQL GIS索引的原理请参考

《从难缠的模糊查询聊开 - PostgreSQL独门绝招之一 GIN , GiST , SP-GiST , RUM 索引原理与技术背景》

2. 如果是多种精度地图的切换(比如多个图层,每个图层代表一种地图精度),建议使用辐射的方式逐渐展开更精细的图层,以点为中心,逐渐辐射。(很多专业的地图软件是这样做的)

3. 如果要将图形转换为网格,可以使用geotools提供的java class来转换,也可以使用PostGIS的UDF来转换,当然PostgreSQL如果安装了pljava过程语言的话,可以直接在数据库中调用geotools提供的java class对图形进行转换。

4. pljava

https://tada.github.io/pljava/

参考

1. geotools vector grid包

http://docs.geotools.org/latest/userguide/extension/grid.html

2. PostGIS 生成六边形网格的UDF

https://github.com/minus34/postgis-scripts/tree/master/hex-grid

3. PostGIS 生成六边形网格的算法基础

https://trac.osgeo.org/postgis/wiki/UsersWikiGenerateHexagonalGrid

4. 六边形几何公式

https://hexnet.org/content/hexagonal-geometry

蜂巢的艺术与技术价值 - PostgreSQL PostGIS's hex-grid相关推荐

  1. 【阿里云技术】PostgreSQL的20+种玩法

    作者 德哥,周正中,阿里云高级技术专家,PostgreSQL 中国社区发起人之一,PostgreSQL 象牙塔发起人之一,DBA+社群联合发起人之一,10余项数据库相关专利,曾就职于斯凯网络,负责数据 ...

  2. 游戏设计的艺术和技术

    1998年5月14日,Intel公司在香格里拉饭店组织的发展商会议,由国外一些专家们进行技术讲座.其中交互式软件剧本设计课程,对计算机游戏软件设计的艺术和技术进行讲述. 此次课程的主讲是美国South ...

  3. 百度增长复苏,市值一夜涨160亿;李彦宏:技术价值再度闪耀,宁可创新冒险也不平庸保守...

    李根 乾明 发自 凹非寺  量子位 报道 | 公众号 QbitAI 为什么百度财报受关注? 或许是因为BAT之名,或许是因为AI押注和变革的典型,或许还是上市公司清晰可循的各项数据指标. 当然,作为国 ...

  4. PostgreSql+PostGIS和uDig的安装

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 总体来说,这两款开源软件均是很好安装的,一般按照提示一步一步 ...

  5. 【空间数据库】Windows操作系统PostgreSQL+PostGIS环境搭建图文安装教程

    PostgreSQL是一种特性非常齐全的自由软件的对象-关系型数据库管理系统(ORDBMS),PostgreSQL支持大部分的SQL标准并且提供了很多其他现代特性,如复杂查询.外键.触发器.视图.事务 ...

  6. PostgreSQL PostGIS 的5种空间距离排序(knn)算法

    摘要: 标签 PostgreSQL , PostGIS , operator , ops , knn 背景 PostgreSQL GiST索引支持排序接口,可以支撑空间.标准.数组.文本向量.文本等类 ...

  7. 细数数据中台的3个业务价值和5个技术价值

    导读:数据中台有什么用?本文带你细数它的业务价值与技术价值. 作者:付登坡 江敏 任寅姿 孙少忆 等 来源:大数据DT(ID:hzdashuju) 01 业务价值:从洞察走向赋能业务创新,形成核心壁垒 ...

  8. [转]地图的色彩设计——艺术与技术共存

    地图作为描述.研究人类生存环境的一种信息载体,融科学.艺术于一体.随着地图的广泛运用和人们对地图审美能力的不断提高,地图美学越来越受到重视,地图色彩设计作为地图美学的重要组成部分,起着美化地图,引导读 ...

  9. 安装教程:PostgreSQL + PostGIS + pgAdmin

    ----Picture from <Guide to Maritime Informatics> 安装于2022/3/25,安装于Win10系统,总用时20分钟 安装版本: Postgre ...

最新文章

  1. postfix文档修正
  2. urllib的实现---请求响应and请求头处理
  3. WebSocket与http长连接的区别
  4. 苹果回应大数据杀熟:罪在开发者,和苹果没关系!
  5. 转hdmi_LT8619CHDMI转LVDS-HDMI支持高达4Kx2K_30Hz的分辨率
  6. php-fpm stop,php-fpm 启动,重启,终止操作
  7. 把路由器配置成DHCP服务器,并确保路由功能。
  8. Linux驱动系列目录
  9. 硬盘出现异响应急方案
  10. 三天两夜,1M图片优化到100kb/肝都熬爆了
  11. 周记录学习总结<大杂烩>
  12. Observable与Subject
  13. html如何实现统计访客功能,JS 实时网站访客(用户)统计
  14. 计算机毕业设计android的学生考勤请假app(源码+系统+mysql数据库+Lw文档)
  15. # MPU6050之2阶低通滤波,滤波效果非常好
  16. TensorFlow 2.X获取Flops和参数量(parameters)的方法(2022年)
  17. 网络速率方面的知识(Kbps Mbps KB/s Mb/s Kb/s等)
  18. 如何将项目部署到服务器:从选择服务器到维护应用程序的全流程指南
  19. 计算机英语听力教程,致用英语听力教程2 《英语听力教程2》文本.doc
  20. 移知模拟版图就业班,直播教学+项目实战,两个月即可就业!

热门文章

  1. Modular Arithmetic
  2. html双击变成可编辑状态,JS实现双击编辑可修改状态的方法
  3. Android 内外边距
  4. 计算机科学与技术专业毕业答辨问题,计算机科学与技术论文答辩问题(问题及技巧介绍)...
  5. 用Python制作好玩的小游戏
  6. DB2数据库认证系列教程——IBM DB2认证考前必备
  7. github项目的JAVA项目Ratel,基于Netty实现
  8. 可用的PHP在线云加密系统源码
  9. Java实现 洛谷 P1064 金明的预算方案
  10. E-Competitive Seagulls