Исключение «Указанный ввод не представляет допустимый экземпляр geography» при использовании SqlGeographyBuilder

Я написал небольшое приложение, которое считывает ряд файлов 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, а затем перебирает их, чтобы создать многоугольник.

Однако некоторые файлы KML, которые я импортирую, завершаются ошибкой, за исключением следующего:

System.ArgumentException было перехвачено. Сообщение = 24200: указанные входные данные не представляют допустимый экземпляр geography.

Это происходит в следующей строке: return geographyBuilder.ConstructedGeography;

Я нашел несколько ссылка на это исключение, однако в тех случаях, которые я обнаружил, они обнаруживают и обрабатывают это исключение в SQL Server, а не С#.


person Peter Bridger    schedule 25.11.2011    source источник


Ответы (2)



У меня была такая же ошибка, но это оказалось проблемой ориентации полигонального кольца. Простое изменение порядка массивов координат решило проблему.

Чтобы проиллюстрировать, это не удается с приведенной выше ошибкой:

 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 }

person AnOttawan    schedule 17.04.2013
comment
Работал на меня. Я считаю, что порядок точек определяет, хотите ли вы внутреннюю или внешнюю часть многоугольника. Например. если вы рисуете небольшой квадрат, хотите ли вы, чтобы многоугольник был всем внутри этих координат, или это многоугольник, состоящий из всего, НО область, ограниченная этими координатами. - person dougajmcdonald; 27.10.2013