Modifier la «neutralité» des polygones pour SQL 2008 (ordre inverse des sommets des polygones)


11

J'ai quelques centaines de formes ( polygons et multipolygons) constitués chacun de plusieurs dizaines de milliers de points que je suis en train d'entrer dans SQL 2008.

Malheureusement, les formes que j'ai essayé d'importer sont "droitières" (le périmètre de chacune est tracé dans le sens des aiguilles d'une montre autour des points qu'il contient). Serveur SQL suppose « gauchers » formes ( dans le sens antihoraire autour de l'intérieur), au moins pour les geographytypes. Cela signifie que SQL suppose que j'essaie de sélectionner la terre entière à l' exception de ma forme. Certaines personnes décrivent cela comme des formes "à l'envers".

De MSDN , qui ne dit pas avec frustration quelle orientation d'anneau on doit utiliser:

Si nous utilisons le geographytype de données pour stocker l'instance spatiale, nous devons spécifier l'orientation de l'anneau et décrire avec précision l'emplacement de l'instance.

Si vous utilisez la mauvaise orientation de l'anneau dans SQL 2008, il se bloque avec l'erreur suivante (c'est moi qui souligne):

Une erreur .NET Framework s'est produite lors de l'exécution d'une routine définie par l'utilisateur ou d'une "géographie" agrégée: Microsoft.SqlServer.Types.GLArgumentException: 24205: L'entrée spécifiée ne représente pas une instance géographique valide car elle dépasse un seul hémisphère. Chaque instance de géographie doit tenir dans un seul hémisphère. Une raison courante de cette erreur est qu'un polygone a la mauvaise orientation d'anneau.

L'importation des formes au geometrylieu de geographyfonctionne très bien, mais j'aimerais utiliser geographysi je le peux.

Dans SQL 2012, il semble assez trivial de résoudre ce problème, mais je suis lié à 2008.

Comment dois-je convertir les formes?


1
+1 grande question ... avez-vous un lien où il est dit que le serveur SQL prend des formes pour gauchers?
Kirk Kuykendall du

@Kirk Merci. J'ai du mal à trouver la documentation officielle, mais je peux créer un lien vers le MSDN où il est dit que l '"orientation de l'anneau" est importante (bien qu'elle ne dise pas quel moyen utiliser). Je vais également mettre dans l'erreur que l'on obtient quand il se bloque.
Michael - Où est Clay Shirky

Réponses:


14

Le blog de Spatial Ed avait une solution concise. Voici du SQL démontrant la transformation:

DECLARE @geom GEOMETRY = 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))';
DECLARE @geog GEOGRAPHY = @geom.MakeValid().STUnion(@geom.STStartPoint()).STAsText()

Et un extrait du post d' Ed:

La clé de ce comportement est la STUnion()méthode. Puisqu'il s'agit d'une méthode basée sur OGC, travaillant sur toute la géométrie pour une entité donnée, elle force les polygones dans l'orientation requise pour la méthode, qui se trouve être celle utilisée pour le Geographytype [...]. Cette méthode illustrée est assez efficace, en gardant les frais généraux petits [...].


2
Sur SQL Server 2008 r2, je devais également mettre .MakeValid () à l'intérieur de STUnion () pour que cela fonctionne: .STUnion (@ geom.MakeValid (). STStartPoint ())
Chris Smith

@Smitty Cela a du sens pour les cas où SQL ne peut pas autrement déterminer le point de départ. Peut-être que si la forme se replie sur elle-même ou dans d'autres circonstances étranges?
Michael - Où est Clay Shirky

Oui, dans ma circonstance, la forme est délabrée et se chevauche.
Chris Smith

0

Dans> = SQL Server 2012, la méthode ReorientObject () devrait accomplir cela. Pour <SQL Server 2012, voici une méthode alternative.

Pour une géographie SQL existante @g, le code ci-dessous extrait les points et recrée un polygone avec des points (sommets) dans l'ordre inverse:
(NOTE 1: fonctionne pour les polygones simples, pas pour les multipolygones ou les polygones avec des anneaux / centroïdes)
(NOTE 2: en utilisant le système de coordonnées SRID 4326 (WGS 84))

--For existing geography @g
DECLARE @GeometryText varchar(max), @ReversedPolygon geography
DECLARE @GeometryType varchar(20) = 'POLYGON', @Count int
SET @Count = @g.STNumPoints()
WHILE @Count > 0
BEGIN
    SET @GeometryText = @GeometryText + CONVERT(varchar(30),CONVERT(decimal(12,8),@g.STPointN(@Count).Long)) + ' ' + CONVERT(varchar(30),CONVERT(decimal(12,8),@g.STPointN(@Count).Lat))
    SET @Count = @Count - 1
    IF @Count > 0 SET @GeometryText = @GeometryText + ','
END
SET @GeometryText = @GeometryType +'((' + @GeometryText + '))'
SET @ReversedPolygon = geography::STGeomFromText(@GeometryText, 4326); 

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.