0

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. Using the same data in QGIS 2.2.0, I clearly see the point is inside the polygon (screenshot).

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.

enter image description here

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
Gup3rSuR4c
  • 9,145
  • 10
  • 68
  • 126

2 Answers2

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 Philips
  • 53,428
  • 11
  • 128
  • 150
0

@Erik's answer is correct in that SQL Server was excluding the area I was specifying in the polygon. 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

Community
  • 1
  • 1
Gup3rSuR4c
  • 9,145
  • 10
  • 68
  • 126