これは、ドキュメント不備によるソフトウェアユーザーのリスクに関する2部構成シリーズの第2部です。具体的には、GISソフトウェアにおける空間演算子の弱いドキュメントから生じる混乱と予期しない結果についてです。 シリーズの第1部<\/A>では、不完全かつ一貫性のないドキュメントがユーザーに空間演算子の実装方法を推測させる必要があることを取り上げました。 シリーズの第2部<\/STRONG>では、異なる実装の空間演算子を混在させた場合に生じる一貫性のない結果について検討します。<\/EM><\/P><\/P>最近私が提出した多くの空ジオメトリバグのうちの1つが今週急浮上しました。Esriがステータスを「Closed: Will Not be Addressed.」に更新したことに気づいたためです。 その後、期待される動作と予期しない結果について現在も議論が続いています。 偶然にも、この問題はこのシリーズの最初の記事(What's Within: When (Esri != Clementini) = ?<\/A>)の議論と例でうまく整理できます。<\/P><\/P>このシリーズの最初の記事では、ジオメトリライブラリや地理空間アプリケーションにおける空間関係の単一定義は存在せず、Dimensionally Extended 9 Intersection Model (DE-9IM) がOpenGIS Implementation Specification for Geographic information - Simple feature access - Part 1: Common architecture<\/A>に含まれたことで主流の2D定義となったことを説明しました。 記事は、空間演算子の不完全なドキュメントがユーザーにソフトウェアの動作を推測させ、時には誤った理解を招くことに焦点を当てました。 不完全なドキュメントがユーザーにとって不幸である一方で、同じ空間演算子内で異なる空間関係定義を混在させることはさらに悪く、それがEsriが行ったことのように見えます。<\/P><\/P>前回の記事の例を借りて、3つのフィーチャとArcPy Geometry.within()<\/SPAN> メソッドを見てみましょう。<\/P><\/P>>>> #正方形ポリゴンを作成>>> polygon = arcpy.FromWKT('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))')>>> #ポリゴン境界上に完全に位置するラインを作成>>> line = arcpy.FromWKT('LINESTRING(1 0, 2 0)')>>> #空のラインを作成>>> line_empty = arcpy.FromWKT('LINESTRING EMPTY')>>>>>> #ラインがポリゴン内かテスト>>> line.within(polygon)False>>> #空ラインがポリゴン内かテスト>>> line_empty.within(polygon)True<\/PRE><\/P>比較目的で、Oracle上でEsriのST_Geometryを使って同じ9行目と12行目のテストを実行してみましょう:<\/P><\/P>SQL> --ラインがポリゴン内かテストSQL> SELECT sde.st_within(sde.st_geomfromtext('LINESTRING(1 0, 2 0)', 0), sde.st_geomfromtext('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))', 0)) FROM dual;SDE.ST_WITHIN(SDE.ST_GEOMFROMTEXT('LINESTRING(10,20)',0),SDE.ST_GEOMFROMTEXT('PO'-------------------------------------------------------------------------------- SQL> --空ラインがポリゴン内かテストSQL> SELECT sde.st_within(sde.st_geomfromtext('LINESTRING EMPTY', 0), sde.st_geomfromtext('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))', 0)) FROM dual;SDE.ST_WITHIN(SDE.ST_GEOMFROMTEXT('LINESTRINGEMPTY',0),SDE.ST_GEOMFROMTEXT('POLY'-------------------------------------------------------------------------------- <\/P>興味深いことに、ST_Geometryを使った結果はArcPyとは異なります。 ST_Geometry関数はOGC simple feature accessおよびSQL準拠であり、つまりDE-9IMを実装しているため、Oracle上でST_Geometryから得られる結果は予想通りです。ポリゴン境界上のみのラインはポリゴン内とは見なされず、空ジオメトリは他のジオメトリ内には存在できません。<\/P><\/P>ArcPy結果を見ると、10行目はArcPy Geometry Classes<\/A>がClementini定義を実装している場合のみ正しいです。このシリーズ最初の記事で見たように、この状況下でEsriのWithin定義はTrueとなります。残念ながらArcPyドキュメントはどちらの定義を実装しているか明示していません。13行目の結果はArcPy Geometry Classes<\/A>がEsri定義を実装している場合のみ正しく、Clementini定義では空ジオメトリが他ジオメトリ内にあることは許されません。非常にわかりづらいですね?<\/P><\/P>Esriの立場は現時点で「すべて設計通りに動作している」というものです。なんと?!もしそうならば、Esriは暗黙的に同じ空間演算子内で異なる空間関係定義を実装していることを認めていることになり、それは渡すジオメトリ次第ということになります!!クローズドソースコード、不完全なドキュメント、および恣意的と思われる実装から判断すると、ArcPy Geometry Classesは自己責任で使用してください。 Caveat utilitor<\/EM>.<\/P><\/BODY><\/HTML>
<\/P>
このシリーズの最初の記事では、ジオメトリライブラリや地理空間アプリケーションにおける空間関係の単一定義は存在せず、Dimensionally Extended 9 Intersection Model (DE-9IM) が
前回の記事の例を借りて、3つのフィーチャとArcPy Geometry.within()<\/SPAN> メソッドを見てみましょう。<\/P><\/P>>>> #正方形ポリゴンを作成>>> polygon = arcpy.FromWKT('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))')>>> #ポリゴン境界上に完全に位置するラインを作成>>> line = arcpy.FromWKT('LINESTRING(1 0, 2 0)')>>> #空のラインを作成>>> line_empty = arcpy.FromWKT('LINESTRING EMPTY')>>>>>> #ラインがポリゴン内かテスト>>> line.within(polygon)False>>> #空ラインがポリゴン内かテスト>>> line_empty.within(polygon)True<\/PRE><\/P>比較目的で、Oracle上でEsriのST_Geometryを使って同じ9行目と12行目のテストを実行してみましょう:<\/P><\/P>SQL> --ラインがポリゴン内かテストSQL> SELECT sde.st_within(sde.st_geomfromtext('LINESTRING(1 0, 2 0)', 0), sde.st_geomfromtext('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))', 0)) FROM dual;SDE.ST_WITHIN(SDE.ST_GEOMFROMTEXT('LINESTRING(10,20)',0),SDE.ST_GEOMFROMTEXT('PO'-------------------------------------------------------------------------------- SQL> --空ラインがポリゴン内かテストSQL> SELECT sde.st_within(sde.st_geomfromtext('LINESTRING EMPTY', 0), sde.st_geomfromtext('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))', 0)) FROM dual;SDE.ST_WITHIN(SDE.ST_GEOMFROMTEXT('LINESTRINGEMPTY',0),SDE.ST_GEOMFROMTEXT('POLY'-------------------------------------------------------------------------------- <\/P>興味深いことに、ST_Geometryを使った結果はArcPyとは異なります。 ST_Geometry関数はOGC simple feature accessおよびSQL準拠であり、つまりDE-9IMを実装しているため、Oracle上でST_Geometryから得られる結果は予想通りです。ポリゴン境界上のみのラインはポリゴン内とは見なされず、空ジオメトリは他のジオメトリ内には存在できません。<\/P><\/P>ArcPy結果を見ると、10行目は
Esriの立場は現時点で「すべて設計通りに動作している」というものです。なんと?!もしそうならば、Esriは暗黙的に同じ空間演算子内で異なる空間関係定義を実装していることを認めていることになり、それは渡すジオメトリ次第ということになります!!クローズドソースコード、不完全なドキュメント、および恣意的と思われる実装から判断すると、ArcPy Geometry Classesは自己責任で使用してください。 Caveat utilitor<\/EM>.<\/P><\/BODY><\/HTML>
I think the risk is assuming Clementini operators exist where no mention of "Clementini" is found. Esri has supported a WITHIN operator since long before the Clementini paper was written.
The creation of SDE (at 3.0) provided a new opportunity to implement a spatial operators library, and Clementini was chosen to be the basis of that library. SDE.ST_GEOMETRY was implemented using that library, and OpenGIS adopted Clementini (probably at Esri's suggestion, though I'm not certain of that). I've got a copy of the Clementini paper (actually, I have several, one in each boot partition of every system I manage), and I use it to check for defects and cross-check for desired functionality, but the average user is not going to want a 2-hour lecture on geometry algebra (and another on geometry calculus) before using a theme-on-theme query tool.
Choosing to break existing functionality on upgrade is a dangerous endeavor. The rules become even more slippery when additional functionality is added. And Clementini treats a number of common topological relationships as multiple discrete cases, which would have removed functionality. So, yes, there are multiple geometric relationship libraries within Esri code. When you add in the absurdity of having an "empty line" discrete from an "empty point" and don't support a true "Nil" (which is a feature of WKT), then you've also got multiple conflicting standards to address. And that means that yes, there are multiple possible oddities when asking a computer to answer a nonsensical Boolean question. Personally, I would return FALSE to all Boolean questions outside of defined behavior, but because it is undefined, any outcome, including a division by zero exception would be technically correct.
Vince Angelo, thanks for the comments, I know you have a long history with SDE and spatial operators. Your background and perspective is always good reading, even if we aren't always in perfect agreement.
Regarding your first paragraph, I completely agree. It seems I may have failed to put what was in my head down in writing. When it comes to the ArcPy Geometry Classes specifically, which is really what I am selfishly most concerned about, I expected the Geometry.within() method to return the same results as the Select Layer By Location tool, but that isn't the case with a line on a polygon boundary. With no reference to Clementini or DE-9IM, I expected to see results consistent with Esri's definition but the line on boundary results from Geometry.within() are consistent with Clementini instead.
Vince ... got notes???
..... but the average user is not going to want a 2-hour lecture on geometry algebra (and another on geometry calculus) before using a theme-on-theme query tool.....
doing my sabbatical stuff so anything interesting pass on!!!
I do, somewhere, but they were part of the 'C' API training materials, so I can't give them away.
The Clementini paper itself ("A Small Set of Topological Relationships Suitable for End-User Interaction") formed the basis of my slides, with a table for the function calls and how they were defined with respect to features, boundaries, exterior, and interior. I usually lost most of the students before the end, so I never went on the calculus-based method (CBM). But I did design some exercises that could construct geometries from the command line, then test the various relationships possible (and those tools made their way into se_toolkit).
- V
サインインしたメンバーは投稿、更新のフォローなどができます。初めてですか?無料アカウントを登録してください。
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.