简体   繁体   English

检查点是否在多边形内不起作用

[英]Checking if a Point is inside a Polygon not working

Using SQL Server 2012 the following query keeps telling me that the point I'm looking for is not inside the polygon I'm using, when I know it is. 使用SQL Server 2012,以下查询不断告诉我,当我知道要查找的点不在所使用的多边形内时。 Using the same data in QGIS 2.2.0, I clearly see the point is inside the polygon (screenshot). 在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

What do I need to do make the query tell me the point is in the polygon? 我需要做些什么使查询告诉我点在多边形中? I've seen some search results talk about "direction", but I have no idea how to specify it. 我已经看到一些搜索结果谈论“方向”,但是我不知道如何指定它。 The coordinates are captured from the Google Maps JavaScript API and persisted to the database using Entity Framework 6.1. 坐标是从Google Maps JavaScript API捕获的,并使用Entity Framework 6.1保留到数据库中。

在此处输入图片说明

I think you have a Ring Orientation problem . 我认为您遇到环取向问题 You need to reverse the order of the polygon: 您需要颠倒多边形的顺序:

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

@Erik's answer is correct in that SQL Server was excluding the area I was specifying in the polygon. @Erik的答案是正确的,因为SQL Server排除了我在多边形中指定的区域。 Inverting the polygon fixed the issue. 反转多边形可解决此问题。 His code is correct, but I had to make a modification to fit my usage, so here's my code for anyone who cares: 他的代码是正确的,但是我必须进行修改以适合我的用法,因此这是我在乎的代码:

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

I was getting an exception when trying to return from @Erik's code, so I used the code from the answer here: Entity Framework: SqlGeography vs DbGeography 尝试从@Erik的代码返回时遇到异常,因此我在此处使用了答案中的代码: 实体框架:SqlGeography vs DbGeography

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM