Home > Blockchain >  Sql DbGeography Issues
Sql DbGeography Issues

Time:09-10

Please help me

I have the following sql code

DECLARE  @polygon geography
SET @polygon = 'POLYGON((-73.6965649914466 41.4459906683457,-73.6688781089674 41.4399017487713,-73.6969460096452 41.4295218755254,-73.6965649914466 41.4459906683457))'

SELECT @polygon

It compiles but when I look at the spatial results tab the polygon is not correct.

enter image description here

Can anybody help me to understand why is that?


EDIT

If i use ReorientObject then it works, but, when i should used it?

SELECT @polygon.ReorientObject()

enter image description here

CodePudding user response:

The points are around the wrong way, this is one of those Left Hand rule issues.

Ultimately this occurs when the Application Interface is using logic or a library that uses the Right Hand rule. Some toolkits have a flag so you can reverse this, if you are manually constructing the SQL query to write to the database, you should update that logic to inject the points in the correct sequence.

In this case the middle points in your polygon need to be reversed:

DECLARE  @polygon geography
-- First attempt
SET @polygon = 'POLYGON((-73.6965649914466 41.4459906683457,-73.6688781089674 41.4399017487713,-73.6969460096452 41.4295218755254,-73.6965649914466 41.4459906683457))'
-- Fixed points
SET @polygon = 'POLYGON((-73.6965649914466 41.4459906683457,-73.6969460096452 41.4295218755254,-73.6688781089674 41.4399017487713,-73.6965649914466 41.4459906683457))'

SELECT @polygon

enter image description here

Unfortunately, in this case MakeValid() will not work, But when we know this is the problem we can use ReorientObject() to reverse the points:

DECLARE  @polygon geography
SET @polygon = 'POLYGON((-73.6965649914466 41.4459906683457,-73.6688781089674 41.4399017487713,-73.6969460096452 41.4295218755254,-73.6965649914466 41.4459906683457))'
SELECT @polygon.ReorientObject()

This is a good reference for these types of issues: Inverted Polygons? How to Troubleshoot SQL Server's Left Hand Rule


How to know?

A simple way to determine if the orientation is correct is to use the STIsValid() function. If the polygon is not valid, then we can use .MakeValid() to try to fix the points.

In cases like this where the polygon is actually valid, we can compare the area to the inverse area and pick the smaller of the two:

DECLARE  @polygon geography
SET @polygon = 'POLYGON((-73.6965649914466 41.4459906683457,-73.6688781089674 41.4399017487713,-73.6969460096452 41.4295218755254,-73.6965649914466 41.4459906683457))'
SELECT @polygon.STIsValid() AS STIsValid, @polygon.STArea() AS STArea
UNION ALL
SELECT @polygon.ReorientObject().STIsValid(), @polygon.ReorientObject().STArea()
STIsValid STArea
1 510065619584113
1 2126883.4132309

So we could use SQL logic like this:

DECLARE  @polygon geography
SET @polygon = 'POLYGON((-73.6965649914466 41.4459906683457,-73.6688781089674 41.4399017487713,-73.6969460096452 41.4295218755254,-73.6965649914466 41.4459906683457))'

DECLARE @Area real, @InvertedArea real;
SELECT @Area = @polygon.STArea()
     , @InvertedArea = @polygon.ReorientObject().STArea();
IF (@InvertedArea < @Area)
BEGIN
    SELECT @polygon = @polygon.ReorientObject();
END

SELECT @polygon;

It is best to validate the data as part of the write operation instead of on every read. If you have a Service Orientated Architecture, then the obvious place would be in the API layer, however you could even use an after or instead of trigger to _correct the data if you do not have control over the code.

If you post the SQL or application code that is performing the write, then I can provide a pragmatic solution for you, but hopefully this information will be enough to get you on your way.

  • Related