1

In a varchar column verticies, I store this JSON:

[{"lng":-82.82312393275788,"lat":27.982508364801642},
 {"lng":-82.8065586098819,"lat":27.984479050536944},
 {"lng":-82.808017731586,"lat":27.9704560800863},
 {"lng":-82.82166481105378,"lat":27.975004270258353},
 {"lng":-82.8230381020694,"lat":27.980537643052056},
 {"lng":-82.82312393275788,"lat":27.982508364801642}]

This was saved as a string from a Google maps polygon. My intent is to save it as a geography data type, and store it into the [geo] column.

My problem is when I'm trying to use:

geography::STGeomFromText('POLYGON(' + replace(replace(replace(replace(replace(vertices,'{"lng":',''),',"lat":',' '),'[','('),']',')'),'}','') + ')', 4326)

I get the geography error:

24205: The specified input does not represent a valid geography instance because it exceeds a single hemisphere. Each geography instance must fit inside a single hemisphere. A common reason for this error is that a polygon has the wrong ring orientation. To create a larger than hemisphere geography instance, upgrade the version of SQL Server and change the database compatibility level to at least 110.

Looking at other stack overflow answers I'm told this is a ring orientation problem, and I need to reverse the Json. From what I understand, the first and last points are the start/stop points and they are good, and I need to reverse the order of all the other points.

My question: Is there any way to do this using a function in SQL Server?

shA.t
  • 16,580
  • 5
  • 54
  • 111
arcee123
  • 101
  • 9
  • 41
  • 118
  • Which version of SQL Server are you using? – shA.t Sep 06 '17 at 04:43
  • SQL Server 2016 – arcee123 Sep 06 '17 at 14:51
  • SQL Server 2016 – arcee123 Sep 06 '17 at 14:54
  • The "exceeds a single hemisphere" error went away in (IIRC) SQL 2012. The JSON still doesn't represent the thing you're interested in (i.e. it's very likely the whole world with a thing-sized hole in it), but that's fixable with a call to the `.ReorientObject()` method call. But back to the underlying issue, I think you're on SQL 2008 (or in a database that has its compatibility mode set as such). – Ben Thul Sep 06 '17 at 15:17
  • ok. let me double check the version. but do I put the `.ReorientObject()` at the end of the `geography::STGeomFromText()` call? – arcee123 Sep 06 '17 at 16:12
  • @arcee123: if you're able to, yes. The abbreviated version is `declare @g = geography::STGeomFromText().ReorientObject();`. But I don' think you're going to get past the hemisphere problem. – Ben Thul Sep 07 '17 at 03:41

1 Answers1

0

If you are using SQL Server 2014+ and geometry type; your code should work perfectly:

declare @g geometry, @json nvarchar(400) = '[{"lng":-82.82312393275788,"lat":27.982508364801642},
 {"lng":-82.8065586098819,"lat":27.984479050536944},
 {"lng":-82.808017731586,"lat":27.9704560800863},
 {"lng":-82.82166481105378,"lat":27.975004270258353},
 {"lng":-82.8230381020694,"lat":27.980537643052056},
 {"lng":-82.82312393275788,"lat":27.982508364801642}]';

 set @g = geometry::STPolyFromText('POLYGON(' + replace(replace(replace(replace(replace(@json,'{"lng":',''),',"lat":',' '),'[','('),']',')'),'}','') + ')', 4326);  
SELECT @g.ToString(); 

[SQL Fiddle Demo]


But if your question is about creating a Scalar-Function, the code can be something like this:

create function dbo.GetPolygon 
(
    @inputJson nvarchar(max),
    @sid int
)
returns geometry
as
begin
    declare @g geometry, @json nvarchar(max) = @inputJson;
    
    set @g = geometry::STPolyFromText('POLYGON(' + replace(replace(replace(replace(replace(@json,'{"lng":',''),',"lat":',' '),'[','('),']',')'),'}','') + ')', @sid);  

    return @g;
end
go

Then use it just like this:

select dbo.GetPolygon(@json, 4326).ToString();

But if you are using geography type: you can't draw a polygon simply, it should covers some other conditions also:

Note: The geography type is a little bit more restrictive than geometry. It can't cross different hemispheres and the outer ring must be drawn counter-clockwise.[1]

GEOGRAPHY is for terrestrial spatial data (that is, data on the curved surface of the Earth)[2]

And for more Geographical info check this: What are the pros and cons of PostGIS geography and geometry types?

SELECT @g.ToString(), @g.STIsValid(); 
-- To test that geography is valid

BTW; This code will also work fine and is valid: [SQL Fiddle Demo]

Community
  • 1
  • 1
shA.t
  • 16,580
  • 5
  • 54
  • 111
  • thanks much, but I need geography, not geometry. Thanks! – arcee123 Sep 06 '17 at 12:20
  • ok. the problem here is I can't tell the difference between what you are saying and what I put in. This is truly the definition of insanity. why would mine cause the error, and yours don't. I didn't leave anything out. btw, SQL Server 2016. Thanks. – arcee123 Sep 06 '17 at 14:53
  • OK!, I'll check it in a local SQL Server 2016 soon -HTH ;). – shA.t Sep 06 '17 at 14:55