postgresql - 如何从无效的线串中构建区域(或防止错误)

标签 postgresql openstreetmap postgis

我正在使用 OpenStreetMaps 数据。由 Osmosis 加载到带有 Postgis 2.2 的 Postgres 9.4 中,带有为 ways 表构建的线串几何图形。

我想根据某些关系制作多边形(在 OSM 中,关系是一组方式(线串) - 一些标记为外部,一些标记为内部,并非所有方式都必须关闭 - 多种方式一起可以表示外圈)。但 OSM 数据并不完美 - 存在错误的关系,内部“孔”与外环相交。例如:http://www.openstreetmap.org/relation/6095901#map=17/48.93209/19.14858

我正在尝试这个查询

SELECT ST_BuildArea(ST_Collect(w.linestring)) AS geom
FROM relations r
JOIN relation_members rm ON r.id = rm.relation_id AND rm.member_type = 'W'
JOIN ways w ON w.id = rm.member_id
WHERE r.id = 6095901 -- in reality here is broad condition on relation
GROUP BY r.id

结果是错误的:

ERROR:  LWGEOM_GEOS_buildArea: TopologyException: Input geom 1 is invalid: Self-intersection at or near point 19.149718131981164 48.934732947538478 at 19.149718131981164 48.934732947538478

那么,我在这里有哪些选择?理想情况下,我想以某种方式“解决这个问题”——也许忽略有问题的“漏洞”,或者将它们“夹”到外环边界等。

如果不可能,至少我希望查询“跳过”(返回 NULL 几何体)这样的无效关系,而不是在第一个错误没有结果时死掉。

编辑:原始示例案例已在 OSM 数据中修复。这是新示例:关系 ID 5636774 是自相交的多边形

最佳答案

我相信您可以通过使用 ST_Union 而不是 ST_Collect 来避免这些错误。它速度较慢,但​​会消除重叠的部分。 ST_Collect 的文档中有关于它的注释:

http://postgis.net/docs/ST_Collect.html

这是我为测试您的第二个示例所做的工作:

create table ways ( id integer, linestring  geometry(Linestring, 4326) );
insert into ways values (1, ST_GeomFromText('LINESTRING(52.3474437 35.3635293,52.347219 35.3636168,52.3472848 35.36407,52.3475095 35.3639826,52.3474437 35.3635293 )', 4326));
insert into ways values (1, ST_GeomFromText('LINESTRING(52.3473579 35.3642849,52.347274 35.3636982,52.3468764 35.3638506,52.3468949 35.3639796, 52.3472102 35.3638587, 52.3472757 35.3643164, 52.3473579 35.3642849)', 4326));
insert into ways values (1, ST_GeomFromText('LINESTRING(52.3468455 35.3636261, 52.34673 35.3636689, 52.3468697 35.3646806, 52.3474622 35.3644612, 52.3474339 35.3642567, 52.3473579 35.3642848, 52.3472762 35.3643151, 52.346957 35.3644333,  52.3468945 35.3639806,  52.3468765 35.3638507, 52.3468455 35.3636261)', 4326));
select ST_BuildArea(ST_Collect(linestring)) from ways;
select ST_BuildArea(ST_Union(linestring)) from ways;

我也考虑过使用 ST_IsValid,但事实证明即使对于这种糟糕的形状,ST_IsValid(ST_Collect(linestring)) 也是正确的,所以我想这无济于事你。

关于postgresql - 如何从无效的线串中构建区域(或防止错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36624943/

相关文章:

sql - PostGIS 按 ST_Distance 排序 - 不按距离排序记录

ruby-on-rails - Heroku 推送错误

google-maps - 使用 google map 或 openstreetmaps API 绘制大城市的区域

openstreetmap - 如何使用Leaflet在OpenStreetMap上显示节点和路线?

html - 如何解决传单 html 小部件中缺少 OSM 磁贴的问题?

参数错误的postgresql调用函数

postgresql - 查询在 PostgreSQL 中运行几分钟后连接丢失

postgresql - 在 Postgres 中将重复数据存储为列?

sql - 带有父子的嵌套 sqlalchemy 过滤器

sql - 你能阻止在 postgresql 中的 after 触发器中插入吗?