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.
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. 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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.