'The specified input does not represent a valid geography instance' exception when using SqlGeographyBuilder

心已入冬 提交于 2019-12-12 07:20:02

问题


I've written a small application that reads in from a series of KML files and then converts them into the Microsoft.SqlServer.Types.SqlGeography type using the following code:

    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;
    }

Basically this code retrieves the list of Lat/Longs from the KML file, then loops through them to create a polygon.

However some of the KML files I'm importing fail with the following exception:

System.ArgumentException was caught Message=24200: The specified input does not represent a valid geography instance.

This happens on the following line: return geographyBuilder.ConstructedGeography;

I've found some reference to this exception, however in the cases I've found they're encountering and dealing with this exception within SQL Server, rather than C#.


回答1:


I've had the same problem and solved it using a project called Sql Server Spatial Tools (http://sqlspatialtools.codeplex.com).

It has (among other interesting stuff) these two methods:

  • MakeValidGeographyFromGeography
  • MakeValidGeographyFromText (which receives a WKT string)

They modify the points so that it conforms to the geography restrictions.

It works really, really well, and I've used it for several months now without any problem.




回答2:


I had this same error, but it turned out to be a polygon ring orientation problem. A simple matter of flipping the order of the coordinate arrays solved the problem.

To illustrate, this fails with the above error:

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

whereas this works:

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

Note that I'm not flipping the x,y pairs within a point, I am flipping the order of the entire point array (e.g. {pt1, pt2, pt3, pt4, pt5} becomes {pt5, pt4, pt3, pt2, pt1}



来源:https://stackoverflow.com/questions/8271349/the-specified-input-does-not-represent-a-valid-geography-instance-exception-wh

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!