地籍の小包データで構成される2つのデータセットがあり、それぞれ約125,000行です。ジオメトリ列は、区画の境界を表すWKBポリゴンです。すべてのデータは幾何学的に有効です(ポリゴンが閉じているなど)。
いくつかの最近のデータは、比較ジョブに使用されているベースデータとは異なる投影法で到着しました。そのため、新しいデータを再投影しました(ベースは4326でした。もう1つは、900914としてPostGISに取り込まれたWGA94でした... 4326に再投影しました)。 。
分析の最初の段階は、一致しない区画を見つけて保存することでした。その一部は、同一のジオメトリを持つ区画を識別して保存することです。
だから私は非常に標準的なクエリを実行しました(以下のコードブロックはスキーマの詳細などを抽象化しています):
create table matchdata as
select a.*
from gg2014 a, gg2013 b
where ST_Equals(a.g1,b.g1)
結果はゼロです。
「おかしい…」と思った。「おそらく、再投影によって引き起こされた小さな頂点シフトがありました。それは煩わしいことであり、実際には起こらないはずです。」
幸いにも、空間的に同一である必要がある区画を確立できるようにする豊富な空間データ(5つの識別子列)があります。2014年のテーブルの変更日が2013年のデータの最大変更日より前である同じ識別子を持つものです。これは、120,086の個別の行になります。
識別子とジオメトリを別のテーブル(match_id
)に保存し、次のクエリを実行しました。
select apid,
bpid,
ST_Area(ag::geometry) as aa,
ST_Area(bg::geometry) as ab,
ST_Area(ST_Intersection(ag,bg)::geometry)/ST_Area(ag::geometry) as inta,
ST_Area(ST_Intersection(ag,bg)::geometry)/ST_Area(ag::geometry) as intb
from match_id
order by inta
最初の16の値についてinta
とintb
同様にゼロであった、次の456であった0.99999999っぽい(最小0.99999999999994、最大0.999999999999999)、以降1た473行-交差の面積があった行120050まで、より大きいいずれかの幾何学的形状(最大値inta
とはintb
)まだ1.00000000000029だったが、。
だからここに私の難問があります:2つのジオメトリがそれぞれの領域の99.999999999994%から100.000000000029%の間で空間的に交差する場合、「ST_Equals」に「そうです...それを与えます。十分に近い」と言ってもらいたいのです。
結局のところ、これは16兆分の1の割合で減少していることに相当します。
地球の周囲(約40,000 km)のコンテキストでは、0.0000000025 kmの頂上から離れているようなものです(面積の差が小さくなるため、頂点のシフトはさらに小さくする必要があります)。
TFD(私がR'dを持っています)によると、許容値ST_Intersects()
は概念的に0.00001m(1mm)であるため、頂点の暗黙の変更(私が確認していないことを告白します:ST_Dump()
それらを変更するので)は小さくなるようです。公差より。(私はそれを理解していますがST_Intersects !== ST_Intersection()
、言及されている唯一の許容範囲です)。
ST_Equals()
... によって行われた頂点比較に対応する許容誤差を見つけることができませんでしたが、少なくとも120,000行の行が空間的同一性の賢明な評価に合格するはずであるのに実際にはそうではないようです。
(注:私も同じ演習を使用しました::geography
-結果はよりばらつきがありましたが、きれいな「1」で110,000エントリ以上ありました)。
コードの隙間を掘り下げる必要がない、ST_Equalsの許容範囲を緩和する方法はありますか?私はそうすることに熱心ではありません。
そうでない場合、誰もが知っているクラッジはありますか?
注:「kludge」が次のような二者間比較を行わなかった場合、それは良いことです。
where ST_within(g1, ST_Buffer(g2, 0.0000001))
and ST_within(g2, ST_Buffer(g1, 0.0000001))
- I've done that: sure, it works... but it's a gigantic documentation PITA).
私はこれを回避できますが、回避策を文書化するために20ページを書くことは-危険なデータを取得した場合にのみ再び表示されます-一度限りの可能性があることを考えると、私が行う必要はないPITAです。
(バージョン:Postgresql 9.3.5; PostGIS 2.1.3)
ST_Equals
true
ジオメトリが等しい場合にのみ返されます-ジオメトリタイプ、頂点の数、SRID、および頂点の値(すべての次元で、同じ順序)。差異がある場合、比較は停止し、false
返されます。
ST_Equals()
方向性を無視します。閉じた2次元ポリゴンの場合、ポイントが時計回りと反時計回りのどちらで列挙されても違いはないことを意味します。ST_OrderingEquals()
より厳しいテストです。とはST_Dump()
いえ、頂点を検査した(すべての頂点のデルタを使用および計算した)ので、@ JohnBarçaのすばらしい答えはお金にかかっていることは明らかです。ST_SnapToGrid()で比較が行われない限り、1つのジオメトリが再投影される場合、事前に同一である既知のデータST_equals()
であっても禁忌です。
(100*(ST_Area(ST_Intersection(a.g1, b.g1))/ST_Area(a.g1)))::int as int_pca
して(100*(ST_Area(ST_Intersection(a.g1, b.g1))/ST_Area(b.g1)))::int as int_pcb
(JOIN
インクルードを確認してくださいST_Intersects(a.g1,b.g1)
)。(int_pca, int_pcb)=(100,100)
(またはその他のカットオフのセット)かどうかをテストします。Kludgyですが、30分以内に260万個の区画を処理します(g1にGISTインデックスが作成されている限り)。