deezus blog

.Net Core、Typescriptを中心に技術的ノウハウを公開しています

SQLServerのgeography型をポリゴンで検索する場合は左回りである必要があります

はじめに

SQLServerのgeography型をポリゴンで空間検索する際、座標が左回りでなければうまく検索できません
NetTopologySuiteを使用し、座標を左回り(時計回り)に修正する方法です

SQL

geography型のlocationを持つ、customersテーブルを空間検索するとします
下記例は左回りの座標でポリゴンを作成しているので正常に検索できます

SELECT
  *
FROM
  customers
WHERE
  location.STIntersects(geography::STGeomFromText('POLYGON((139.781225 35.686380, 139.782368 35.683731,  139.777267 35.683319, 139.781225 35.686380))', 4326)) = 1

下記は右回りの座標でポリゴンを作成しています
エラーにはなりませんが、空間検索ができません

SELECT
  *
FROM
  customers
WHERE
  location.STIntersects(geography::STGeomFromText('POLYGON((139.781225 35.686380, 139.777267 35.683319, 139.782368 35.683731, 139.781225 35.686380))', 4326)) = 1

NetTopologySuite.Geometries.Polygonを使う

nugetでNetTopologySuiteをインストールします www.nuget.org

NetTopologySuite.Geometries.Polygonを使えば、右回り座標を左回りに修正することができます
polygon.Shell.IsCCWがfalseなら右回りなので、座標を逆転させると左回りになります

// 右回りの座標
var coordinates = new[]
{
    new Coordinate(139.781225, 35.686380),
    new Coordinate(139.777267, 35.683319),
    new Coordinate(139.782368, 235.683731),
    new Coordinate(139.781225, 35.686380),
};
var polygon = new Polygon(new LinearRing(coordinates)); 
if(!polygon.Shell.IsCCW){
    // 右回りなら座標を逆転させる
    coordinates = coordinates.Reverse().ToArray();
}

おわりに

地図上でユーザーがポリゴンを描画し、そのポリゴンで空間検索する際など座標の回り方向が不確かな場合、この方法を使えば座標を判定し左周りに修正することができます