简体   繁体   中英

SQL Server 2014 find a point in polygon

I do not know why SQL does not detect this point in my polygon

select geography::STGeomFromText('POLYGON ((51.561283 -0.199251
,51.562136 -0.045443
,51.468985 -0.045443
,51.472407 -0.197878
,51.561283 -0.199251))', 4326).STIntersects(geography::Point(51.519425,-0.127029, 4326))

My polygon is valid in result of STIsValid() and also is in right direction which SSMS display the polygon:

多边形的 SSMS 结果

My point is also located in center of the polygon via Google Maps:

谷歌地图结果

Here is the tools I used to detect if my points are correct: https://www.doogal.co.uk/polylines.php

With these data in text input:

51.561283,-0.199251
51.562136,-0.045443
51.468985,-0.045443
51.472407,-0.197878
51.561283,-0.199251
51.519425,-0.127029

The strange thing is that when I change lat and long to geography::Point function the result is true.

select geography::STGeomFromText('POLYGON ((51.561283 -0.199251
,51.562136 -0.045443
,51.468985 -0.045443
,51.472407 -0.197878
,51.561283 -0.199251))', 4326).STIntersects(geography::Point(-0.127029,51.519425, 4326))

The Text string representations of Geometry/Geography always uses the XY convention for specifying coordinates. This means, when interpreted as geography, it defies the usual convention of putting Latitude first.

So you need to use Long Lat in specifying your POLYGON in a string.

You can see this in your SSMS output, where you can see that the polygon is located just south of the equator, somewhere ~51° East, and not somewhere in London.

You have to flip the values on the geography::Point since the first value is the longitude and the second value is the latitude:

The Point type for geography data type represents a single location where x and y represent longitude and latitude values respectively.

source: https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/bb964737(v=sql.105)

See the following comparison between using the Point data type directly or getting the Point object with geometry::STGeomFromText . The order of langitude and longitude is different .

-- get the Point from text using geography::STGeomFromText
SELECT geography::STGeomFromText('POINT(51.519425 -0.127029)', 4326).Lat  -- -0,127029
SELECT geography::STGeomFromText('POINT(51.519425 -0.127029)', 4326).Long -- 51,519425

-- get the Point directly using geography::Point
SELECT geography::Point(51.519425, -0.127029, 4326).Lat   -- 51,519425
SELECT geography::Point(51.519425, -0.127029, 4326).Long  -- -0,127029

So you have two possibilities to solve this:

1. flip the values of the Point :

SELECT geography::STGeomFromText('POLYGON ((51.561283 -0.199251
  ,51.562136 -0.045443
  ,51.468985 -0.045443
  ,51.472407 -0.197878
  ,51.561283 -0.199251))', 4326
).STIntersects(geography::Point(-0.127029, 51.519425, 4326))

2. specify the Point using text:

SELECT geography::STGeomFromText('POLYGON ((51.561283 -0.199251
  ,51.562136 -0.045443
  ,51.468985 -0.045443
  ,51.472407 -0.197878
  ,51.561283 -0.199251))', 4326
).STIntersects(geography::STGeomFromText('POINT(51.519425 -0.127029)', 4326))

Since you are working with geographical data, make sure the polygon matches the correct area to get the correct data. You can use the following polygon to match the expected area:

SELECT geography::STGeomFromText('POLYGON((
  -0.199251 51.561283, 
  -0.197878 51.472407,
  -0.045443 51.468985,
  -0.045443 51.562136,
  -0.199251 51.561283))', 4326
)

Now you can use the following solution to check if the Point is inside the polygon:

SELECT geography::STGeomFromText('POLYGON((
  -0.199251 51.561283, 
  -0.197878 51.472407,
  -0.045443 51.468985,
  -0.045443 51.562136,
  -0.199251 51.561283))', 4326
).STIntersects(geography::Point(51.519425, -0.127029, 4326))

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.

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