问题
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