web-dev-qa-db-fra.com

SQL Server 2008 Spatial: recherchez un point dans un polygone

J'utilise les types de données spatiales SQL Server 2008. J'ai une table avec tous les états (sous forme de polygones) comme type de données GEOMETRY. Maintenant, je veux vérifier si les coordonnées d'un point (latitudes, longitudes) en tant que type de données GEOGRAPHY sont à l'intérieur de cet état ou non.

Je n'ai trouvé aucun exemple utilisant les nouveaux types de données spatiales. Actuellement, j'ai une solution de contournement qui a été mise en œuvre il y a plusieurs années, mais elle présente certains inconvénients.

J'ai à la fois SQL Server 2008 et 2012. Si la nouvelle version comporte des améliorations, je peux aussi commencer à travailler dessus.

Merci.

MISE À JOUR 1:

J'ajoute un exemple de code pour un peu plus de clarté.

declare @s geometry  --GeomCol is of this type too.
declare @z geography --GeogCol is of this type too.

select @s = GeomCol
from AllStates
where STATE_ABBR = 'NY'

select @z = GeogCol
from AllZipCodes
where ZipCode = 10101
22
Farhan

Je pense que la méthode géographique STIntersects () fera ce que vous voulez:

DECLARE @g geography;
DECLARE @h geography;
SET @g = geography::STGeomFromText('POLYGON((-122.358 47.653, -122.348 47.649, -122.348 47.658, -122.358 47.658, -122.358 47.653))', 4326);
SET @h = geography::Point(47.653, -122.358, 4326)

SELECT @g.STIntersects(@h)
28
Ben Thul

Si vous ne pouvez pas modifier le type de données pour les polygones stockés en GEOGRAPHY, vous pouvez convertir la latitude et la longitude en entrée en GEOMETRY et utiliser le STContains ou le STIntersects contre la valeur convertie.

DECLARE @PointGeography GEOGRAPHY = geography::Point(43.365267, -80.971974, 4326)
DECLARE @PointGeometry GEOMETRY = geometry::STGeomFromWKB(@PointGeography.STAsBinary(), 4326);

SELECT @PolygonGeometry.STContains(@PointGeometry);

Aller dans la direction opposée - essayer de convertir les polygones GEOMETRY en GEOGRPAHY - est sujet à des erreurs et risque d’échouer de par mon expérience.

Et notez que si vous essayez de créer le point GEOMETRY directement à partir des valeurs de latitude et de longitude, alors la STContains (ou STIntersects) ne fonctionnera pas (c’est-à-dire ne donnera pas de correspondance quand ils le devraient).

2
Christopher King
  1. Vous ne devriez pas mélanger la géométrie et la géographie. La géométrie est pour PLANE PLANES, la géographie est pour SPHEROIDS (comme la Terre).
  2. Vous "devriez" réconcilier les SRID pour traiter ceci. Chaque SRID (par exemple 2913 = NZG2000) décrit une relation de transformation. Chaque SRID peut être utilisé pour mapper de/vers une sphère uniforme, ce qui vous permet d’aller de l’une à l’autre.
  3. Jusqu'à ce que vous obteniez un "même" SRID sur les deux valeurs, de nombreuses fonctions .STxXX renverront NULL (vous pourriez avoir la valeur par défaut 0 dans les deux cas).
  4. S'ils ne sont pas identiques mais que vous prétendez qu'ils le sont, vous pouvez avoir des erreurs dans les cas Edge.
  5. Si vous passez du temps "précalculé", vous pouvez déterminer les points haut/gauche et bas/droite pour les liens englobants impliqués (et les stocker), et utiliser ces valeurs dans les index pour limiter le nombre d'enregistrements à vérifier./L <BB/R et AB/R> BT/L ils ne peuvent pas se chevaucher, ce qui signifie un simple contrôle 4 ET numérique dans votre WHERE limitera votre ST dans les contrôles

Voici un exemple que j'ai utilisé dans SRID 2193. Toutes les routes dans un rayon de 3 km d'un point donné et à l'intérieur d'une zone scolaire spécifique

DECLARE @g geometry

SELECT @g = GEO2193 FROM dbo.schoolzones WHERE schoolID = 319

SELECT DD.full_road_name, MIN(convert(int,  dd.address_number)), MAX(convert(int,  dd.address_number))
FROM (

select A.* from dbo.[street-address] A

WHERE (((A.Shape_X - 1566027.50505) * (A.Shape_X - 1566027.50505)) + ((A.Shape_Y - 5181211.81675) * (A.Shape_Y - 5181211.81675))) < 9250000

and a.shape_y > 5181076.1943481788

and a.shape_y < 5185097.2169968253

and a.shape_x < 1568020.2202472512

and a.shape_x > 1562740.328937705

and a.geo2193.STWithin(@g) = 1
) DD
GROUP BY DD.full_road_name
ORDER BY DD.full_road_name
0
Roger Willcocks
declare @g geometry
set @g=geometry::STGeomFromText('POLYGON((-33.229869 -70.891988, -33.251124 -70.476616, -33.703094 -70.508045, -33.693931 -70.891052,-33.229869 -70.891988))',0)

DECLARE @h geometry;

SET @h = geometry::STGeomFromText('POINT(-33.3906300 -70.5725020)', 0);
SELECT @g.STContains(@h);
0
Leonel

Si vous avez une table (exemple: SubsriberGeo) où l’une des colonnes (exemple: Emplacement) a des points géographiques comme valeurs et que vous souhaitez trouver tous les points de cette table qui sont dans un polygone, voici une façon de le faire:

 WITH polygons
 AS (SELECT 'p1' id, 
            geography::STGeomFromText('polygon ((-113.754429 52.471834 , 1 5, 5 5, -113.754429 52.471834))', 4326) poly
),
 points
 AS (SELECT [SubscriberId],[Location] as p FROM [DatabaseName].[dbo].[SubscriberGeo])
 SELECT DISTINCT 
        points.SubscriberId, 
        points.p.STAsText() as Location
 FROM polygons
      RIGHT JOIN points ON polygons.poly.STIntersects(points.p) = 1
 WHERE polygons.id IS NOT NULL;
0
grabhints