蜂巢的艺术与技术价值 - 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
蜂巢的艺术与技术价值 - PostgreSQL PostGIS's hex-grid相关推荐
- 【阿里云技术】PostgreSQL的20+种玩法
作者 德哥,周正中,阿里云高级技术专家,PostgreSQL 中国社区发起人之一,PostgreSQL 象牙塔发起人之一,DBA+社群联合发起人之一,10余项数据库相关专利,曾就职于斯凯网络,负责数据 ...
- 游戏设计的艺术和技术
1998年5月14日,Intel公司在香格里拉饭店组织的发展商会议,由国外一些专家们进行技术讲座.其中交互式软件剧本设计课程,对计算机游戏软件设计的艺术和技术进行讲述. 此次课程的主讲是美国South ...
- 百度增长复苏,市值一夜涨160亿;李彦宏:技术价值再度闪耀,宁可创新冒险也不平庸保守...
李根 乾明 发自 凹非寺 量子位 报道 | 公众号 QbitAI 为什么百度财报受关注? 或许是因为BAT之名,或许是因为AI押注和变革的典型,或许还是上市公司清晰可循的各项数据指标. 当然,作为国 ...
- PostgreSql+PostGIS和uDig的安装
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 总体来说,这两款开源软件均是很好安装的,一般按照提示一步一步 ...
- 【空间数据库】Windows操作系统PostgreSQL+PostGIS环境搭建图文安装教程
PostgreSQL是一种特性非常齐全的自由软件的对象-关系型数据库管理系统(ORDBMS),PostgreSQL支持大部分的SQL标准并且提供了很多其他现代特性,如复杂查询.外键.触发器.视图.事务 ...
- PostgreSQL PostGIS 的5种空间距离排序(knn)算法
摘要: 标签 PostgreSQL , PostGIS , operator , ops , knn 背景 PostgreSQL GiST索引支持排序接口,可以支撑空间.标准.数组.文本向量.文本等类 ...
- 细数数据中台的3个业务价值和5个技术价值
导读:数据中台有什么用?本文带你细数它的业务价值与技术价值. 作者:付登坡 江敏 任寅姿 孙少忆 等 来源:大数据DT(ID:hzdashuju) 01 业务价值:从洞察走向赋能业务创新,形成核心壁垒 ...
- [转]地图的色彩设计——艺术与技术共存
地图作为描述.研究人类生存环境的一种信息载体,融科学.艺术于一体.随着地图的广泛运用和人们对地图审美能力的不断提高,地图美学越来越受到重视,地图色彩设计作为地图美学的重要组成部分,起着美化地图,引导读 ...
- 安装教程:PostgreSQL + PostGIS + pgAdmin
----Picture from <Guide to Maritime Informatics> 安装于2022/3/25,安装于Win10系统,总用时20分钟 安装版本: Postgre ...
最新文章
- postfix文档修正
- urllib的实现---请求响应and请求头处理
- WebSocket与http长连接的区别
- 苹果回应大数据杀熟:罪在开发者,和苹果没关系!
- 转hdmi_LT8619CHDMI转LVDS-HDMI支持高达4Kx2K_30Hz的分辨率
- php-fpm stop,php-fpm 启动,重启,终止操作
- 把路由器配置成DHCP服务器,并确保路由功能。
- Linux驱动系列目录
- 硬盘出现异响应急方案
- 三天两夜,1M图片优化到100kb/肝都熬爆了
- 周记录学习总结<大杂烩>
- Observable与Subject
- html如何实现统计访客功能,JS 实时网站访客(用户)统计
- 计算机毕业设计android的学生考勤请假app(源码+系统+mysql数据库+Lw文档)
- # MPU6050之2阶低通滤波,滤波效果非常好
- TensorFlow 2.X获取Flops和参数量(parameters)的方法(2022年)
- 网络速率方面的知识(Kbps Mbps KB/s Mb/s Kb/s等)
- 如何将项目部署到服务器:从选择服务器到维护应用程序的全流程指南
- 计算机英语听力教程,致用英语听力教程2 《英语听力教程2》文本.doc
- 移知模拟版图就业班,直播教学+项目实战,两个月即可就业!