geotrellis使用(十一)实现空间数据库栅格化以及根据属性字段进行赋值

时间:2022-07-25 14:58:19

Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html

目录

  1. 前言
  2. 安装空间数据库
  3. 空间数据库栅格化
  4. 根据属性字段进行赋值
  5. 总结

一、前言

       前面写了一篇文章(geotrellis使用(八)矢量数据栅格化)讲解了如何使用Geotrellis将Shape文件栅格化,并许下了后续会写一篇文章讲解空间数据库栅格化的诺言,周末虽然不是闲来无事,但是也得抽出时间兑现自己的诺言,就认认真真的折腾了一番,总算完成了,遂记录之。

二、安装空间数据库

       目前有许多数据库添加了空间支持,如SQLSERVERPostgreSqlite等,本文选择开源的Postgre,其空间支持名称为PostGis

       网上讲解Postgre安装的文章很多,在这里主要强调两点。

  1. 在安装完Postgre之后,要点击Application Stack Builder选择Spatial Extensions安装空间扩展。
  2. 在创建数据库的时候需要选择空间模板,否则数据库不支持空间操作。

三、空间数据库栅格化

3.1 添加Postgre驱动

       由于项目采用sbt框架,所以只需要在build.sbt文件中添加一句libraryDependencies += "org.postgresql" % "postgresql" % "9.4.1208"即可,此处给大家提供一个网站可以查询常用jar包的sbt添加方式,链接为http://search.maven.org

3.2 连接Postgre

       此处只用到最基本的读取数据库,代码如下:

var url = "jdbc:postgresql://localhost:5432/dbName"
var conn: Connection = null
try {
conn = DriverManager.getConnection(url, "user", "pass") val statemnt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)
val rs = statemnt.executeQuery("select * from tablename")
while (rs.next()) {
rs.getString("columnName")
}
}
catch {
case e: Throwable => println(e.getMessage)
}
conn.close

其中dbName表示空间数据库名称,user表示用户名,pass表示密码,tablename表示表名,columnName表示要取的字段名。

3.3 读取空间数据

       此处需要先准备空间数据,具体不在这里赘述,简单的方式可以将shape file直接导入到数据库中。然后查看空间字段名称,一般为geom

       其实读取空间数据与读取普同数据相同,只需要更改一下select语句,给需要读取的空间字段添加一个st_astext函数即可,如select st_astext(geom) as geom from tablename,这样采用rs.getString("geom")读出来的就是一个WKT字符串,后续处理与之前介绍的Shape file栅格化相同。

四、根据属性字段进行赋值

       在geotrellis使用(八)矢量数据栅格化一文中介绍的栅格化方式只能给栅格化后的空间对象赋同一个值,无论是Shape file还是空间数据库,有时候往往需要读取另一个属性(字段),并将此属性的值作为空间对象栅格化后的值。其实现方式与之前的方式基本相同,主要存在两点不同:

  1. 需要多读取一个属性值
  2. 每个空间属性根据此值赋值

4.1 读取字段值

       读取与空间字段相同,需要注意的是要与空间字段的值一一对应,可以采用Map或者自定义类(包含Geometry对象和值对象)的方式进行关联。

4.2 为空间属性赋值

       之前介绍的栅格化方式是使用Rasterizer.rasterizeWithValue(features, re, value)直接为所有空间对象赋同一个值value,此处需要为每个对象赋不同的值,可以采用以下方式:

val tile = ByteArrayTile.fill(byteNODATA, re.cols, re.rows)
for (feature <- features) {
Rasterizer.foreachCellByGeometry(feature.geometry, re) { (col, row) => tile.set(col, row, Math.round(feature.value).toInt) }
}

此处的feature是自己定义的一个类,具体为case class VectorData(geometry: Geometry, value: Double)

       具体实现原理是:先新建一个Tile类型对象,然后循环每个空间对象,调用Rasterizer类中的foreachCellByGeometry方法,其定义如下:def foreachCellByGeometry(geom: Geometry, re: RasterExtent)(f: (Int, Int) => Unit)。这里采用柯里化函数的方式,f表示为空间对象赋值的函数,这里为其赋值为(col, row) => tile.set(col, row, Math.round(feature.value).toInt),即为tile(col, row)坐标点赋值为对应的属性值。

五、总结

       以上就是利用周末时间完成的读取空间数据库栅格化以及为空间对象赋对应的其他字段的值的实现方法,都很基础。但是万丈高楼原地起,只有经过一点点的积累,一点点的努力方能成就你的伟岸高楼。周末愉快!