こんにちは。beaglesoftの真鍋です。
SQL ServerでGeographyのポリゴンを扱う場合には右巻/左巻で世界が一変するわけで、結構重要です。普通はSQL Serverで以下のクエリを発行すればよしなに行ってくれます。
-- geomがポリゴンを保存しているGeeography型の列 -- 巻きが逆の場合に補正します update `テーブル名` set [geom] = [geom].MakeValid().ReorientObject() where [geom].MakeValid().EnvelopeAngle() > 90 -- 有効なインスタンスに補正します update `テーブル名` set [geom] = [geom].MakeValid() where [geom].STIsValid() = 0
ただ、EntityFrameworkを使っているとこの処理だけSQLを実行するのも手間です。そこで、DbGeography
型で対応できないかと調べたのですが、現在のところDbGeometory
型に変換してからでないと処理ができないことがわかりました。
うーんと思っていたところ、どうやら以下の方法で同じことができることがわかりました。
/// <summary> /// 経度 緯度,経度 緯度...の文字列からポリゴンを生成します。 /// </summary> /// <param name="polygonText">経度 緯度,経度 緯度...の文字列</param> /// <returns>DbGeoGraphyのインスタンス</returns> public static DbGeography ConvertToPolygon(string polygonText) { if (string.IsNullOrEmpty(polygonText)) { throw new ArgumentNullException(); } var sqlGeography = SqlGeography.STGeomFromText(new SqlChars($"POLYGON(({polygonText}))"), 4326).MakeValid(); if (sqlGeography.EnvelopeAngle() > 90) { sqlGeography = sqlGeography.ReorientObject(); } return DbSpatialServices.Default.GeographyFromProviderValue(sqlGeography); }
行っていることはSQLと同じですので省略しますが、これは便利です。SqlGeography
はMicrosoft.SqlServer.Types 名前空間に定義されているクラスで、DbGeography
よりも多くの処理が定義されているようです。もともとWKTを介してデータの変換は DbGeometory⇔DbGeography と行えるのですが、こっちはより便利ですね。