Spatial querying, converting metres to radians? - sql-server

I have geographic data that was loaded into the geography datatype. For very specific purposes, I now need to have store this as a geometry. However, I need to perform a query like this.
DECLARE #radius INT -- e.g. 3000 metres
DECLARE #geo geometry -- my starting shape
SET #geo = #geo.STBuffer(#radius) -- this obviously doesnt work..
SELECT Geo FROM GeometryTable
WHERE Geo.STWithin (#geo) = 1

Meters are a measure of length while radians are a measure of an angle so i don't think you can.
Are you trying to calculate an arc length?
Take a look at the links below:
http://wiki.answers.com/Q/How_do_you_convert_radians_to_meters
http://www.regentsprep.org/Regents/math/algtrig/ATM1/arclengthlesson.htm

This trick might work, if someone can validate this technique or provide a better alternative then they'll get the accepted answer.
Basically, I am thinking I can use the STBuffer of a geography which will apply the correct radius in metres around my geographical shape and then I convert back to a geometry. As the shapes were loaded originally as geography all the points are the same. This shape-flip should give me a resulting geometry with a pretty accurate buffer around it.
DECLARE #radius INT -- e.g. 3000 metres
DECLARE #geo geometry -- my starting shape
SET #geo = GEOMETRY::STGeomFromWKB(GEOGRAPHY::STGeomFromWKB(#geo.STAsBinary(),
4326).STBuffer(#radius).STAsBinary(),4326)
SELECT Geo FROM GeometryTable
WHERE Geo.STWithin (#geo) = 1

Related

determine if geography point falls on geography polygon line

I understand that you cannot check if a geography point touches for example a geography polygon (see here) using something like this, which is possible in the geometry world:
WHERE A.Geo.STTouches(#s0) = 1
Is there a way to achieve this in the geography world? I guess a solution would be to transform the geography polygon + geography point into their geometry equivalents?
PS:
This should also work with complex polygons - such as this one with holes:
POLYGON ((99.999999999999986 5.3926387744713564E-14, 101.00000000000001 5.3926387744713564E-14, 100.99999999999987 1.0000000000000155, 100.00000000000013 1.0000000000000155, 99.999999999999986 5.3926387744713564E-14), (100.20000000000003 0.19999999999992918, 100.19999999999989 0.79999999999990257, 100.80000000000011 0.79999999999990234, 100.79999999999998 0.19999999999992912, 100.20000000000003 0.19999999999992918))
I'm assuming that my statement of your wanting to track whether or not the given point intersects with the boundary of your polygon. The below should do the trick:
SELECT #point.STIntersects(#polygon.RingN(1));
In essence, you're getting the outer boundary with RingN(1) (I'm making an assumption that this is a simple polygon, so the first ring should be the outer boundary) and then checking whether that intersects with the point you care about.
Edit: If you want to check if a given point lies on the boundary of any ring in the given polygon, something like this should do the trick:
select n.n as [IntersectedRingNumber],
#polygon.RingN(n) as [IntersectedRing]
from dbo.Numbers as n
where n <= #polygon.NumRings()
and #point.STIntersects(#polygon.RingN(n)) = 1;

Mix and match spatial-reference systems?

Assuming that I have a table of postal codes, with a Geography column that was populated with Global - WGS84 (SRID 4326), can I accurately compare them (using STDistance) with a Geography point that has been populated with North America – NAD83 (SRID 4269)?
In short, No.
SQL Server requires for spatial functions that all items' have the same SRID. This is because the SRID provides other information in the background used to calculate distances and such on an ellipsoidal model.
That said, you could have a second column which is calculated to have a common SRID and use that for distance calculations. It's as simple as:
Declare #commonSrid geography = geography::STGeomFromWKB(<existing column>.STAsBinary(), 4326);
In doing this, you must be sure that all SRIDs are based from latitude and longitude decimal coordinates, and not for example grid references. Also because you're not doing a proper conversion between them, you may find distances are not 100% accurate - but they will be very very close.

SQL Server flat world map on geometry column

I need help regarding geometry and geography columns. Well not much about geography as that works fine. What im trying to achieve is to represent world map on geometry column instead of geography. Well not really represent itself but to be able to measure distance between two coordinates on flat map (as i know geography makes curves as earth itself is curved of course). Is there any way to do this?
I was reading a bit but nothing has make any difference to it if i do:
DECLARE #g geometry;
SET #g = geometry::STGeomFromText('LINESTRING(-122.360 47.656, -122.343 47.656)', 0);
SELECT #g.STLength();
I get distance 0.016 while for geography its 1277... changing srid to 4326 doesn't change it also.. any help?
The geometry datatype is for Cartesian geometry. The line that you've defined is from point (x1, y1) = (-122.360, 47.656) to (x2, y2) = (-122.343, 47.656). The distance between these is sqrt( (x2-x1)^2 + (y2-y1)^2 ).
With the geography datatype, the points are given as degrees around the equator and degrees of inclination from the equator. The calculation of distance between two points so defined is given by the Haversine formula.
As you can see, the two are vastly different. But the real question is: what are you really trying to accomplish? If your points represent points on a globe, why are you using the geometry datatype at all?

STIntersects in the wrong lat/lng

I'm facing a problem regarding the order of the lat/lng in the following query, it works if i put the coordinates in the wrong order (lng,lat). However geography::Point should take the lat then lng, this is very weird. I tried checking the lat/lng on google maps, and its in the correct position, the polygone in a clockwise order, everything looks fine, the query is as follows:
DECLARE #branch_id int = 0;
DECLARE #point geography;
SET #point = geography::Point(31.3353608924066, 30.0798141318826, 4326);
SELECT B.ID, B.DeliveryZone, A.LatLong
FROM [dbo].[Branches] AS B
INNER JOIN [dbo].Addresses AS A ON B.AddressID = A.ID
WHERE B.ServiceProviderID = 2 AND
B.Deleted = 0 AND
B.DeliveryZone.STBuffer(1000).STIntersects( #point ) > 0 ;
The SQL Server documentation for Point is inconsistent. It says:
Lat - Is a float expression representing the x-coordinate of the Point being generated.
Latitude is generally used as a y-coordinate, that is, how far north or south you are from the equator.
The same inconsistency is given for Long:
Long - Is a float expression representing the y-coordinate of the Point being generated.
Of course, longitude is usually intepreted as an x-coordinate, that is, how far east or west you are from the prime meridian.
Also, lat and lng aren't used by all SRIDs, just ones that define unprojected coordinate systems like 4326, so "Lat" and "Long" are poor choices for generic parameter names in the documentation.
Based on these issues in the docs, it's most likely that for EPSG 4326, the database expects coordinates in (x,y) order, so (lng, lat), not (lat, lng). This also is consistent with the way most other spatial systems define coordinates in EPSG 4326.

Geometry column: STGeomFromText and SRID (what is an SRID?)

I'm playing with the new geography column in SQL Server 2008 and the STGeomFromText function. Here is my code (works with AdventureWorks2008)
DECLARE #region geography;
set #region = geography::STGeomFromText('POLYGON((
-80.0 50.0, -90.0 50.0,
-90.0 25.0, -80.0 25.0,
-80.0 50.0))', 4326);
SELECT #region;
My question is about the 4326 in the code. It is supposed to be a spacial Reference ID. When I go to MSDN there isn't a lot on it. If I change the value to 56 I get an error telling me the value must be in the sys.spatial_reference_systems table.
You can look at that table by executing:
select * from sys.spatial_reference_systems
There is a well_known_text column in that table, but it doesn't tell me much. The value for 4326 is:
GEOGCS["WGS 84", DATUM["World Geodetic System 1984", ELLIPSOID["WGS 84", 6378137, 298.257223563]], PRIMEM["Greenwich", 0], UNIT["Degree", 0.0174532925199433]]
Can anyone explain this mystery to me? What is the SRID?
So I ended up talking with an ex-military guy yesterday who was a radar/mapping specialist.
Basically, he knew exactly what that number (4326) was, where it came from, and why it is there.
It is an industry standard for computing geography. The problem is that the earth is not a perfect sphere (it bulges in the middle), and SRID 4326 accounts for that.
As I stated, the table sys.spatial_reference_systems lists all of the code and what they are. But the short version is that you are really only going to use 4326 unless you have a very specific reason to use something different.
SRID = Spatial Reference IDentifier
coordinates must use the same SRID to be comparable. otherwise you'd end up comparing kilometeres and miles. or something similar.
There are a lot of systems to map the earth. For example you want to map some state in USA. You can set the most south-east point as 0,0 and map all other spatial coordinates according to this point. On the other hand you may want to map some spatial data that span all over the map. In any case you must choose some point as 0,0. In addition you must select some sort of measurement unit: miles/kilometers/degrees/some other magical unit that suits you better. Over the years a lot of such systems where developed. Each has its own zero point, its own coordinates, its own rules about if the earth is flat or not. SRID or SRS is the id of such system. Using this id you can map point expressed in one system to another system, although sometimes it involves some pretty complex math.
And about 4326 SRID. It also called "WGS 84"
(http://en.wikipedia.org/wiki/World_Geodetic_System) system. It's the most common system to represent point on spherical(not flat) earth. It uses degree,minute,second notation and its x and y coordinates are usually called latitude and longitude.
Most used non-spherical earth projection is called UTM. You can read about it here: http://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system
Anyway, as long you are not doing any spatial conversions from one system to other, you don't really care about the system that you data uses.
I have found this website: http://spatialreference.org/ref/epsg/4326/ quite helpful in understanding the SRID you intend to use. It provides a handy map, some bounding box information and other links.
For other SRIDs simply change the digits at the end of the URL to what you are after.
The distance returned depends on the "Spatial Reference Identifier (SRID)" you define for your geography types.
In the example below, the default SRID of 4336 is used, see the second argument of STGeomFromText. This means the distance returned is in meters, you find this via querying the catalog view spatial_reference_systems i.e. select srs.unit_of_measure from sys.spatial_reference_systems as srs where srs.spatial_reference_id = 4326
As an alternative to STGeomFromText, you can use parse which assumes a SRID of 4326 and you don't have to specify one explicitly.
When calculating the distance between two points, you must use the same SRID for both geography types else you get an error. Example:
DECLARE #address1 GEOGRAPHY
DECLARE #address2 GEOGRAPHY
DECLARE #distance float
SET #address1 = GEOGRAPHY::STGeomFromText ('point(53.046908 -2.991673)',4326)
SET #address2 = GEOGRAPHY::STGeomFromText ('point(51.500152 -0.126236)',4326)
SET #distance = #address1.STDistance(#address2)
SELECT #distance --this is the distance in meters

Resources