To pozornie proste pytanie dotyczące geometrii programu SQL Server, które - jak myślałem - miałoby gotowe rozwiązanie, ale nie mam szczęścia go znaleźć.
Moim zamiarem jest wybranie wszystkich rekordów w jednej tabeli, które mają wielokąty zagnieżdżone (zawarte) w większym wielokącie z innej tabeli. Oczekiwałem funkcji STWithin
i STContains
jako rozwiązań, których potrzebowałem, ale niestety oba identyfikują tylko wewnętrzne wielokąty w obrębie tych zagnieżdżonych w większym wielokącie, a nie te zagnieżdżone wielokąty, które dotykają granicy większego wielokąta. Zobacz na przykład obraz.
Alternatywą, która spełniła moje potrzeby, była STIntersection
. Problem z tą funkcją polega jednak na tym, że zwraca tylko kolumnę geometrii! Zamiast tego chciałbym uzyskać identyfikator rekordu. Czy ktoś ma sugestie, jak to zrobić?
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'
Edytować:
Jedną z sugestii było pominięcie STIntersection
i użycie wyłącznie STIntersects
w następujący sposób:
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'
Problem z tym podejściem polega na tym, że STIntersects
wydaje się, że zaznacza się wszystkie wielokąty wewnątrz lub na zewnątrz i dotyka większego wielokąta, nie tylko te ściśle wewnątrz. Zobacz na przykład obraz.
źródło
STContains
lubSTWithin
. Niezbyt fajny hack, ale zapewni Ci oczekiwane rezultaty. Inną opcją byłoby wykonanie STIntersects z porównaniem obszaru przecięcia i obszaru wielokątów.Odpowiedzi:
Teoretycznie zadane przez Ciebie zapytania powinny zwrócić wielokąty, o których mówiłeś, że nie zostały zwrócone. To sprawia, że podejrzewam, że możesz napotkać problemy z błędami zmiennoprzecinkowymi, które występują w SQL Server z typami danych przestrzennych. Stąd mój komentarz na temat buforowania ograniczającego wielokąta minimalną ilością.
Więc coś takiego jak poniżej powinno uzyskać pożądane wyniki.
Oto szybki przykład oczekiwanego zachowania kilku metod przestrzennych.
Wyniki
źródło
Zapytanie o przecięcie powinno wyglądać tak (zakładając, że chcesz odzyskać wszystkie rekordy z „a”):
Jeśli chcesz tylko te obszary, które przecinają b (tj. Przycinanie a do b), dodajesz przecięcie STI
Ale to nie daje ci wielokątów, które są jeszcze w obrębie b ...
Ten typ wielokąta w wielokącie jest bardzo wrażliwy na granice i ich zbieżność - aby być „wewnątrz”, granice a nie mogą być zbieżne z granicami b - to samo dotyczy „Contains”.
Według tych definicji, ile twoich wielokątów w a faktycznie znajduje się w obrębie b ...?
Czy chcesz buforować b, zanim wybierzesz wielokąty znajdujące się w środku? Czy zrobić bufor ujemny na?
Nie jestem pewien, jaka jest dokładna odpowiedź tutaj ...
źródło