问题
A little about the application;
The application allows the user to draw and save polygons onto bing maps WPF api.
The piece of code we are interested in is finding weather a point is whithin the polygon or not. The following function simply loops through the LocationCollection
of the polygon on the bing map, and creates a SqlGeography object (OpenGisGeographyType.Polygon)
which is an instance of a polygon.
We then convert the mouse click into SqlGeography object (OpenGisGeographyType.Point)
by latitude and longitude and use the SqlGeography.STIntersection to find if our point lies within the polygon.
As seen in the picture, even when the point is outside the polygon, SqlGeography.STIntersection still returns a point of intersection. (You can tell this in the picture as I set a label to "Within Delivery Area" or "Customer our of Area" depending on what polygonSearch() function returned.
The right example in the picture has the expected results when a location is tested within the polygon.
The left example in the picture contains the unexpected results - Which indicates that a point is within a polygon , when it clearly is not!
NOTES:
- I Use SqlGeography (myShape) to put the shapes on the map, so I know the shape is being constructed with proper verticies.
- I use SqlGeography (myPoint) to put the pin on the map, so I know the
pin is being tested at the correct verticies.
- THIS ONLY FAILS ON LARGE POLYGONS
Below I give the peice of code which creates the polygon in memory, as well as converts the mouse click event to lat, longitude. ( I have included the polygon verticies in comments so that this can be looked at without the need of the bing api, just replace the for loop with the comments above it ) Although, you will need to reference Microsoft.SqlServer.Types.dl
l to create the SqlGeography objects. Its free with SQL Express 2008 , and can be found in C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies
public bool polygonSearch2(LocationCollection points, double lat, double lon)
{
SqlGeography myShape = new SqlGeography();
SqlGeographyBuilder shapeBuilder = new SqlGeographyBuilder();
// here are the verticies for the location collection if you want to hard code and try
//shapeBuilder.BeginFigure(47.4275329011347, -86.8136038458706);
//shapeBuilder.AddLine(36.5102408627967, -86.9680936860962);
//shapeBuilder.AddLine(37.4928909385966, -80.2884061860962);
//shapeBuilder.AddLine(38.7375329179818, -75.7180936860962);
//shapeBuilder.AddLine(48.0932596736361, -83.7161405610962);
//shapeBuilder.AddLine(47.4275329011347, -86.8136038458706);
//shapeBuilder.EndFigure();
//shapeBuilder.EndGeography();
// Here I just loop through my points collection backwards to create the polygon in the SqlGeography object
for (int i = points.Count - 1; i >= 0; i--)
{
if (i == 0)
{
shapeBuilder.AddLine(points[i].Latitude, points[i].Longitude);
shapeBuilder.EndFigure();
shapeBuilder.EndGeography();
continue;
}
if (i == points.Count - 1)
{
shapeBuilder.SetSrid(4326);
shapeBuilder.BeginGeography(OpenGisGeographyType.Polygon);
shapeBuilder.BeginFigure(points[i].Latitude, points[i].Longitude);
continue;
}
else
{
shapeBuilder.AddLine(points[i].Latitude, points[i].Longitude);
}
}
myShape = shapeBuilder.ConstructedGeography;
// Here I am creating a SqlGeography object as a point (user mouse click)
SqlGeography myPoint = new SqlGeography();
SqlGeographyBuilder pointBuilder = new SqlGeographyBuilder();
pointBuilder.SetSrid(4326);
pointBuilder.BeginGeography(OpenGisGeographyType.Point);
// Should pass, which it does
// Lat: lat = 43.682110574649791 , Lon: -79.79005605528323
// Should fail, but it intersects??
// Lat: 43.682108149690094 , Lon: -79.790037277494889
pointBuilder.BeginFigure(lat, lon);
pointBuilder.EndFigure();
pointBuilder.EndGeography();
myPoint = pointBuilder.ConstructedGeography;
SqlGeography result = myShape.STIntersection(myPoint);
if (result.Lat.IsNull)
return false;
else
return true;
}
Any help at all is much appreciated, I am starting to drive my boss nuts with this problem >.<
Could this have anything to do with the SRID?
回答1:
I fixed this by converting all my polygon lat / long to a Point
object on the screen using LocationToViewPortpoint
function, as well as the point I'm testing for intersection, and use the X and Y values instead of lat / long in my STIntersects
.
来源:https://stackoverflow.com/questions/17458117/sqlgeography-stintersection-returns-even-when-i-know-there-is-no-intersection