在PostGIS

时间:2016-06-19 18:29:51

标签: postgresql postgis raster tile

我是postgres / postgis的新手,我正在试图弄清楚如何使用postgis制作一个空的平铺栅格。

我想生成一个包含5000 X 2000个单元格的空栅格,我想稍后查询它以找到x / y位置的特定单元格或在x / y位置添加单元格值。我将基本上将单个单元格值添加到空栅格中(例如,随着时间的推移报告单元格中的动物目标)。

我发现大多数情况都可以通过首先创建一个栅格表来实现:

CREATE TABLE myRasterTable(rid serial primary key, rast raster);

然后添加一个空栅格:

INSERT INTO myRasterTable(rid,rast)
VALUES(1, ST_MakeEmptyRaster( 5000, 2000, 2485869.5728, 1299941.7864, 100, 100, 0, 0, 2056) );

(参考:http://suite.opengeo.org/docs/latest/dataadmin/pgGettingStarted/raster2pgsql.html

我还添加了一个波段并为其中一个栅格单元添加了一个值:

UPDATE myRasterTable SET rast = ST_AddBand(rast, 1, '32BF'::text, 0);
UPDATE myRasterTable SET rast = ST_SetValue(rast, 1,ST_Transform(ST_SetSRID(ST_MakePoint(7.5,48.5),4326),2056),987.654321)

(参考:https://gis.stackexchange.com/questions/14960/postgis-raster-value-of-a-lat-lon-point

我现在可以查询我设置的栅格单元格的值:

// Location with value
SELECT rid, ST_Value(rast, ST_Transform(ST_SetSRID(ST_MakePoint(7.5,48.5),4326),2056),false) val FROM myRasterTable
// Return = 987.654296875 in 0.5224609375 Seconds

// Location without value:
SELECT rid, ST_Value(rast, ST_Transform(ST_SetSRID(ST_MakePoint(7.0,48.5),4326),2056),false) val FROM myRasterTable
// Return =  0 in 0.51311993598938 Seconds

我发现有很多帖子说,对于较大的栅格,在查询性能方面至关重要,栅格的平铺范围大约为每块瓷砖100X100个单元格(参考:http://postgis.17.x6.nabble.com/raster-loading-and-ST-Value-performance-td4999924.htmlhttps://duncanjg.wordpress.com/2013/09/21/effect-of-tile-size-and-data-storage-on-postgis-raster-query-times/

现在我不知道:

  1. 如何在PostGIS中使用我的大型栅格创建切片,或者如何从PostGIS开始创建平铺栅格?换句话说:我需要使用什么查询来创建覆盖5000X2000栅格的栅格图块集合,其中包含多个包含多个波段的100X100个单元格的图块?
  2. 创建切片后,是否需要创建单独的空间索引,还是自动完成?
  3. 最后:如何在平铺栅格后对特定位置的单元格值进行查询?
  4. 任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:2)

经过一番反复试验后,我似乎找到了解决办法。

要在PostGIS中创建一个包含空白图块的新表格,这些图块加起来为5000 X 2000单元格,我使用了这个查询:

CREATE TABLE myRasterTable (rid integer, rast raster);
INSERT INTO myRasterTable(rast) VALUES(ST_Tile(ST_MakeEmptyRaster( 5000, 2000, 2485869.5728, 1299941.7864, 100, 100, 0, 0, 2056), 10,10, TRUE, NULL));

使用ST_MakeEmptyRaster创建一个范围为5000 X 2000的临时栅格。然后,它使用ST_Tile将临时栅格平铺到10X10单元格中,并将这些图块添加到表格中。

然后我可以添加我的乐队:

UPDATE myRasterTable SET rast = ST_AddBand(rast, 1, '32BUI'::text, 0, NULL);

最后,我可以使用以下内容添加和检索值:

// Add cell value
UPDATE myRasterTable SET rast = ST_SetValue(rast, 1,ST_Transform(ST_SetSRID(ST_MakePoint(7.5,48.5),4326),2056),987654321) WHERE ST_Intersects(rast, ST_Transform(ST_SetSRID(ST_MakePoint(7.5,48.5),4326),2056));

// Get cell value
SELECT rid, ST_Value(rast, ST_Transform(ST_SetSRID(ST_MakePoint(7.5,48.5),4326),2056), false) FROM myRasterTable WHERE ST_Intersects(rast, ST_Transform(ST_SetSRID(ST_MakePoint(7.5,48.5),4326),2056));
// Return = 987654321 in 0.22717499732971 Seconds

正如您所看到的,这已经将查询时间缩短到原始时间的约2/5。

如果我另外添加一个索引:

CREATE INDEX myRasterTable_rast_gist_idx ON myRasterTable USING GIST (ST_ConvexHull(rast));

然后再次执行查询,我得到:

// Get cell value
SELECT rid, ST_Value(rast, ST_Transform(ST_SetSRID(ST_MakePoint(7.5,48.5),4326),2056), false) FROM myRasterTable WHERE ST_Intersects(rast, ST_Transform(ST_SetSRID(ST_MakePoint(7.5,48.5),4326),2056));
// Return = 987654321 in 0.084153890609741 Seconds

正如您所看到的,查询时间再次被削减了一半以上,导致查询时间低于原始查询的1/5。 我还尝试了不同的瓷砖尺寸,发现瓷砖尺寸为10 X 10,性能最佳,但仅比瓷砖尺寸100 X 100略好。

如果有人有进一步的优化,请随意添加。

编辑(08.07.2016)

我写了一篇关于此的小博文。如果有兴趣,您可以在这里查看:http://www.geonet.ch/postgres-postgis-of-rasters-and-geojsons/