Проверка того, находится ли точка внутри многоугольника, не работает

Используя SQL Server 2012, следующий запрос продолжает говорить мне, что точка, которую я ищу, не находится внутри многоугольника, который я использую, хотя я знаю, что это так. Используя те же данные в QGIS 2.2.0, я ясно вижу, что точка находится внутри многоугольника (скриншот).

DECLARE @polygon GEOGRAPHY = GEOGRAPHY::STPolyFromText('POLYGON ((-111.0498046875 33.966142265597391, -110.9124755859375 33.472690192666633, -110.94268798828125 32.983324091837417, -111.7364501953125 32.680996432581921, -112.587890625 32.731840896865656, -113.0657958984375 33.307577130152978, -112.9010009765625 33.811102288647007, -112.32147216796875 34.1890858311723, -111.4453125 34.129994745824717, -111.0498046875 33.966142265597391))', 4326);
DECLARE @point GEOGRAPHY = GEOGRAPHY::STPointFromText('POINT (-112.0685317 33.4491407)', 4326);

SELECT  @point.STIsValid() AS [PointIsValid], --True
        @polygon.STIsValid() AS [PolygonIsValid], --True
        @point.STWithin(@polygon) AS [PointWithinPolygon], --False
        @point.STIntersects(@polygon) AS [PointIntersectsPolygon], --False
        @polygon.STContains(@point) AS [PolygonContainsPoint]; --False

Что мне нужно сделать, чтобы запрос сказал мне, что точка находится в многоугольнике? Я видел, что некоторые результаты поиска говорят о «направлении», но я понятия не имею, как его указать. Координаты получаются из API Google Maps JavaScript и сохраняются в базе данных с помощью Entity Framework 6.1.

введите здесь описание изображения


person Gup3rSuR4c    schedule 18.05.2014    source источник


Ответы (2)


Я думаю, у вас есть Проблема ориентации кольца. Вам нужно изменить порядок многоугольника:

using Microsoft.SqlServer.Types;
using System;
using System.Collections.Generic;
using System.Data.Spatial;
using System.Data.SqlTypes;

namespace SomeNamespace
{
  public static class DbGeographyHelper
  {
    // 4326 is most common coordinate system used by GPS/Maps
    // 4326 format puts LONGITUDE first then LATITUDE
    private static int _coordinateSystem = 4326;

    public static DbGeography CreatePolygon(string wktString)
    {
      // create polygon is same order as wktString
      var sqlGeography = SqlGeography
        .STGeomFromText(new SqlChars(wktString), _coordinateSystem)
        .MakeValid();

      // create the polygon in the reverse order
      var invertedSqlGeography = sqlGeography.ReorientObject();

      // which ever one is big is probably not the one you want
      if (sqlGeography.STArea() > invertedSqlGeography.STArea())
      {
        sqlGeography = invertedSqlGeography;
      }

      return DbSpatialServices.Default.GeographyFromProviderValue(sqlGeography);
    }
  }
}
person Erik Philips    schedule 18.05.2014

@ Ответ Эрика верен в том, что SQL Server исключал область, которую я указывал в многоугольнике. Инвертирование многоугольника решило проблему. Его код правильный, но мне пришлось внести изменения, чтобы он соответствовал моему использованию, так что вот мой код для всех, кому небезразлично:

public static class DbGeographyExtensions {
    public static DbGeography PolygonFromGoogleMapsText(
        string wellKnownText,
        int coordinateSystemId) {
        SqlGeography geography = SqlGeography.STGeomFromText(new SqlChars(wellKnownText), coordinateSystemId).MakeValid();
        SqlGeography invertedGeography = geography.ReorientObject();

        if (geography.STArea() > invertedGeography.STArea()) {
            geography = invertedGeography;
        }

        return DbGeography.FromText(geography.ToString(), coordinateSystemId);
    }
}

Я получал исключение при попытке вернуться из кода @Erik, поэтому я использовал код из ответа здесь: Entity Framework: SqlGeography против DbGeography

person Gup3rSuR4c    schedule 18.05.2014