How to calculate area in SQL using geographic coordinates? - sql

Does anybody know what is the problem with my query. I am trying to calculate area using geographical coordinates, but result seems to be too small to be true. 0.00118 sqm. Can anybody help?
SELECT ST_Area(the_geom) As sqm
FROM (SELECT
ST_GeomFromText('POLYGON
(
(14.604514925547997 121.0968017578125,
14.595212295624522 121.08512878417969,
14.567302046916149 121.124267578125,
14.596541266841905 121.14761352539062,
14.604514925547997 121.0968017578125)
)',4326) ) As foo(the_geom)

How accurate should be the calculation?
A solution is to cast GEOMETRY to GEOGRAPHY, which is acceptably accurate for the most use cases:
SELECT ST_Area(the_geom::GEOGRAPHY ) As sqm
FROM (SELECT
ST_GeomFromText('POLYGON
(
(14.604514925547997 121.0968017578125,
14.595212295624522 121.08512878417969,
14.567302046916149 121.124267578125,
14.596541266841905 121.14761352539062,
14.604514925547997 121.0968017578125)
)',4326) ) As foo(the_geom)
The geography type automatically converts degrees to meters.
Depending on your scenario you could also use directly the geography constructor St_GeographyFromText, which accept a WKT string as argument, very similar to ST_GeomFromText
ST_GeographyFromText('POLYGON((14.604514925547997 121.0968017578125,
14.595212295624522 121.08512878417969,
14.567302046916149 121.124267578125,
14.596541266841905 121.14761352539062,
14.604514925547997 121.0968017578125))'
)

Related

SQL Multipolygon void where it overlaps

I have a polygon WKT and turning it into a geography and am presented with two polgyons, but where they overlap there is a void.
I am trying to find markers that exist in any polygon in the string (lat long intersects). The issue is that this void that is created I am not being delivered markers that exist there when it is required.
IF OBJECT_ID('tempdb..#customPolygon') IS NOT NULL DROP TABLE #customPolygon
CREATE TABLE #customPolygon (geog GEOGRAPHY)
[![DECLARE #customPolygon geography = 'MULTIPOLYGON (((-122.31260682058497 41.7828672412252, -122.66803538233832 41.74189213171878, -123.0157152218382 41.67409631073075, -123.35191487435746 41.58021595697532, -123.67306979164175
41.461266240272025, -123.97583066087832 41.31852640120816, -124.25710598001243 41.15352132907401, -124.51409805934621 40.96800014522892, -124.74433194261869 40.763912348675035, -124.94567706168226 40.54338210199239,
-125.11636173536279 40.30868123071627, -125.25498087780294 40.06220148128715, -125.3604974831004 39.80642653665781, -125.4322385960062 39.543904229883005, -125.46988656305209 39.277219329961135, -125.4734663894492
39.008967205820475, -125.44333001234564 38.74172860785035, -125.38013825025583 38.47804574501649, -125.28484111194828 38.22039978159673, -125.1586570556347 37.971189832187214, -125.00305168962673 37.73271349727281,
-124.8197163058454 37.50714895406215, -124.61054654308778 37.296538597688055, -124.37762139148631 37.102774215181654, -124.12318267532315 36.9275836675835, -123.8496150891857 36.772519052867715, -123.55942681226277
36.638946322795874, -123.25523068653888 36.52803632929597, -122.93972591543192 36.44075727956827, -122.61568021845359 36.377868583149755, -122.28591236310895 36.339916078129036, -121.9532749859139 36.327228627297,
-121.62063760871888 36.339916078129036, -121.2908697533742 36.377868583149755, -120.96682405639588 36.44075727956827, -120.65131928528895 36.52803632929597, -120.34712315956506 36.638946322795874, -120.0569348826421
36.772519052867715, -119.78336729650465 36.9275836675835, -119.52892858034149 37.102774215181654, -119.29600342874002 37.29653859768806, -119.08683366598238 37.50714895406215, -118.90349828220107 37.73271349727281,
-118.7478929161931 37.971189832187214, -118.62170885987955 38.22039978159673, -118.52641172157198 38.47804574501649, -118.46321995948216 38.74172860785035, -118.43308358237861 39.008967205820475, -118.43666340877571
39.277219329961135, -118.4743113758216 39.543904229883005, -118.54605248872741 39.80642653665781, -118.65156909402486 40.06220148128715, -118.79018823646503 40.30868123071627, -118.96087291014557 40.54338210199239,
-119.16221802920913 40.763912348675035, -119.3924519124816 40.96800014522892, -119.6494439918154 41.15352132907401, -119.93071931094948 41.31852640120816, -120.23348018018605 41.461266240272025, -120.55463509747037 41.58021595697532, -120.89083474998958 41.67409631073075, -121.2385145894895 41.74189213171878, -121.59394315124284 41.7828672412252, -122.31260682058497 41.7828672412252)), ((-119.1795222467484 42.50521242789702, -120.70099431758788 39.07636493660857, -115.32512633395542 38.91870544294517, -119.1795222467484 42.50521242789702)))'
INSERT INTO #customPolygon
SELECT geography::STPolyFromText(#customPolygon, 4326).MakeValid().ToString()
UPDATE #customPolygon SET geog=case when geog.EnvelopeAngle() > 90 then geog.ReorientObject() else geog end
SET #customPolygonJoin = ' join #customPolygon poly on poly.geog.STIntersects(a.GeoLoc) = 1 '][1]][1]
I would like to avoid itemizing polygons within the multipolygon string as there could be an unlimited number.
I've tried ST unions and ST difference, except it seems those require two geography inputs, where the multipolgyon is just 1.
TYIA
I think this "hole" is artifact of your drawing tool. Within SQL Server, it is two overlapping polygons - so there is no hole, it is instead covered by both of the polygons.
But if you want to dissolve this into a single polygon, I would try to StUnion it with empty geography (geography::STGeomFromText('POLYGON EMPTY', 4326)) or with itself.

How to convert from PostgreSQL to GeoJSON format?

I have a simple table called"imposm3_restaurant" with columns [ id, name, geometry] I want to convert these data into geoJSON, I am using this function
CREATE VIEW imposm3_restaurants_geojson AS SELECT row_to_json(fc) AS geojson FROM
(SELECT 'FeatureCollection' As type, array_to_json(array_agg(f))
As features FROM
(SELECT
'Feature' As type,
ST_AsGeoJSON((lg.geometry),15,0)::json As geometry,
row_to_json((id, name)) As properties
FROM imposm3_restaurants As lg) As f ) As fc;
and the result is this:
{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"LineString","coordinates":[[2615020.47191046,5899232.25158985],[2615034.50527113,5899231.67978097],[2615033.86145338,5899215.4513157],[2615032.35921198,5899215.51938806],[2615031.96732292,5899205.64890158],[2615034.97180572,5899205.51275702],[2615034.36531075,5899190.07397728],[2615018.19522163,5899190.71385561],[2615018.77372453,5899205.40384137],[2615020.47191046,5899205.32215463],[2615020.91045298,5899216.48601561],[2615019.83742341,5899216.52685903],[2615020.47191046,5899232.25158985]]},"properties":{"f1":2719,"f2":"Atelierul de Pizza"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[2615018.19522163,5899190.71385561],[2615018.77372453,5899205.40384137],[2615020.47191046,5899205.32215463],[2615020.91045298,5899216.48601561],[2615019.83742341,5899216.52685903],[2615020.47191046,5899232.25158985],[2615034.50527113,5899231.67978097],[2615033.86145338,5899215.4513157],[2615032.35921198,5899215.51938806],[2615031.96732292,5899205.64890158],[2615034.97180572,5899205.51275702],[2615034.36531075,5899190.07397728],[2615018.19522163,5899190.71385561]]]},"properties":{"f1":2720,"f2":"Atelierul de Pizza"}},{"type":"Feature","geometry":{"type":"LineString","coordinates":[[2624875.82864931,5903443.39761349],[2624897.49451598,5903452.78251964],[2624901.44139867,5903443.67003443],[2624879.78486269,5903434.29875908],[2624875.82864931,5903443.39761349]]},"properties":{"f1":2986,"f2":"Pizza Acrobatica"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[2624875.82864931,5903443.39761349],[2624897.49451598,5903452.78251964],[2624901.44139867,5903443.67003443],[2624879.78486269,5903434.29875908],[2624875.82864931,5903443.39761349]]]},"properties":{"f1":2988,"f2":"Pizza Acrobatica"}},{"type":"Feature","geometry":{"type":"LineString","coordinates":[[2622460.22447654,5904586.41424973],[2622479.10046632,5904587.95362911],[2622480.25747212,5904573.81314552],[2622461.39081303,5904572.26014582],[2622460.22447654,5904586.41424973]]},"properties":{"f1":3248,"f2":"Casa Vikingilor"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[2622460.22447654,5904586.41424973],[2622479.10046632,5904587.95362911],[2622480.25747212,5904573.81314552],[2622461.39081303,5904572.26014582],[2622460.22447654,5904586.41424973]]]},"properties":{"f1":3249,"f2":"Casa Vikingilor"}},{"type":"Feature","geometry":{"type":"LineString","coordinates":[[2625201.09657005,5897608.45120294],[2625224.46062264,5897614.30435379],[2625241.33051365,5897576.653689],[2625213.43174478,5897570.82778714],[2625201.09657005,5897608.45120294]]},"properties":{"f1":6152,"f2":"Silva"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[2625201.09657005,5897608.45120294],[2625224.46062264,5897614.30435379],[2625241.33051365,5897576.653689],[2625213.43174478,5897570.82778714],[2625201.09657005,5897608.45120294]]]},"properties":{"f1":6153,"f2":"Silva"}},{"type":"Feature","geometry":{"type":"LineString","coordinates":[[2622825.25980629,5904372.27967993],[2622826.15555271,5904353.45341631],[2622834.51585268,5904353.1673446],[2622854.22227404,5904346.00193242],[2622860.03529512,5904362.26715407],[2622856.61093118,5904374.66361634],[2622825.25980629,5904372.27967993]]},"properties":{"f1":6322,"f2":"Restaurant Sinaia"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[2622825.25980629,5904372.27967993],[2622856.61093118,5904374.66361634],[2622860.03529512,5904362.26715407],[2622854.22227404,5904346.00193242],[2622834.51585268,5904353.1673446],[2622826.15555271,5904353.45341631],[2622825.25980629,5904372.27967993]]]},"properties":{"f1":6323,"f2":"Restaurant Sinaia"}}]}
which does not have a current geometry, do you know what is wrong in function: I am using Postgres 9.3 and PostGIS 2.2
Your output is a valid geojson file but the geometries are projected using the projection EPSG:3857.
You can load the data without problems in the most gis desktop applications, in example Quantum Gis.
Probably geojson.io supports only long/lat coordinates EPSG:4326, also try reprojecting the geometries to long/lat coordinates using the function St_Transform
Change this line:
ST_AsGeoJSON((lg.geometry),15,0)::json As geometry,
in this:
ST_AsGeoJSON(ST_Transform(lg.geometry, 4326),15,0)::json As geometry,

Oracle Spatial transform

We have a table in an Oracle Spatial database containing polygons (lying in Austria) in Lambert projection (SRID=1000047), which we want to transform into WGS84 (SRID=8307). After performing
create table Table2 as (
select ..., SDO_CS.TRANSFORM(geometry, 8307) as geometry, ...
from Table1)
the polygons in Table2 all lie practically on a single point north of Paris. What are we doing wrong?
Edit: As an example, the point [11.26555560027597,53.87928275206266] gets transformed to [2.3069645331040123,49.293822884973984]. I get the same results using SRID=4326 instead of 8307.
The sqlplus query select * from cs_srs where srid=100047 returns
PROJCS["LAMBERT",GEOGCS["GCS_MGI",DATUM["D_MGI",SPHEROID["Bessel_1841",6377397.1‌55,299.1528128]], PRIMEM["Greenwich",0],UNIT["Decimal Degree",0.017453292519943295]],PROJECTION["Lambert Conformal Conic"], PARAMETER["False_Easting",400000],PARAMETER["False_Northing",400000], PARAMETER["Central_Meridian",13.33333333333333],PARAMETER["Standard_Parallel_1",‌​46], PARAMETER["Standard_Parallel_2",49],PARAMETER["Scale_Factor",1], PARAMETER["Latitude_Of_Origin",47.5],UNIT["Meter",1]]
Your source SRID (1000047) is not a standard EPSG code, neither is it any coordinate system that ships with any version of Oracle: it looks like one you defined yourself. Can you show us the definition (select * from cs_srs where srid=1000047) ?
Looking at your input (11.26555560027597,53.87928275206266) - that does not look like any projection. It looks to me like some geodetic coordinates, possibly on a different datum than WGS84.
The coordinate system definition you use is that of the standard SRID 31287:
PROJCS[
"MGI / Austria Lambert",
GEOGCS["MGI",
DATUM["Militar-Geographische Institut",
SPHEROID[
"Bessel 1841",
6377397.155,
299.1528128,
AUTHORITY["EPSG", "7004"]],
TOWGS84[577.326, 90.129, 463.919, 5.137, 1.474, 5.297, 2.4232],
AUTHORITY["EPSG", "6312"]],
PRIMEM["Greenwich", 0.000000, AUTHORITY["EPSG","8901"]],
UNIT["degree (supplier to define representation)", 0.0174532925199433, AUTHORITY["EPSG", "9122"]],
AXIS["Lat", NORTH],
AXIS["Long", EAST],
AUTHORITY["EPSG", "4312"]],
PROJECTION ["Lambert Conformal Conic"],
PARAMETER ["Latitude_Of_Origin", 47.5],
PARAMETER ["Central_Meridian", 13.3333333333333333],
PARAMETER ["Standard_Parallel_1", 49.0],
PARAMETER ["Standard_Parallel_2", 46.0],
PARAMETER ["False_Easting", 400000.0],
PARAMETER ["False_Northing", 400000.0],
UNIT["metre", 1.0, AUTHORITY["EPSG", "9001"]],
AXIS["X", NORTH],
AXIS["Y", EAST],
AUTHORITY["EPSG", "31287"]]
The main difference with yours is that yours is missing the datum shift parameters. The other difference is that the standard parallels are reversed: parallel 1 is 49 and parallel 2 is 46 vs. 46 and 49 in your definition.
Here is what I get when I transform the geometry you posted as example (encoded using 31287):
select sdo_cs.transform (
sdo_geometry(2003,31287,null,sdo_elem_info_array(1, 1003, 1),sdo_ordinate_array(607205.274999979, 528729.87700098, 607052.849999979, 528254.154000983, 607080.702999979, 528224.753000982, 607098.889999979, 528220.193000982, 607113.807999979, 528225.393000979, 607272.533999979, 528720.85100098, 607269.772999979, 528724.96700098, 607205.274999979, 528729.87700098)),
4326
)
from dual;
SDO_GEOMETRY(2003, 4326, NULL, SDO_ELEM_INFO_ARRAY(1, 1003, 1), SDO_ORDINATE_ARRAY(16.1442004, 48.62389, 16.1419009, 48.6196637, 16.1422641, 48.6193904, 16.1425084, 48.6193435, 16.1427132, 48.6193854, 16.1451079, 48.623787, 16.1450725, 48.6238249, 16.1442004, 48.62389))
The result looks fine to me. Can you verify that it is ?
What exact version of Oracle do you run? SRID 31287 exists since 10gR2.
The simplest seems to me to use srid 31287 for your data instead of the custom 100047.

Geography data type vs. Geometry data type in SQL Server

Environment: SQL Server 2012
I'm using an online tool, the only one I could find so far, to plot polygons and points on the earth. http://www.birdtheme.org/useful/googletool.html
I have two tables. One stores "areas" as polygons and the other table stores points amongst other things irrelevant to my question.
For simplicity, I'll just reduce my scenario to sql variables.
In the query below, I'm using the geography data type for well known points of interest.
I drew a polygon around Robben Island, a point in Robben Island and a point in Alcatraz.
DECLARE #robben_island geography = ('POLYGON((18.351803 -33.788421,18.382788 -33.787494,18.386736 -33.820515,18.354464 -33.822369,18.351803 -33.788421))')
DECLARE #point_in_robben_island geography= ('POINT(18.369226 -33.80554)')
DECLARE #point_in_alcatraz geography= ('POINT(-122.423401 37.827006)')
SELECT #robben_island.STContains(#point_in_robben_island) --returns 'False', but it's not what I expected
SELECT #robben_island.STContains(#point_in_alcatraz) --returns 'True', but it's not what I expected
This query above, if I understand it correctly, tells me that my #point_in_robben_island is not contained in #robben_island, rather my #point_in_alcatraz exists in #robben_island which as we all know, is not true.
Now when I change the data types from geography to geometry, everything works fine, but I'm afraid that if I continue using the geometry data type I might come across a few gotchas. I'm just wondering if I won't be negatively affected by fact that geometry doesn't quite account for earth's curvature. touch wood.
DECLARE #robben_island geometry = ('POLYGON((18.351803 -33.788421,18.382788 -33.787494,18.386736 -33.820515,18.354464 -33.822369,18.351803 -33.788421))')
DECLARE #point_in_robben_island geometry= ('POINT(18.369226 -33.80554)')
DECLARE #point_in_alcatraz geometry= ('POINT(-122.423401 37.827006)')
SELECT #robben_island.STContains(#point_in_robben_island) --returns 'True' as it should
SELECT #robben_island.STContains(#point_in_alcatraz) --returns 'False' as it should
Now my question is, why does the geography data type return unexpected results while geometry works as expected? Thank you very much.
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.
Unfortunately (some find this a good thing), SQL Server 2012 no longer throws an error when you create the invalid geography. You need to invert the order of the points in the Roben Island geometry, like:
DECLARE #robben_island geography = ('POLYGON((18.351803 -33.788421, 18.354464 -33.822369,18.386736 -33.820515, 18.382788 -33.787494, 18.351803 -33.788421))')
DECLARE #point_in_robben_island geography= ('POINT(18.369226 -33.80554)')
DECLARE #point_in_alcatraz geography= ('POINT(-122.423401 37.827006)')
SELECT #robben_island.STContains(#point_in_robben_island) --returns 'True'
SELECT #robben_island.STContains(#point_in_alcatraz) --returns 'False'

Querying Netezza via SquirrelSQL returns WKT geometry in unknown encoding

I am using SquirrelSQL to write and execute SQL queries on a Netezza database. Using Netezza's spatial capabilities (which are essentially the same as those of PostGIS) I've executed a query and returned a single result that contains a geometry. Here's the query, for reference:
SELECT t.SHAPE
FROM (SELECT * FROM OS_AB_PLUS..E12_ADDRESSBASE WHERE POSTCODE = 'RH1 6NE'
AND PAO_START_NUMBER = '14') as a, OS_TOPO..TOPOGRAPHICAREA as t
WHERE inza..ST_Within(a.shape, t.shape) = TRUE
My issue is that the geometry field, which should contain the polygon coordinates represented as Well-Known Text (WKT), looks instead like this:
g¹ AË Affff¬0AÍÌÌÌî0AÒ 3333Ê AÍÌÌÌî0A» Aë0Afffæ» AffffÒ0A¹ AÒ0A333³¹ A3333¿0AŒ AffffÀ0AÍÌÌLŒ Affff¬0AË A¯0AëQ8Ê A3333í0A3333Ê AÍÌÌÌî0A
I can't seem to find anywhere in SquirrelSQL to specify the encoding of VARCHAR columns, and I've seen the column returned without encoding issues in Aginity (another SQL client). Any suggestions on how to proceed would be much appreciated.
Turns out my issue was not really related to encoding at all. The human-readable version of the geometry in a PostGIS-like database will only be returned when ST_AsText is used in the select statement. So my SQL query becomes:
SELECT inza..ST_AsText(t.SHAPE)
FROM (SELECT * FROM OS_AB_PLUS..E12_ADDRESSBASE WHERE POSTCODE = 'RH1 6NE'
AND PAO_START_NUMBER = '14') as a, OS_TOPO..TOPOGRAPHICAREA as t
WHERE inza..ST_Within(a.shape, t.shape) = TRUE
Which returns. as intended:
POLYGON ((526696.15 148931.9, 526703.94 148932.34, 526703.8 148935.2, 526705.5 148935.3, 526705.4 148937.8, 526695.9 148937.35, 526696.15 148931.9))