分享人:图贲
正文:
本篇内容将从3个部分为读者介绍Ganos时空云计算,希望可以让大家对Ganos有更深入的了解,并可以将这些特性应用到项目中,达到降本提效的目的。
l 空间/时空数据库的概念
l 应用场景
l 四个模型的使用案例
一、 空间/时空数据库的概念
1)空间/数据库
为什么要有空间数据库?在原来这种关系型数据库的基础上,要管理地理空间的数据,没有直接的这种类型以及它提供不了空间关系、空间参考和空间检索这些一系列的特性。所以空间数据库基本上就是表示它拥有独特的空间模型,空间类型以及它包含这种空间关系、空间拓补,还有它的空间参考。空间参考主要是指坐标系、投影以及它能够进行空间检索即空间索引。最重要的是它提供一系列的空间分析和操作的算子。
随着动态监控轨迹以及时空遥感的数据越来越多,把时间维度即空间数据加上时间维度这种需求也慢慢地越来越多,现在产生了一个概念叫时空数据库,相当于是空间数据库的一个升级。
目前常见的这种关系型空间时空数据库主要有postGIS以及Ganos-我们阿里云推出的时空数据库,还有就是传统的Oracle Special。
2)空间模型
空间模型主要有哪些呢?主要有平面几何模型、球面几何模型、栅格模型、时空轨迹模型、点云模型以及拓扑网络模型,这些是现在市面上比较能常见的空间模型。
二、应用场景
时空数据库的应用是非常广泛的。在传统的测绘遥感,还有互联网出行、运动社交、城市大脑、智慧物流以及LBS、车联网等等这些场景下,都能用到时空数据库。
三、 四个模型的使用案例
1)几何模型使用案例
几何模型主要包括2d、3d、4d这些对象,比如点线面体、不规则三角网,它具体的代码类型就是point、LineString、Polygon、MultiPolygon以及它的多维多对象的存储。
l 创建几何扩展
在Ganos的层面扩展语句,就是创建几何扩展、创建拓扑扩展以及创建sfcgal插件扩展。然后对应的是PostGIS里面的创建扩展。
l 几何数据管理
那几何数据怎么管理呢?
这里简单列举了一下:
首先创建一张表里面带geometry字段,那它就是一张几何表,就可以存储几何数据。它的定义比较简单,就是geometry后面带一个数据类型,比如线以及它的空间参考。还有一种方式,就是先创建一张普通的关系表,然后再增加一个几何字段。
然后数据入库。数据入库有入库工具,就是pg底下带有一个shp2pgsql。第二种就是自己写SQL通过GeomFrom text这种方式能够直接写入求数据。
l 空间测量与分析
下面介绍一下空间测量与分析。
空间测量如计算这种道路的长度以及湖面的面积。空间分析如叠加分析就是overlap两个多边形,做一个叠加分析,就是右面的这个示意图,蓝色的与绿色的叠加之后的结果就是这个橙色的多边形。
l 空间索引
空间索引在PostGIS里面以及Ganos里面是依赖于pg的Gist框架。这张图是Gist框架的结构图以及它的内部关系。
首先它有索引项,它基本上就是表示你索引的是一个什么东西?在空间里它索引的是boxdf,也就是说一个媒体、一个几何对象的一个外包框,二维的是box2df,三维的话是gitx。三维、四维,五维,甚至很多维,它是一个可扩展的。
然后它的GIST包括几大框架函数,即实现了这几大框架函数之后, GIST索引就实现了:
l Compress就是一个Germotry进来之后,它会把它压缩成一个框,然后作为它的索引项。
l Decompress就是取的时候要把它给解压出来。
l Penaity就是计算你的那个索引生成树的代价。
l Picksplit是索引数的拆分。当你索引从root节点开始,它一步步拆分。
l Union就是索引的合并。
l Same就是两个索引项的比较。
l 最关键的就是Conststent。索引它定义了咱们常见的空间关系操作的方式方法,包括图中右边蓝色的就是每一个索引的操作符,所对应的一个操作算子。比如“<<”表示判断是在左边,然后“&&”表示它是一个空间覆盖。
l 框架函数里面有两个函数是打虚线的,其中distance主要是算它的knn距离,这两个函数打虚线表示它可以实现,也可以不实现,它不是必须的。
l 空间搜索
有了空间索引之后,我们就可以来做空间搜索。空间搜索是一个简单的计算,就是一张表里面计算在它周边5km范围内的所有的地物,按照它的距离来排序。
这种应用主要是在外卖或者是出行这种搜索上。
它的一个SQL我这里解读一下,首先最外层是一个st contains,就是一个包含。第一个参数是Geometry,它通过你的一个点,实时构构造出来make point,设置它的空间参考4326,它是一个球面坐标,所以是一个joyblaff对象。通过st buffer做一个转换,转成个平面坐标之后,再套用到st contains这个函数里面,5000就是5000米,它必须是一个平面坐标,就是你要计算这个半径距离为5km的这个范围内包含这个点的这些地物。然后order by是跟这个点距离最近的一个排序,post<->是一个计算距离的操作符。
2)栅格模型使用案例
栅格模型比较复杂,在空间数据库里面也很重要,它主要是管理大规模遥感影像以及我们的气象、灾害以及高层Dem这些这种栅格数据,包括普通的照片。
l 操作
这里通过之前写的一个云栖上的文章来直接解释操作。这是在Ganos里面利用影像来实现洪涝灾害承灾体损失综合评估的一个案例。
我们看一下数据的准备。
要准备洪水淹没水深分布的数据、土地利用类型分布的数据、土地利用价值分布数据,还有土地利用淹没水深损失率对照表。
然后数据计算它有两个公式:
数据输出就是输出洪涝灾害损失率分布,就是哪里损失率比较高。洪涝灾害损失
价值分布就是产生损失的价值是多少?
1、你把影像栅格数据拿进来之后,我们通常要先做一下空间参考投影。
投影就是transform,意思就是因为提供的影像不一定是你当前分析的那个空间参考,所以说要先把它转为当前你作为数据分析的空间参考。这个示意图就是怎么来做影像转换的,比如每个格子就是一个影像的栅格向元,向元里面有它的向元池。这是一个方方正正的栅格,它转换之后可能就是斜的,就传成一个斜的,它旁边产生了很多空白的向元。这些空白的向元就是一个no data无效值。
2、做完投影之后我们再做一下空间分辨率。
它的分辨率与它的价值模型不一定是匹配的,所以要将分辨率重新设置到需要的分辨率。分辨率就是比如说5000×5000向元,它代表地面实际的范围是多少?这个时候它有一个比例,比如1:50000,相当于原来我们的比例尺。它每一个向元代表实际的距离大小就是它的分辨率,比如我们的5m分辨率,就是说我一个向元里面其实代表的实际的距离是5m。分辨率的重设置就相当于这个示意图,在你的分辨率比较高的情况下,要抽的比较稀,从5×5抽成3×3,然后抽的过程中会有一个重采样,也就是说抽完之后这个向元它的实际的值应该是多少?
3、分辨率重设置之后,要重分类。
因为有个ST_Reclassify,影像的向元值比较杂,这个时候我们要把它归为两类或者三类,就是归为简单的几类来做一个价值的计算,比如说小于10的我们就设置为零;大于10的,我们就统一归为10。这样做一个重分类,得到了我们右边这张栅格图。
4、接下来就做一个代数运算。代数运算是什么意思呢?
每个向元里面它的值通过一定的代数函数,计算之后得到一个新的值,比如我们的这个代数是x=x+10,这个时候第一个向元值是3,通过代数运算之后得到的向元值就是13。
l 实战过程
数据拿到之后是一幅影像,它是外面的一个带路径的tf文件,这个时候我们怎么入库,怎么做投影变换?
首先创建一个数据表,creat table这个数据表里面带一个raster的类型。将这个影像数据入库,直接通过SQL的方式INSTER INTO导入到这张表,然后value里面第一个是它的名称,第二个是这幅影像。这里面连续做了好几个动作,首先是最里层的CreateRast,这个就是先把影像读进来,读进来之后嵌套一个transform做一个重投影,然后在外面再做一个Resize,就是一个分辨率的重置。
底下这里面只是导了不同的数据。
只是它的数据类型不一样,数据体现的维度不一样,一个是土地利用的类型,一个是洪水深度的类型,一个是土地价值的类型,
然后这三幅影像我们入库之后,就可以来计算它的损失力。比如说以type,type是一种类型,21就表示林地。
看一下林地的洪水淹没水深与土地利用赋值结果的一个相乘值。
经过一系列的计算之后,我们直接得到了它的一个评估,一个损失率的评估效果图。以及它的承灾体损失值计算。
上面的这些步骤可以压缩到一个SQL把它搞定。虽然比较复杂,但是它可以减少开发的工作量。
3)轨迹模型使用案例
轨迹也就是我们通常说的移动对象,是一种带有位置、时间、属性(包括速度、方向、角度,温度等),一个移动对象里面同时包含这么多维度。轨迹里面还可以包含它的时空事件,比如一个汽车在高速路上的行驶轨迹,它其中有一个加油事件,这个时候也可以把这个事件定义下来。
轨迹模型提供轨迹的存储以及轨迹的时空查询、分析计算,比如穿越分析,OD分析,相似度计算等等。
接下来通过几个具体的例子看一下轨迹是怎么管理、查询分做分析的。
l 轨迹基本概念
首先介绍一下轨迹的概念。轨迹首先得有轨迹点,轨迹点右边这张图就是画出了轨迹的几个维度。首先一个时间最顶上是一个时间维度,也就是说它一定是朝着时间往前走的。然后空间维度就朝着空间也是要有变化的,空间位置要有变化。还有属性维度,你可以指定多个属性,比如刚才说的速度方向;事件维度,事件就是比如路中间的一个加油事件,抛锚事件,这些都可以记录下来。
一系列的轨迹点以及轨迹事件就构成了轨迹对象。
l 轨迹构造
我们看一下轨迹的构造,我们怎么通过SQL来构造一个轨迹。
首先在数据库里面,这里轨迹以Ganos空间数据库为例,创建扩展,它提供了makeTrajectory轨迹构造的这么一个函数。它可以传入leaftype节点的类型以及几何对象,也就是一系列的点以及时间序列,时间起始值和终止值,也可以提供一个时间的数组,也就是一个时间序列。最后以cstring attrs_jsonff的方式传进来的是它的属性以及它的事件。
我们看一下示例:
STPOINT就表示这个轨迹是一个轨迹点类型的轨迹,轨迹它还分不同的类型,有轨迹点的轨迹,也有面状的轨迹。面状的轨迹如海面漏油了,这个油所产生的一片油面随着时间不停的往前飘,这个轨迹它就是一个以面为单位往前移动的轨迹。
红色的就表示这个轨迹的几个轨迹的点,每个点的坐标。
蓝色的就是轨迹的时间。时间序列这里是指定的一个数组,就是时间3个值,还可以是刚才说到的起始时间,终止时间,这样会做一个超值。
绿色的就是它的属性:首先看第一个参数leafcount,就表示轨迹有多少个属性,有多有多少个点?轨迹点有多少个?这里是3个,然后它的属性有什么?最后的events就是事件,事件通过定义事件的类型比如1代表什么类型,2代表什么类型?然后事件发生的时间是什么?这样就构成了一个轨迹对象。
l 轨迹管理与查询
有了轨迹对象之后我们怎么管理以及查询?
这里以一个航班轨迹为例,创建一个航班轨迹表。可以看到这里面橙色的轨迹字段就是我们原生的轨迹类型字段,其他的都是普通的属性,比如航班信息,航班时间,起飞时间,到达时间这些这些属性。
有了这个轨迹表之后,我们通过刚才的轨迹构造就可以往里写轨迹。写轨迹这个数据,通常轨迹提供的数据都是文本性质的,每一行是一条轨迹,这个时候写个小程序就可以把这个一行的记录对应到我们的轨迹对象。
有了这个轨迹数据之后,就可以做时空查询。这时候做时空查询就是时间和空间的一个交叉交错查询,非常简单。这里面有一个st intersects,这个函数直接接受轨迹类型以及两个时间的参数,以及最后一个空间范围的参数,也就是说查这张表里面轨迹字段中所有开始时间,结束时间以及在这个空间范围内的所有轨迹。
l 轨迹压缩
我们再来看一下轨迹的压缩。
通常轨迹比如航班数据,航班轨迹以及轮船轨迹或者是车辆的轨迹,它发射的采集密度是比较密集的,所以产生的数据量是非常大的。这个时候要做分析显示必然就会有很大的压力。为了加快这种查询分析以及显示的速度,所以要做轨迹压缩。轨迹的压缩根据它的三大特征来做,位置、速度和方向。
我们压缩的目的很简单,就是要保留重要的轨迹点,同时删除信息多余或者不重要的轨迹点,就是留下重要的有很多特征信息的轨迹点,其他的无关紧要的我们不需要的就把它删掉,或者把它过滤掉。
哪些是重要的轨迹点?这里也有个定义,比如说起始点、终止点,还有拐弯点以及中间的折返点,以及在一个地方徘徊不动的点,一种突然速度改变的点如速度、加速度或者是减速很大的点等等,还有一些其他的用重要特征来定义这个是否是重要回击点。
我们看一下轨迹的压缩:
最上面这张图就是它的一个原始的轨迹,可以看到非常密集,堆在一起看也看不清,作用也有限。
目前像Posgis也好,Ganos也好,压缩的算法主要有simplify,simplify它只考虑空间位置上的一个压缩,它就是一个道格拉斯普克算法的压缩,然后把一些认为空间上不太重要的,不能够显示出它的一个整体趋势的点删掉,但这个压缩之后的效果是比较差的,这个是它压缩后的一个效果。
在Ganos里面它有一个新的压缩算法叫做ST_COMPRESS,好处是既考虑了空间位置,也考虑了它的方向,比如说折返的这些点是要保留的,以及方向变化比较大的转弯的这种点。还有就是它的速度变化,很多时候可能这个轨迹它是一条近似直线,但是它速度在变,这个时候你也不能把它删掉,所以说这样压完之后它的效果图就是比上面这个只考虑位置的效果要好很多。
l 轨迹相似性判断
看完了轨迹压缩,我们再来看一下轨迹的相似性判断,这个应用是比较多的,就是判断两个轨迹它是否有相似的地方,相似的范围是多少?从什么时候开始到什么时候结束,这两段轨迹是有重叠、相似的。
我们先来看一下这个SQL。这个SQL首先定义了两条轨迹,通过ST_MAKETRAJECTORY这个轨迹构造的函数定义了两条轨迹。然后直接有一个LcssSimilarity算轨迹相似度的算子。它的参数也很简单,直接传入两个轨迹,然后定义100,因为默认是米,100就表示100m,就是两个轨迹点,它不能超过100m,在100m以内挨着就表示是相似的。返回的就是轨迹点相似值,就是有多少个轨迹点是相似的,比如右边这两张图上面这条蓝色的轨迹也是条红色的轨迹,在ab这两点基本上是完全相同的,这个时候它的相似度对于这一段来说是100%。下面这个示例就是在235这3个点它是相似的,4是不相似的,因为它的距离超过了100,所以这个时候它的返回值应该就是3,就是235这3个点。
4)点云模型使用案例
最后我们来看一下点云模型的案例。点云模型,通常将自动驾驶就是激光雷达这种设备产生的数据是非常密集的,数据量大,带有时间的属性,还带有很多属性的属性。比如RGB,时间,反射率,温度、湿度,属性维度非常多,所以它的挑战是1、非常巨大的体积,上几万亿这都是很正常的;2、多维,除了位置的xyz,还有它的n维的这种属性。
点云它是怎么管理的呢?在空间数据库里面是有一种pc patch类型,这个类型首先定义一个charmerroy模式,属于Ganos,在模式里面你可以定义它的维度以及它每个维度的字段名称。xyz这个是空间维度,还有属性维度,就是每一个维度有一个名称以及它用什么类型,比如xyz是用浮点类型来存储,时间就用时间类型来存储这么一个模板。然后加分块存储模型,就是实际的存储点云的表。这两个组合构造了一种pc patch类型。
目前它也支持压缩以及基于这种pc patch类型,它提供了很多空间关系、判断操作、以及统计这些算子。右面这个示意图就是就是表示一个框,它就是一个pc patch,它在数据库表里面存储为一行记录,这里面还要说明的一点就是因为点云数据比较大,直接放在数据库里面也不太现实,所以目前通常的做法加上现在的存储方法又有改进,就是将这个patch这些原始的数据直接放到廉价存储如OSS、NAS上面,数据库里面放它的空间索引,这个时候它可能是多维的,至少空间上是xyz三维的,然后可能还带一些时间之类其他的一些属性的一个索引,只把索引放到数据库里面,这样就能够实现存储的廉价以及查询的高效。
l 创建点云扩展
首先也是创建点云扩展模块,就是create extension ganos_pointcloud cascade以及pointcloud_geometry的这两个扩展。可以看一下点云的表是什么样子的?这个时候它是有一个pc patch类型,还有一个pc point的类型,这种方式比较原始,就是一个点一个点作为一行记录来存储,这种存储是比较低效的,所以主要是推荐pc patch这种类型。也就是说一批点来打包成一个patch,然后放到数据库里面,再在这个patch里面构建它的一个索引数。
点云入库
看一下点元数据怎么入库,这是一个真实的案例,这个点云数据客户提供的是一个csv的文件,目前来说管理点云数据最多的也是这种文件格式,很简单,就是一堆的值通过某种比如说逗号来分隔,第一个值是x,第二个是y,第3个是z,第四个值是一个密度,第五个值是一个其他的属性。我们将它入到数据库里面,文件存储是没法检索做分析的,所以这个时候要入数据库里面,看看我们空间数据库是怎么来管理这种点云数据的。
网上有PDAL这么一个入库工具,怎么使用呢?也很简单,你可以定义一个jason,一个配置,在jason里面定义好源数据是什么以及转换器用哪一个,目标要写到哪里?
这里的源数据就是这个csv文件,比如说type是reader读txt的,文件名你可以指定一个文件夹,也可以指定具体的一个文件,这里面是一个具体的csv文件。
header就是字段,第一个字段叫是什么名称?这个可以在这里指定,比如xyz以及它的反射率、时间。
spatialreference就是它的空间参考,因为它也是时空类型的一个数据,它必须要有它的空间参考。
源数据定义完了之后,指定转换器转chipper, 400表示就是一个pc patch里面包含多少个点?就是点云的点包含多少个点,组合成一个patch,这里是400。目标就是writer,writer就是写这种pgpointcloud类型,这需要我们的pg数据库以及阿里云的rdspg以及Ganos引擎组合才能有这种类。
它的连接方式就是我们pg的连接方式, ip地址或者是rds地址、数据库名称、用户按密码、端口,往哪张表里。这个是指定它的表table。
它的空间参考这个时候通常来说是跟原空间参考是一样的。目标这个表它会去创建,这个时候我们不需要手动的去创建这个表,因为在源里面它也指定了字段名称,而且通过模板,可以知道它每个字段它的类型是什么,所以这个时候会自己会去创建表,而不需要我们手动去数据库里面执行创建这个表。
l 点云查询与管理
入完之后我们怎么来创建点云的索引?也很简单,就是creat index这个索引名称,在索引点云这个表也是使用gist索引框架。这里面通过一个函数建立的是一个函数索引,基于函数的索引,这个函数返回的是个pa即那字段是pc patch类型,后通过boundingDiagionalGeometry绑定这个算子,我们得到了patch的一个对角线的框。然后建立gist索引,也就是我们的空间索引,因为是nd,所以我们要指定具体的名称。通常二维空间索引是不需要指定的,因为后面是有一个默认的gist_Geometry_ops-rd,是默认索引类型,如果你是nd是要特意写出来的。
点云数据入库,建完索引,这个时候我们要查可以看一下,这是做了一个压测,你可以xyz来实时构造一个外包框即 3DMakebox,一个左下角点一个右上角点,这么一个三维的点就构造了一个box的框,然后把这个点云的所有的数据,做一个intersection,就是来看看在这个框相交的点源的数据,我们把它查出来,这个时候最好是在后面跟一个ntersex,因为索引3个&&&我们可以去查一下,它是gist_nd索引的外包框。三维的外包框过滤,就是我们where条件后面带一下,把一些在空间上根本不相干的数据先过滤掉,加快做覆盖分析的速度。
它虽然比较小众,并不一定每个行业每个人都对这个能够有所了解,但是它所涉及的范围和知识面也是非常广的。很多行业都可以用它,但不同行业用的时候它所关注的点也是非常不一样的。