2016-04-14 15 views
1

私はOpenStreetMapsデータを使って遊んでいます。 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ジオメトリ)、このような無効な関係のため、結果のない最初のエラーでは死ぬことはありません。

EDIT:元の例はOSMデータで修正されています。ここに新しい例があります:関係ID 5636774は自己交差する多角形です

+0

無効なgeomにはST_MakeValid(geom)関数を使用できます。 –

答えて

0

ST_Collectの代わりにST_Unionを使用することで、これらのエラーを回避できます。それは遅くなりますが、重なったセクションを取り除きます。 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))この悪い形であっても真実だから、それはあなたを助けないと思う。

+0

私はST_Unionを試しましたが、それは良くありません。ポリゴン内の穴はこのように失われています。外側のシェル内のすべての領域が埋まっています。これは有効なポリゴンでも発生するため、問題のある無効なポリゴンよりもはるかに多くの無効なデータが生成されます – rouen