程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> 利用GDAL/OGR導空間數據到SQLServer2008

利用GDAL/OGR導空間數據到SQLServer2008

編輯:關於SqlServer

       網上有個工具可以做到,可惜導入的中文是亂碼,搜索了一圈好像沒什麼解決辦法,於是想自己搞一個,哎,一搞才知道麻煩重重啊~

      首先查資料,了解了一下SQLServer中的空間數據分兩種,Geometry和Geography,一種是平面一種球面,比如在做距離計算時結果是不一樣的啊

      所以我必須先Geography球面坐標系,但這玩意兒有限制啊,比如多邊形外環方向必須是逆時針,內環方向必須是順時針,不能超過一個半球等等

      不管了先做,加載GDAL和ORG,打開MapInfo圖層,遍歷之,取字段正常,取幾何個數正確,下一步將幾何數據導出,方法很多,支持OpenGIS的系統

      都支持WKT和WKB,為了方便選ExportToWkt,然後生成 INSERT語句,差不多了,執行之,問題來了:Sqlserver報錯,說什麼

      消息 6522,級別 16,狀態 1,第 1 行

      在執行用戶定義例程或聚合 "geography" 期間出現 .NET Framework 錯誤:

      Microsoft.SqlServer.Types.GLArgumentException: 24205: 因為指定的輸入超過了一個半球,所以它不代表有效的地理實例。每個地理實例必須能容納在一個半球內。此錯誤的常見原因是某個多邊形的環方向錯誤。

      Microsoft.SqlServer.Types.GLArgumentException:

      在 Microsoft.SqlServer.Types.GLNativeMethods.ThrowExceptionForHr(GL_HResult errorCode)

      在 Microsoft.SqlServer.Types.GLNativeMethods.GeodeticIsValid(GeoData g)

      在 Microsoft.SqlServer.Types.SqlGeography.IsValidExpensive()

      在 Microsoft.SqlServer.Types.SqlGeography.ConstructGeographyFromUserInput(GeoData g, Int32 srid)

      在 Microsoft.SqlServer.Types.SqlGeography.GeographyFromText(OpenGisType type, SqlChars taggedText, Int32 srid)

      在 Microsoft.SqlServer.Types.SqlGeography.STGeomFromText(SqlChars geometryTaggedText, Int32 srid)

      將geography::STGeomFromText換成geometry::STGeomFromText,沒問題可以正常生成幾何,哎,說明真的環方向有問題,改吧,於是有了以後代碼

      using System;

      using System.Collections.Generic;

      using System.Text.RegularExpressions;

      namespace SqlSpatialTools

      {

      public class Point

      {

      public double X { get; set; }

      public double Y { get; set; }

      public Point(double x, double y)

      {

      X = x;

      Y = y;

      }

      public static Point Parse(string pt)

      {

      var p = pt.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);

      return p.Length == 2 ? new Point(Convert.ToDouble(p[0]), Convert.ToDouble(p[1])) : null;

      }

      public override string ToString()

      {

      return string.Format("{0:F8} {1:F8}", X, Y);

      }

      }

      public static class Wkt

      {

      ///

      /// 判斷環的是否為順時針方向

      ///

      ///

      /// True順時針,False逆時針

      private static bool IsRingClockwise(IList pp)

      {

      double t = 0;

      for (var i = 1; i < pp.Count; i++)

      t += pp[i - 1].X * pp[i].Y - pp[i].X * pp[i - 1].Y;

      t += pp[pp.Count - 1].X * pp[0].Y - pp[0].X * pp[pp.Count - 1].Y;

      return t < 0;

      }

      //判斷是否是環

      public static bool IsRing(IList pp)

      {

      var t = pp.Count - 1;

      return (t > 2 && pp[0].X == pp[t].X && pp[0].Y == pp[t].Y);

      }

      public static string[] Resverse(List pts, bool resverse)

      {

      var sl = new List();

      foreach (var pt in pts)

      {

      sl.Add(pt.ToString());

      }

      if (resverse)

      sl.Reverse();

      return sl.ToArray();

      }

      public static string ReverseWKT(string wkt)

      {

      if (!Regex.IsMatch(wkt, "POLYGON"))

      return wkt;

      var retwkt = wkt;

      var ms = Regex.Matches(retwkt, @"(d+.*?d+)");

      //按geography規則,多邊形外環應該逆時針,內環順時針

      //POLYGON(())中第一個()中的是外形,其它的是內環

      //LINESTRING()直接判斷是否為逆時針即可(判斷一下需要需要逆時針)

      if (ms.Count > 0)

      {

      for (var i = ms.Count - 1; i >= 0; i--)

      {

      var m = ms[i];

      var s = m.ToString().TrimStart(new[] { '(' }).TrimEnd(new[] { ')' });

      var pa = s.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);

      var ls = new List();

      foreach (var p in pa)

      {

      var pt = Point.Parse(p);

      if (pt != null)

      ls.Add(pt);

      }

      //TODO 多邊形有內環的不能逆轉,要順時針

      if (IsRing(ls))

      {

      var rs = string.Join(",", Resverse(ls, IsRingClockwise(ls)));//如果是順時針則逆轉

      retwkt = retwkt.Remove(m.Index, m.Length).Insert(m.Index, string.Format("({0})", rs));

      }

      }

      return retwkt;

      }

      return wkt;

      }

      }

      }

      以上用的.net 2.0所以string[].ToArray這種都不支持,雖然MutiPolygon和GeomertyCollection還是搞不定, 不過一般Polygon是沒問題的,再次測試了一個MapInfo Table

      (中國面省界)基本OK,再導面縣界,結果一些搞不定,導出WKT用SELECT在SQLER裡試了一下,真不行啊,查了一下用網上工具導的記錄,WKT是GEOMETRYCOLLECTION,而我用GDAL/OGR查出來說是POLYGON類型

    利用GDAL/OGR導空間數據到SQLServer2008 三聯

      這明明是一條線和一個多邊形組成的啊,GDAL/OGR居然說是POLYGON,試了GDAL1.6、GDAL1.7,應該是OGR的問題,不搞了,累覺不愛啊

      總之導ESRI Shape用Geometry模式還是可以的,中文問題解決了,配和SQLServer的Update語句基本能解決問題

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved