Ceci est le deuxième volet d'une série en deux parties sur les risques pour les utilisateurs de logiciels liés à une documentation insuffisante ; plus précisément, la confusion et les résultats inattendus qui découlent d'opérateurs spatiaux faiblement documentés dans les logiciels SIG. La première partie de la série <\/A>examine comment une documentation incohérente et incomplète oblige les utilisateurs à deviner comment les opérateurs spatiaux sont implémentés. La deuxième partie de la série<\/STRONG> analyse les résultats incohérents qui résultent du mélange de différentes implémentations des opérateurs spatiaux.<\/EM><\/P><\/P>L'un des nombreux bugs de géométrie vide que j'ai soumis récemment a été mis en avant cette semaine lorsque j'ai remarqué qu'Esri avait mis à jour le statut en "Fermé : Ne sera pas traité." Ce qui a suivi est une discussion toujours en cours sur le comportement attendu versus les résultats inattendus. Par coïncidence, le problème peut être clairement encadré dans la discussion et les exemples du premier article de cette série (Ce qui est à l'intérieur : Quand (Esri != Clementini) = ?<\/A>).<\/P><\/P>Le premier article de cette série expliquait qu'il n'existe pas de définition unique des relations spatiales pour les bibliothèques de géométrie et les applications géospatiales, et comment le Modèle d'Intersection Étendue Dimensionnellement 9 (DE-9IM) est devenu la définition 2D dominante après son inclusion dans la Spécification d'implémentation OpenGIS pour l'information géographique - Accès aux entités simples - Partie 1 : Architecture commune<\/A>. L'article mettait l'accent sur la façon dont une documentation incomplète des opérateurs spatiaux force les utilisateurs à deviner, souvent incorrectement, comment fonctionne le logiciel au lieu de savoir comment il devrait fonctionner. Aussi regrettable que soit une documentation incomplète pour les utilisateurs, mélanger différentes définitions des relations spatiales au sein du même opérateur spatial est bien pire, et c'est apparemment ce qu'Esri a fait.<\/P><\/P>En reprenant les exemples du post précédent, examinons trois entités et la méthode ArcPy Geometry.within()<\/SPAN>.<\/P><\/P>>>> #Créer un polygone carré>>> polygon = arcpy.FromWKT('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))')>>> #Créer une ligne qui se trouve entièrement sur la frontière du polygone>>> line = arcpy.FromWKT('LINESTRING(1 0, 2 0)')>>> #Créer une ligne vide>>> line_empty = arcpy.FromWKT('LINESTRING EMPTY')>>>>>> #Tester si la ligne est à l'intérieur du polygone>>> line.within(polygon)False>>> #Tester si line_empty est à l'intérieur du polygone>>> line_empty.within(polygon)True<\/PRE><\/P>À titre comparatif, exécutons les mêmes deux tests des lignes 9 et 12 en utilisant ST_Geometry d'Esri dans Oracle :<\/P><\/P>SQL> --Tester si la ligne est à l'intérieur du polygoneSQL> 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'--------------------------------------------------------------------------------  :&nbpsp; &nbpsp; &nbpsp; &nbpsp; &nbpsp; &nbpsp; &nbpsp; &nbpsp; &nbpsp; &nbpsp;SQL> --Tester si line_empty est à l'intérieur du polygoneSQL> SELECT sde.st_within(sde.st_geomfromtext('LINESTRING EMPTY', 0), .&nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;.  .&nbpsp;. FROM dual;SDE.ST_WITHIN(SDE.ST_GEOMFROMTEXT('LINESTRINGEMPTY',0),SDE.ST_GEOMFROMTEXT('POLY'-------------------------------------------------------------------------------- .&nbpsp;. <\/P>Intéressant, les résultats obtenus avec ST_Geometry diffèrent de ceux avec ArcPy.& nbsp; Sachant que les fonctions ST_Geometry sont conformes à l'accès aux entités simples OGC et SQL, ce qui signifie qu'elles implémentent DE-9IM, les résultats obtenus avec ST_Geometry dans Oracle sont attendus car une ligne uniquement sur la frontière d'un polygone n'est pas considérée comme étant à l'intérieur du polygone, et une géométrie vide ne peut pas être à l'intérieur d'une autre géométrie.<\/P><\/P>En regardant les résultats ArcPy, la ligne 10 est correcte seulement<\/SPAN> si les Classes de Géométrie ArcPy <\A>implémentent la définition de Clementini puisque nous avons vu dans le premier article de cette série que la définition Esri de Within est Vrai dans cette situation.& nbsp; Malheureusement, la documentation ArcPy ne précise pas quelle définition elle implémente.& nbsp; Le résultat à la ligne 13 est correct seulement<\SPAN> si les Classes de Géométrie ArcPy<\A>implémentent la définition Esri car la définition Clementini n'autorise pas une géométrie vide à être à l'intérieur d'une autre géométrie.& nbsp; Clair comme de la boue, non ?<\P><\P><\P>L'attitude d'Esri jusqu'à présent est que tout fonctionne comme prévu.& nbsp; Quoi ?!& nbsp; Si c'est le cas, Esri reconnaît implicitement qu'ils implémentent différentes définitions d'une relation spatiale au sein du même opérateur spatial, cela dépend juste des géométries que vous lui passez !!& nbsp; Entre le code source fermé, la documentation incomplète et une implémentation apparemment arbitraire ; utilisez les Classes de Géométrie ArcPy à vos risques et périls.& nbsp;Caveat utilitor<\EM>.<\BODY><\HTML>
<\/P>
Le premier article de cette série expliquait qu'il n'existe pas de définition unique des relations spatiales pour les bibliothèques de géométrie et les applications géospatiales, et comment le Modèle d'Intersection Étendue Dimensionnellement 9 (DE-9IM) est devenu la définition 2D dominante après son inclusion dans la
En reprenant les exemples du post précédent, examinons trois entités et la méthode ArcPy Geometry.within()<\/SPAN>.<\/P><\/P>>>> #Créer un polygone carré>>> polygon = arcpy.FromWKT('POLYGON((0 0, 3 0, 3 3, 0 3, 0 0))')>>> #Créer une ligne qui se trouve entièrement sur la frontière du polygone>>> line = arcpy.FromWKT('LINESTRING(1 0, 2 0)')>>> #Créer une ligne vide>>> line_empty = arcpy.FromWKT('LINESTRING EMPTY')>>>>>> #Tester si la ligne est à l'intérieur du polygone>>> line.within(polygon)False>>> #Tester si line_empty est à l'intérieur du polygone>>> line_empty.within(polygon)True<\/PRE><\/P>À titre comparatif, exécutons les mêmes deux tests des lignes 9 et 12 en utilisant ST_Geometry d'Esri dans Oracle :<\/P><\/P>SQL> --Tester si la ligne est à l'intérieur du polygoneSQL> 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'--------------------------------------------------------------------------------  :&nbpsp; &nbpsp; &nbpsp; &nbpsp; &nbpsp; &nbpsp; &nbpsp; &nbpsp; &nbpsp; &nbpsp;SQL> --Tester si line_empty est à l'intérieur du polygoneSQL> SELECT sde.st_within(sde.st_geomfromtext('LINESTRING EMPTY', 0), .&nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;. &nbpsp;.  .&nbpsp;. FROM dual;SDE.ST_WITHIN(SDE.ST_GEOMFROMTEXT('LINESTRINGEMPTY',0),SDE.ST_GEOMFROMTEXT('POLY'-------------------------------------------------------------------------------- .&nbpsp;. <\/P>Intéressant, les résultats obtenus avec ST_Geometry diffèrent de ceux avec ArcPy.& nbsp; Sachant que les fonctions ST_Geometry sont conformes à l'accès aux entités simples OGC et SQL, ce qui signifie qu'elles implémentent DE-9IM, les résultats obtenus avec ST_Geometry dans Oracle sont attendus car une ligne uniquement sur la frontière d'un polygone n'est pas considérée comme étant à l'intérieur du polygone, et une géométrie vide ne peut pas être à l'intérieur d'une autre géométrie.<\/P><\/P>En regardant les résultats ArcPy, la ligne 10 est correcte seulement<\/SPAN> si les
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
Les membres connectés peuvent publier, suivre les mises à jour, et plus encore. Nouveau ici ? Inscrivez-vous gratuitement.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.