Il s'agit d'une question de géométrie SQL Server apparemment simple qui, selon moi, aurait une solution prête à l'emploi, mais je n'ai pas de chance d'en trouver une.
Mon intention est de sélectionner tous les enregistrements d'une table contenant des polygones imbriqués (contenus) dans un polygone plus grand d'une autre table. J'avais prévu des fonctions STWithin
et STContains
comme étant les solutions dont j'avais besoin, mais malheureusement, les deux n'identifient que les polygones intérieurs à l'intérieur de ceux imbriqués dans le plus grand polygone, pas les polygones imbriqués qui touchent la limite du plus grand polygone. Voir l'image par exemple.
Une option alternative qui a fonctionné à mes besoins était STIntersection
. Le problème avec cette fonction, cependant, est qu'elle ne renvoie que la colonne de géométrie! Je voudrais plutôt obtenir l'ID d'enregistrement. Quelqu'un at-il une suggestion sur la façon dont cela peut être fait?
STWithin
:
select a.bg10 from
gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STWithin(b.shape) = 1
where b.mktname = 'Loop'
STContains
:
select a.bg10 from
gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on b.shape.STContains(a.shape) = 1
where b.mktname = 'Loop'
STIntersection
:
select a.shape.STIntersection(b.shape)
from gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STIntersects(b.shape) = 1
where b.mktname = 'Loop'
Éditer:
Une suggestion était d'omettre STIntersection
et d'utiliser uniquement STIntersects
comme suit:
STIntersects
:
select a.bg10
from gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STIntersects(b.shape) = 1
where b.mktname = 'Loop'
Le problème avec cette approche, c'est qu'il STIntersects
semble sélectionner tous les polygones à l'intérieur ou à l'extérieur et toucher le plus grand polygone, pas seulement ceux strictement à l'intérieur. Voir l'image par exemple.
la source
STContains
ouSTWithin
. Pas vraiment un bon hack, mais vous obtiendrez les résultats que vous souhaitez. L'autre option serait de faire les STIntersect avec une comparaison de la zone d'intersection et de la zone des polygones.Réponses:
En théorie, les requêtes que vous avez effectuées doivent renvoyer les polygones que vous avez dit ne pas avoir été renvoyés. Cela me fait penser que vous pourriez rencontrer des problèmes d'erreur en virgule flottante que SQL Server a avec ses types de données spatiales. D'où mon commentaire sur la mise en mémoire tampon du polygone englobant avec une quantité minimale.
Donc, quelque chose comme ce qui suit devrait obtenir les résultats souhaités.
Voici un exemple rapide du comportement attendu de quelques-unes des méthodes spatiales.
Résultats
la source
La requête d'intersection devrait ressembler à ceci (en supposant que vous vouliez que tous les enregistrements reviennent de 'a'):
Si vous voulez juste les zones de a qui coupent b (c.-à-d. Coupure de a à b), vous ajoutez alors la STIntersection
Mais cela ne vous donne pas encore les polygones qui se trouvent dans b ...
Ce type de polygone en polygone est très tatillon avec les limites et leur coïncidence - pour être `` à l'intérieur '', les limites de a ne peuvent pas être confondues avec les limites de b - il en va de même pour `` contient ''.
D'après ces définitions, combien de vos polygones dans a sont réellement dans b ...?
Voulez-vous donc mettre en mémoire tampon b avant de sélectionner des polygones dans a qui se trouvent à l'intérieur? Ou faire un tampon négatif sur un?
Je ne sais pas quelle est la réponse exacte ici ...
la source