一篇文章带你玩转PostGIS空间数据库 2

简介: 一篇文章带你玩转PostGIS空间数据库

2.数据投影

2.1 数据投影简介

地球不是平的,也没有简单的方法把它放在一张平面纸地图上(或电脑屏幕上),所以人们想出了各种巧妙的解决方案(投影)。

每种投影方案都有优点和缺点,一些投影保留面积特征;一些投影保留角度特征,如墨卡托投影(Mercator);一些投影试图找到一个很好的中间混合状态,在几个参数上只有很小的失真。所有投影的共同之处在于,它们将(地球)转换为平面笛卡尔坐标系。

使用投影特别简单,PostGIS提供了ST_SRID(geometry)和ST_SetSRID(geometry,SRID)函数。

比较数据

比较坐标需要基于他的SRID(严谨的说应该是空间参考系统),如果不是同一个参考系统,比较没有意义,会返回错误,比如如下实例。

SELECT ST_Equals(
         ST_GeomFromText('POINT(0 0)', 4326),
         ST_GeomFromText('POINT(0 0)', 26918)
         );

转换数据

数据可以在不同SRID的进行转换。

SELECT ST_AsText(
 ST_Transform(
   ST_SetSRID(geom,26918),
 4326)
)
FROM geometries;

2.2 地理坐标

image.png

坐标为"地理(geographics)“形式,即” 纬度(latitude)/经度(longitude)"形式的数据非常常见。地理坐标不是笛卡尔平面坐标。

如果你的数据在地理范围上是紧凑的(包含在州、县或市内),请使用基于笛卡尔坐标的geometry类型。否则,请使用使用基于球体坐标的Geography。而其中的原因,纯粹是数学上的精确度与性能问题,这里不解释。

坐标数据类型准换前面介绍过,这里复习下。

SELECT code, ST_X(geog::geometry) AS longitude FROM airports;

3.几何图形创建函数

目前我们看到的所有函数都可以处理已有的几何图形并返回结果。"几何图形创建函数"以几何图形作为输入并输出新的图形。

3.1 以点代形

组成空间查询时的一个常见需求是将多边形要素替换为要素的点表示。这对于空间连接(spatial join)非常有用,因为在两个多边形图层上使用St_Intersects(geometry, geometry)通常会导致重复计算:位于两个多边形的边界上的多边形将与两侧的多边形都相交,将其替换为点将强制它位于一侧或另一侧,而不是与两侧的多边形都相交


22839e86575449ba9786ec7937e7329a.jpg

ST_Centroid(geometry) —— 返回大约位于输入几何图形的质心上的点。这种简单的计算速度非常快,但有时并不可取,因为返回点不一定在要素本身上。如果输入的几何图形具有凹性(形如字母’C’的几何图形),则返回的质心可能不在图形的内部。

605ec55b4be84073bf33752fa2a73fc5.png

  • ST_PointOnSurface(geometry) —— 返回保证在输入多边形内的点。从计算上讲,它比centroid操作代价要大得多。

3.2 缓冲区

缓冲区操作在GIS工作流中很常见,在PostGIS中也可以进行缓冲区操作。 ST_Buffer(geometry, distance)接受几何图形和缓冲区距离作为参数,并输出一个多边形,这个多边形的边界与输入的几何图形之间的距离与输入的缓冲区距离相等。使用ST_Buffer函数即可。


11a7a300a7624ac3ac23065bae4fd2a4.png

3.3 重叠、相并

另一个经典的GIS操作 - 叠置(overlay)- 通过计算两个重叠多边形的交集来创建新的几何图形。

使用ST_Intersection(geometry A, geometry B)函数。

ST_Union将两个几何图形合并起来

4.几何图形的有效性

多边形不一定有效,如果无效会报错TopologyException错误。下面是一些有效性规则。

多边形的环必须闭合

内环必须位于外环的内部

环不能自相交(它们不能相互接触,也不能交叉)

除了在某个点接触,环不能与其他环接触

前两条是必须的。后面两条则是非必须设置的。您还可以自定义自洽规则。


ST_IsValid(geometry)函数可以用于检测几何图形的有效性。


可以修复无效的图形,坏消息是:没有100%确定的方法来修复无效的几何图形。


在视觉上修复无效几何图形的一个好工具是OpenJump(http://openjump.org),它在Tools->QA->Validate Selected Layers.下包含一个验证程序。



da133506486541298eb96c930fa35bd4.png

现在好消息是:可以使用以下任何一种方法在数据库中修复很大一部分的缺陷:

ST_MakeValid函数

ST_Buffer函数

5.几何图形的相等

在处理几何图形时确定相等可能很困难。PostGIS支持三种不同的函数与操作符,可以用来确定不同级别的相等。


精确相等(ST_OrderingEquals)

精确相等是通过按顺序逐个比较两个几何图形的顶点来确定的,以确保它们在位置上是相同的。如果顶点定义顺序不同,即使是相等也会被认作不相等。


空间相等(ST_Equals)

ST_Equals的函数,可用于测试几何图形的空间相等性或等价性。无论是绘制多边形的方向、定义多边形的起点,还是包含的点的个数的差异在这里都不重要。重要的是多边形包含相同的空间区域,它们就相等。


包围框相等(~=)

为了更快地进行比较,提供了包围框(bounding box)相等运算符 ’ ~= ’ 。这仅在包围框(矩形)上操作,确保几何图形占用相同的二维范围,但不一定占用相同的空间。它不一定精确,但是可以先用它粗筛,再结合其他方法细选。先粗后细。

6.线性参考

线性参考是一种表示要素的方法,这些要素可以通过引用一个基本的线性要素来描述。使用线性参照建模的常见示例包括:

公路资产,这些资产使用公路网络沿线的英里来表示。

道路养护作业,指在一对英里测量之间沿着公路网发生的作业。

水产库存,其中鱼的存在位置被记录为距离上游的一段位置之间。

河流的水文特征,以河流的某一个点到另一个点作为参考。

线性参考到底是个啥?


线性参考是使用沿测量的线状要素的相对位置存储地理位置的方法。


听不懂?


辅助线你总知道吧。其实线性参考就可以理解成一个辅助线,其他位置的计算就算和辅助线的相对位置。比如你以你大哥的身高为参考,计算你比他高了多少,判断你有没有长高(前提是你哥不长个了,误~)


具体可以看如下例子。


e8bcae6dc5404b7382688e84141ac204.png

下图是线性参考在交通网中实际的应用,红色的就是线性参考。


4c261e1421aa438bbe2849802c0f87fc.png

用下列的语法可以创建一个一个线性参考。

SELECT ST_LineLocatePoint('LINESTRING(0 0, 2 2)', 'POINT(1 1)')

7.DE9IM模型

“维数扩展的9交集模型-Dimensionally Extended 9-Intersection Model”(DE9IM)是一个用于建模两个空间对象如何交互的框架。

首先,每个空间对象都具有:

内部(interior)

边界(boundary)

外部(exterior)

即使是线段、点也有内部、外部和边界。

对线段:内部是以端点为界限的线的那一部分;边界是线性要素的端点;外部是平面中除内部和边界外的所有其他部分。


33a58a4361684b399156661821114d90.jpg

对于点来说,更奇怪:内部是点,边界是空集,外部是平面上除点以外的所有其他部分。

使用这些内部、外部和边界的定义,任何一对空间要素之间的关系都可以用一对要素的内部/边界/外部/之间九个可能的交集的维数来表征。


image.png

注意上面有一个dim参数,规则是:对于上例中的多边形,内部的交集是二维区域,因此矩阵的对应部分用"2"填充。边界仅在零维点处相交,因此对应矩阵部分用"0"填充。

再举一个栗子。


7392870d0d554513ac43dd24feee1608.png

关于它们的交集的DE9IM矩阵如下:

83bd4dd8576c425cb68df1198356b173.png

请注意,以上两个要素的边界实际上根本不相交(线的端点与多边形的内部相交,而不是与多边形的边界相交,反之亦然),因此B/B单元用"F"填充。

生成DE9IM模型矩阵的SQL如下。

SELECT ST_Relate(
         'LINESTRING(0 0, 2 0)',
         'POLYGON((1 -1, 1 1, 3 1, 3 -1, 1 -1))'
);

DE9IM矩阵的强大之处不在于生成它们,而在于使用它们作为匹配参数来查找彼此之间具有特定关系的几何图形。


假设我们有一个湖泊(Lakes)和码头(Docks)的数据模型,进一步假设码头必须位于湖泊内部,并且必须在一端接触到湖泊的边界。我们能在数据库中找到所有符合这一规则的码头吗?


用下面sql就可以做到,推导过程就不展开了。

SELECT docks.*
FROM docks JOIN lakes ON ST_Intersects(docks.geom, lakes.geom)
WHERE ST_Relate(docks.geom, lakes.geom, '1FF00F212');

8.索引集群

加速数据访问的一种方法是确保可能在同一结果集中一起被检索的记录位于硬盘上的相近物理位置。这就是所谓的"聚簇(clustering)"。

基于空间索引的聚簇对于将通过空间查询访问的空间数据是有意义的:相似的事物往往具有相似的位置(地理学第一定律)。

写个sql,创建一个索引集群。

-- Cluster the blocks based on their spatial index
CLUSTER nyc_census_blocks USING nyc_census_blocks_geom_idx;

分为两类:

  • 基于R-Tree的聚簇
  • GeoHash上的集群
    b10306fa2ee249dbb1b28fa8e7b9f948.jpg
    可自行深入理解两种算法。


9. 3-D

到目前为止,我们一直在处理2-D几何图形(二维几何图形),只有X和Y坐标。但是PostGIS支持所有几何图形类型额外的维度,对于每个坐标,另外还能支持用于表示高度信息的"Z"维度以及用于添加额外附加信息的"M"维度(通常为时间、道路英里或距离信息)。


有许多函数可用于计算三维对象之间的关系


0df2a8ed6905458d8d6c9ec6c22562d9.png

如果你愿意,甚至可以扩展到N-D。

10.最近领域搜索

KNN是一种基于纯空间索引的近邻搜索方法。这里不展开,你知道有这样的算法就行。

56eae792892a43ab8af21360ff79438e.jpg

11.使用触发器追踪历史编辑操作

生产环境下数据库的一个常见要求是能够跟踪用户编辑数据的历史:数据在两个日期之间是如何变化的,是谁操作的,以及它们哪些内容变化了?一些GIS系统通过在客户端接口中包含更改管理功能来跟踪用户的编辑数据操作,但这增加了客户端编辑工具的复杂性。


使用数据库和数据库的触发器机制,可以对任何表进行编辑历史跟踪,从而让客户端保持对编辑表的简单“直接编辑”(客户端不用负责追踪编辑历史的功能,只负责CRUD)。


12.用于创建空栅格的ST_MakeEmptyRaster函数

ST_MakeEmptyRaster用于创建一个空的没有像元值的栅格(没有波段),各个参数用于定义这个空栅格的元数据:


width、height —— 栅格的列数和行数

upperleftx、upperlefty —— 对应空间坐标系中栅格左上角的坐标

scalex、scaley —— 单个像元的宽度和长度(单位等同于空间参考坐标系的单位)。

skewx、skewy —— 旋转角度,如果栅格数据北方朝上,该值为0。默认值为0。

srid —— 空间参考坐标系,默认被设置为0。

pixelsize —— 单个像元的宽度和长度。当scalex和scaley相等时,就可以直接使用这个参数设置像元大小。


效果如下

d5e3a5dfac814dbfb8a3451038bdc9d3.jpg


相关文章
|
6月前
|
SQL Java 数据库连接
一篇文章彻底理解数据库的各种 JDBC 超时参数 1
一篇文章彻底理解数据库的各种 JDBC 超时参数
|
4月前
|
druid 网络协议 Java
再有人问你数据库连接池的原理,这篇文章甩给他!
在 Spring Boot 项目中,数据库连接池已经成为标配,然而,我曾经遇到过不少连接池异常导致业务错误的事故。很多经验丰富的工程师也可能不小心在这方面出现问题。 在这篇文章中,我们将探讨数据库连接池,深入解析其实现机制,以便更好地理解和规避潜在的风险。
|
1月前
|
存储 NoSQL 关系型数据库
一篇文章带你搞懂非关系型数据库MongoDB
一篇文章带你搞懂非关系型数据库MongoDB
58 0
|
1月前
|
存储 SQL 关系型数据库
【MySQL 数据库】6、一篇文章学习【索引知识】,提高大数据量的查询效率【文末送书】
【MySQL 数据库】6、一篇文章学习【索引知识】,提高大数据量的查询效率【文末送书】
59 0
|
6月前
|
网络协议 Java 关系型数据库
一篇文章彻底理解数据库的各种 JDBC 超时参数 2
一篇文章彻底理解数据库的各种 JDBC 超时参数
|
6月前
|
SQL 存储 关系型数据库
MySQL的第一篇文章——了解数据库、简单的SQL语句
MySQL的第一篇文章——了解数据库、简单的SQL语句
|
6月前
|
Java 数据库连接 数据库
一篇文章学会学会c3p0数据库连接池~
一篇文章学会学会c3p0数据库连接池~
|
8月前
|
存储 数据库 Android开发
Android 使用Room操作SQLite数据库让其变得无比高效和简洁(前一篇文章的完善)
Android 使用Room操作SQLite数据库让其变得无比高效和简洁(前一篇文章的完善)
120 0
|
8月前
|
运维 监控 小程序
【运维知识进阶篇】一篇文章带你搞懂Jumperserver(保姆级教程:安装+用户与用户组+创建资产+授权资产+创建数据库+sudo提权+命令过滤+多因子认证+网域功能+审计台)(四)
【运维知识进阶篇】一篇文章带你搞懂Jumperserver(保姆级教程:安装+用户与用户组+创建资产+授权资产+创建数据库+sudo提权+命令过滤+多因子认证+网域功能+审计台)(四)
434 0
|
8月前
|
运维 数据库
【运维知识进阶篇】一篇文章带你搞懂Jumperserver(保姆级教程:安装+用户与用户组+创建资产+授权资产+创建数据库+sudo提权+命令过滤+多因子认证+网域功能+审计台)(三)
【运维知识进阶篇】一篇文章带你搞懂Jumperserver(保姆级教程:安装+用户与用户组+创建资产+授权资产+创建数据库+sudo提权+命令过滤+多因子认证+网域功能+审计台)(三)
126 0

热门文章

最新文章