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

标签

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

时间: 2025-01-20 21:36:10

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

如何建立GIS测试环境 - 将openstreetmap的样本数据导入PostgreSQL PostGIS库

如何建立GIS测试环境 - 将openstreetmap的样本数据导入PostgreSQL PostGIS库 作者 digoal 日期 2016-09-06 标签 PostgreSQL , openstreetmap , PostGIS , osm2pgsql , pbf , osm 背景 PostgreSQL在GIS领域的用户非常多,这得益于PostgreSQL的开放性,PostGIS即是使用PostgreSQL开放的索引访问.数据类型.函数,操作符等接口打造的一款功能非常强大的GIS数据管理

PostgreSql+PostGIS和uDig的安装

文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 总体来说,这两款开源软件均是很好安装的,一般按照提示一步一步点击next等,就可以装好.当然,也有需要注意的地方.下面我大致介绍下两款软件的安装流程. 2.PostgreSql+PostGIS的安装 2.1下载地址 在官网http://www.postgresql.org/download/处可以下载到最新的PG版本. 2.2PostgreSql的安装流程

PostgreSQL + PostGIS + SFCGAL 优雅的处理3D数据

标签 PostgreSQL , SFCGAL , 3D 背景 PostGIS 整合 SFCGAL,优雅的处理3D空间数据. 例子 PDF: 3D and exact geometries for PostGIS , FOSDEM PGDay http://www.sfcgal.org/ https://www.tuicool.com/articles/jAjIBn https://wiki.postgresql.org/images/3/36/Postgis_3d_pgday2013_hm.pd

九鼎赵忠义:三分投资七分服务 艺术与技术融合

"投资是一种由智力控制资本的工作,同时也是一个'把企业当作商业'.体现'技术+艺术'的过程,所以它是我喜欢并将为之奋斗的事业." 而今的PE界,有关"九鼎凶猛"的神话正在广为相传.这家在2007年才成立的有限合伙制企业,倚仗着"PE工厂化"的商业模式,近200人的企业,在过去一年中组建了30多个办事机构,于各自的辖区内地毯式搜寻符合九鼎投资标准的目标企业. 根据其官方网站,九鼎投资共投资了81家公司,集中在五大领域,包括16个消费项目.16个医药

浅谈网络推广是艺术是技术而不是算术

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 艺术是什么?艺术就是像世人展示美的效果.技术是什么?技术就是通过一定的方法与技巧来达到某种目的.那么算术又是什么,算术就是1+1=2,永远不可能等于三的真理. 做推广也是一样,你不要想到去做算术,即使你今天发了100个QQ群邮件,在200个论坛发了300个帖子,他都不会给你带来400人的流量,在推广中算术是一种不可取的方法,那么艺术呢? 艺术

无人驾驶背后的技术 - PostGIS点云(pointcloud)应用

标签 PostgreSQL , PostGIS , box , grid , pointcloud , pgpointcloud , point聚合 , KNN , 自动驾驶 , 自动配送 , 无人驾驶 , 机器人配送 , 物流 背景 科幻电影的场景随着技术的发展,正在一步步的从荧幕变成现实.从军用到民用,比如汽车厂商.科技公司在尝试的无人驾驶,无人飞行器. 无人驾驶应用非常广泛,比如快递行业,时机成熟以后,将来可能快递员这个职业也会逐渐从社会上消失(解放快递员的双手和创造力,让更多的人参与到科

PostgreSQL 助力企业打开时空之门 - 阿里云(RDS、HybridDB) for PostgreSQL最佳实践

标签 PostgreSQL , Greenplum , 时间 , 空间 , 对象 , 多维透视 , 多维分析 背景 时空数据无处不在,未来空间数据的占比会越来越高,在TP与AP场景的需求也会越来越旺盛. 选址.网格运营 空间数据自动聚集分析:时间+多边形圈人:驻留时间分析:舆情分析:... 室内定位 3D坐标:相对坐标系:+以上:运营活动效果分析报表: 科研 太空探索.测绘.气象.地震预测.溯源 无人驾驶 点云:动态路径规划: 空间调度(菜鸟.饿了么.滴滴.高德.快递...) 实时位置更新:多边

数据库选型十八摸 之 PostgreSQL - 致 架构师、开发者

标签 PostgreSQL , 数据库特性 , 数据库应用场景分析 , 数据库选型 背景 数据库对于一家企业来说,相比其他基础组件占据比较核心的位置. 有很多企业由于最初数据库选型问题,导致一错再错,甚至还有为此付出沉痛代价的. 数据库的选型一定要慎重,但是这么多数据库,该如何选择呢? 我前段时间写过一篇关于数据库选型的文章,可以参考如下 <数据库选型思考> 另外,PostgreSQL这个数据库这些年的发展非常的迅猛,虽然国内还跟不上国外的节奏,但是相信国人逐渐会融合进去. 所以我专门针对Po

音视图(泛内容)网站透视分析 DB设计 - 阿里云(RDS、HybridDB) for PostgreSQL最佳实践

标签 PostgreSQL , 用户透视 , 设备透视 , 圈人 , 标签 , 视频网站 , 优酷 , 土豆 , 喜马拉雅 背景 日常生活中,人们使用最多的除了社交类网站.购物网站,估计就是音频.视频.图文信息类内容网站了. 视频网站,已经渗透到各种终端,除了喜闻乐见的手机,还包括移动终端.电脑.盒子.电视.投影仪等.有设备属性.会员属性.渠道属性等. 内容运营是非常重要的环节,而透视则是运营的重要武器. 业务需求 1.生成设备.会员画像 ID.各个维度的标签.其中包括一些多值列标签(例如最近7