SQL 2008のポリゴンの「利き手」を変更する(ポリゴンの頂点の順序を逆にする)


11

SQL 2008に取得しようとしている数万のポイントで構成される数百の形状(polygonsとmultipolygons)があります。

残念ながら、インポートしようとしたシェイプは「右利き」です(各シェイプの周囲は、含まれているポイントの周りに時計回りに描かれています)。SQLサーバーは、少なくともgeography型については、「左回り」の形状(内部で反時計回り)を想定しています。これは、SQLが、自分の形状を除いて地球全体を選択しようとしていることを前提としていることを意味します。一部の人々は、これを「裏返し」の形状と表現しています。

MSDNから、どのリングの向きを使用するべきかについてイライラするほど言っていません:

geographyデータタイプを使用して空間インスタンスを格納する場合、リングの方向を指定し、インスタンスの場所を正確に記述する必要があります。

SQL 2008で間違ったリング方向を使用すると、次のエラーでクラッシュします(強調は私のものです)。

ユーザー定義ルーチンまたは集計 "geography"の実行中に.NET Frameworkエラーが発生しました:Microsoft.SqlServer.Types.GLArgumentException:24205:指定された入力は、単一の半球を超えているため、有効なgeographyインスタンスを表していません。各geographyインスタンスは、単一の半球内に収まる必要があります。このエラーの一般的な理由は、ポリゴンのリングの向きが間違っていることです。

geometryではなくとしてシェイプをインポートすることはgeography問題ありませんが、geography可能であれば使用したいと思います。

SQL 2012では、この問題を修正するのはかなり簡単ですが、私は2008に縛られています。

形状を変換するにはどうすればよいですか?


1
+1すばらしい質問... SQLサーバーが左利きの形状を想定しているというリンクはありますか?
カークカイケンダル2013

@カークありがとう。公式ドキュメントを見つけるのに問題がありますが、「リングの向き」が重要であると記載されているMSDNにリンクできます(ただし、どちらの方法を使用するかは記載されていません)。また、クラッシュしたときに発生するエラーも表示します。
マイケル-クレイシャーキーはどこですか

回答:


14

Spatial Edのブログには簡潔な解決策がありました。以下は、変換を示すいくつかのSQLです。

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

そして、エドの投稿からの抜粋

この動作の鍵はSTUnion()メソッドです。これはOGCベースのメソッドであり、特定のフィーチャのジオメトリ全体作用するため、ポリゴンをメソッドに必要な方向に強制します。これは、たまたまGeographyタイプ[...]に使用されている方向です。この方法は非常に効率的で、オーバーヘッドを小さく抑えます[...]。


2
SQL Server 2008 r2では、これを機能させるために、.MakeValid()をSTUnion()の内側にも配置する必要がありました。.STUnion(@ geom.MakeValid()。STStartPoint())
Chris Smith

@Smittyこれは、SQLが他の方法で開始点を決定できない場合に適しています。多分、形状がそれ自体または他の奇妙な状況で二重に戻るか?
マイケル-クレイシャーキーはどこですか

はい、私の状況では、形は奇抜で、重なり合っています。
Chris Smith

0

SQL Server 2012以降では、ReorientObject()メソッドがこれを実現する必要があります。<SQL Server 2012の場合、以下は代替方法です。

既存のSQL地理@gの場合、以下のコードはポイントを抽出し、ポイント(頂点)を含むポリゴンを逆の順序で再作成します
(注1:単純なポリゴンでは機能しますが、リング/重心のあるポリゴンでは機能しません)
(注2: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); 

0

Stack Overflowで提案さているようSQL Server Spatial ToolsからSQLとC#の不自然なハイブリッドを使用できるようです。

注:この回答が投稿された時点では、あまり情報がありませんでした。SQL Server Spatial Toolsが他に必要な場合を除いて、この方法を試さないでください。代わりに、ここまたはStack Overflowで他の回答のいずれかを試してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.