使用SqlGeographyBuilder时,“指定的输入不表示有效的地理实例”异常

时间:2011-11-25 15:42:53

标签: sql-server-2008 geospatial kml geography sqlgeography

我编写了一个小应用程序,它从一系列KML文件中读取,然后使用以下代码将它们转换为Microsoft.SqlServer.Types.SqlGeography类型:

    private SqlGeography CreateGeographyFromKML( string kml, bool debug )
    {
        // use SqlGeographyBuilder to help create the SqlGeography type 
        var geographyBuilder = new SqlGeographyBuilder();

        // Get co-ordinates 
        var xml = XDocument.Parse(kml);
        var df = xml.Root.Name.Namespace;
        XElement coordinates = xml.Descendants(df + "coordinates").Single();

        // set the Spatial Reference Identifiers that will used to create the point 
        geographyBuilder.SetSrid(_srid);
        geographyBuilder.BeginGeography(OpenGisGeographyType.Polygon);

        var longLat = coordinates.Value.Split(' ').Select(c => new { Lat = Convert.ToDouble(c.Split(',')[1]), Long = Convert.ToDouble(c.Split(',')[0]) });

        Console.Write("Found {0} ", longLat.Count());

        foreach (var coord in longLat.Select((x, i) => new { Index = i, Value = x }))
        {
            if (coord.Index == 0)
            { // First point
                if ( debug ) Console.WriteLine("First point: {0},{1}", coord.Value.Lat, coord.Value.Long);
                geographyBuilder.BeginFigure(coord.Value.Lat, coord.Value.Long);
            }
            else
            { // Intermediate points
                if (debug) Console.WriteLine("Intermediate point: {0},{1}", coord.Value.Lat, coord.Value.Long);
                geographyBuilder.AddLine(coord.Value.Lat, coord.Value.Long);
            }

            if (coord.Index == longLat.Count() - 1 )
            { // Last point (Close polygon)     
                if (debug) Console.Write("Last point: ");

                // Check not already added
                if (longLat.Last().Lat == longLat.First().Lat && longLat.Last().Long == longLat.First().Long)
                {
                    if (debug) Console.Write("Already exists - not adding...");
                }
                else
                {
                    if (debug) Console.Write("{0},{1}", longLat.Last().Lat, longLat.Last().Long);
                    geographyBuilder.AddLine(longLat.Last().Lat, longLat.Last().Long);
                }

                geographyBuilder.EndFigure(); // End figure
            }
        }

        if (debug) Console.WriteLine();

        // close the figure and geography class 
        geographyBuilder.EndGeography();

        // get the geography builder to return the sqlgeography type 
        return geographyBuilder.ConstructedGeography;
    }

这个代码基本上从KML文件中检索Lat / Longs列表,然后遍历它们以创建一个多边形。

但是我导入的某些KML文件失败,但出现以下异常:

  

System.ArgumentException被捕获Message = 24200:指定的   输入不代表有效的地理实例。

这发生在以下行:return geographyBuilder.ConstructedGeography;

我找到了一些reference to this exception,但在我发现他们遇到并在SQL Server中遇到并处理此异常的情况下,而不是C#。

2 个答案:

答案 0 :(得分:7)

我有同样的错误,但结果却是多边形环定向问题。翻转坐标数组顺序的一个简单问题就解决了这个问题。

为了说明这一点,上述错误失败了:

 select geography::STGeomFromText ('Polygon  ( (10 10, 10 20, 20 20, 20 10, 10 10))',4326)

虽然这有效:

 select geography::STGeomFromText ('Polygon  ( (10 10, 20 10, 20 20, 10 20, 10 10))',4326)

请注意,我没有在一个点内翻转x,y对,我正在翻转整个点数组的顺序(例如{pt1,pt2,pt3,pt4,pt5}变为{pt5,pt4,pt3, pt2,pt1}

答案 1 :(得分:2)

我遇到了同样的问题,并使用一个名为Sql Server Spatial Tools(http://sqlspatialtools.codeplex.com)的项目解决了这个问题。

它有(以及其他有趣的东西)这两种方法:

  • MakeValidGeographyFromGeography
  • MakeValidGeographyFromText(接收WKT字符串)

他们修改了这些点,使其符合地理限制。

它确实非常,非常好,我已经使用了几个月而没有任何问题。