Related
I have to extend the normal GeoJSON format to add some unsopported polygon like Circle.
{
"type": "Circle",
"radius" : 0.001,
"coordinates": [
5.417075157165527,
43.29129488122568
]
}
This is an Example. Coordinates marks the center of circle and radius the radius (in meters).
Searching on PostGis Docs and Stackoverflow, to draw a Circle you have to user ST_BUFFER.
So Im using:
ST_Buffer(ST_GeomFromGeoJSON(<center of circle>),0.001, 'quad_segs=16')
Has you know, this draw a Circle only in 0,0 (near Africa). Other locations add a distortion that change the shape in an oval.
Im using 4326.
I have tried to search (even here) but I can't Find a solution to simply draw a circle avoid projection or transforming it.
The only post here is: How to create a circle in meters in postgis?
but its very old and that solution doesn't works.
Isn't it just doing what is supposed to be done? Which is to compensate the distortion due to projecting the ellipsoid into a 2D flat structure? I believe, the further away you get from the equator, the more oval buffers you will see.
Examples:
db=# SELECT ST_AsText(
ST_Buffer(
ST_GeomFromText('SRID=4326;POINT(43.29 5.41)'),0.001, 'quad_segs=16')
);
This query returns a circle at the south-east of Ethiopia:
POLYGON((43.291 5.41,43.2909951847267
5.40990198285967,43.2909807852804 5.40980490967798,43.2909569403357 5.40970971532275,43.2909238795325 5.40961731656764,43.2908819212644 5.40952860326317,43.2908314696123 5.40944442976698,43.2907730104534 5.40936560671584,43.2907071067812 5.40929289321881,43.2906343932842 5.40922698954664,43.290555570233 5.4091685303877,43.2904713967368 5.40911807873565,43.2903826834324 5.40907612046749,43.2902902846773 5.40904305966427,43.290195090322 5.4090192147196,43.2900980171403 5.40900481527333,43.29 5.409,43.2899019828597 5.40900481527333,43.289804909678 5.4090192147196,43.2897097153227 5.40904305966427,43.2896173165676 5.40907612046749,43.2895286032632 5.40911807873565,43.289444429767 5.4091685303877,43.2893656067158 5.40922698954664,43.2892928932188 5.40929289321881,43.2892269895466 5.40936560671584,43.2891685303877 5.40944442976698,43.2891180787356 5.40952860326317,43.2890761204675 5.40961731656764,43.2890430596643 5.40970971532275,43.2890192147196 5.40980490967798,43.2890048152733 5.40990198285967,43.289 5.41,43.2890048152733 5.41009801714033,43.2890192147196 5.41019509032202,43.2890430596643 5.41029028467725,43.2890761204675 5.41038268343237,43.2891180787356 5.41047139673683,43.2891685303877 5.41055557023302,43.2892269895466 5.41063439328416,43.2892928932188 5.41070710678119,43.2893656067158 5.41077301045336,43.289444429767 5.4108314696123,43.2895286032632 5.41088192126435,43.2896173165676 5.41092387953251,43.2897097153227 5.41095694033573,43.289804909678 5.4109807852804,43.2899019828597 5.41099518472667,43.29 5.411,43.2900980171403 5.41099518472667,43.290195090322 5.4109807852804,43.2902902846773 5.41095694033573,43.2903826834324 5.41092387953251,43.2904713967368 5.41088192126435,43.290555570233 5.4108314696123,43.2906343932842 5.41077301045336,43.2907071067812 5.41070710678119,43.2907730104534 5.41063439328416,43.2908314696123 5.41055557023302,43.2908819212644 5.41047139673683,43.2909238795325 5.41038268343237,43.2909569403357 5.41029028467725,43.2909807852804 5.41019509032202,43.2909951847267 5.41009801714033,43.291 5.41))
The same procedure a bit further away from the equator, in Tunisia POINT(9.76 36.61):
POLYGON((9.761 36.61,9.76099518472667 36.6099019828597,9.7609807852804 36.609804909678,9.76095694033573 36.6097097153227,9.76092387953251 36.6096173165676,9.76088192126435 36.6095286032632,9.7608314696123 36.609444429767,9.76077301045336 36.6093656067158,9.76070710678119 36.6092928932188,9.76063439328416 36.6092269895466,9.76055557023302 36.6091685303877,9.76047139673683 36.6091180787356,9.76038268343236 36.6090761204675,9.76029028467725 36.6090430596643,9.76019509032202 36.6090192147196,9.76009801714033 36.6090048152733,9.76 36.609,9.75990198285967 36.6090048152733,9.75980490967798 36.6090192147196,9.75970971532275 36.6090430596643,9.75961731656763 36.6090761204675,9.75952860326317 36.6091180787356,9.75944442976698 36.6091685303877,9.75936560671584 36.6092269895466,9.75929289321881 36.6092928932188,9.75922698954664 36.6093656067158,9.7591685303877 36.609444429767,9.75911807873565 36.6095286032632,9.75907612046749 36.6096173165676,9.75904305966427 36.6097097153227,9.7590192147196 36.609804909678,9.75900481527333 36.6099019828597,9.759 36.61,9.75900481527333 36.6100980171403,9.7590192147196 36.610195090322,9.75904305966427 36.6102902846773,9.75907612046749 36.6103826834324,9.75911807873565 36.6104713967368,9.7591685303877 36.610555570233,9.75922698954664 36.6106343932842,9.75929289321881 36.6107071067812,9.75936560671584 36.6107730104534,9.75944442976698 36.6108314696123,9.75952860326317 36.6108819212644,9.75961731656763 36.6109238795325,9.75970971532275 36.6109569403357,9.75980490967798 36.6109807852804,9.75990198285967 36.6109951847267,9.76 36.611,9.76009801714033 36.6109951847267,9.76019509032202 36.6109807852804,9.76029028467725 36.6109569403357,9.76038268343236 36.6109238795325,9.76047139673683 36.6108819212644,9.76055557023302 36.6108314696123,9.76063439328416 36.6107730104534,9.76070710678119 36.6107071067812,9.76077301045336 36.6106343932842,9.7608314696123 36.610555570233,9.76088192126435 36.6104713967368,9.76092387953251 36.6103826834324,9.76095694033573 36.6102902846773,9.7609807852804 36.610195090322,9.76099518472667 36.6100980171403,9.761 36.61))
And this one much further away, in the north of Norway POINT(23.20 69.94):
POLYGON((23.201 69.94,23.2009951847267 69.9399019828597,23.2009807852804 69.939804909678,23.2009569403357 69.9397097153227,23.2009238795325 69.9396173165676,23.2008819212643 69.9395286032632,23.2008314696123 69.939444429767,23.2007730104534 69.9393656067158,23.2007071067812 69.9392928932188,23.2006343932842 69.9392269895466,23.200555570233 69.9391685303877,23.2004713967368 69.9391180787356,23.2003826834324 69.9390761204675,23.2002902846773 69.9390430596643,23.200195090322 69.9390192147196,23.2000980171403 69.9390048152733,23.2 69.939,23.1999019828597 69.9390048152733,23.199804909678 69.9390192147196,23.1997097153227 69.9390430596643,23.1996173165676 69.9390761204675,23.1995286032632 69.9391180787356,23.199444429767 69.9391685303877,23.1993656067158 69.9392269895466,23.1992928932188 69.9392928932188,23.1992269895466 69.9393656067158,23.1991685303877 69.939444429767,23.1991180787357 69.9395286032632,23.1990761204675 69.9396173165676,23.1990430596643 69.9397097153227,23.1990192147196 69.939804909678,23.1990048152733 69.9399019828597,23.199 69.94,23.1990048152733 69.9400980171403,23.1990192147196 69.940195090322,23.1990430596643 69.9402902846772,23.1990761204675 69.9403826834324,23.1991180787357 69.9404713967368,23.1991685303877 69.940555570233,23.1992269895466 69.9406343932842,23.1992928932188 69.9407071067812,23.1993656067158 69.9407730104534,23.199444429767 69.9408314696123,23.1995286032632 69.9408819212643,23.1996173165676 69.9409238795325,23.1997097153227 69.9409569403357,23.199804909678 69.9409807852804,23.1999019828597 69.9409951847267,23.2 69.941,23.2000980171403 69.9409951847267,23.200195090322 69.9409807852804,23.2002902846773 69.9409569403357,23.2003826834324 69.9409238795325,23.2004713967368 69.9408819212643,23.200555570233 69.9408314696123,23.2006343932842 69.9407730104534,23.2007071067812 69.9407071067812,23.2007730104534 69.9406343932842,23.2008314696123 69.940555570233,23.2008819212643 69.9404713967368,23.2009238795325 69.9403826834324,23.2009569403357 69.9402902846772,23.2009807852804 69.940195090322,23.2009951847267 69.9400980171403,23.201 69.94))
To make your buffer ignore the distortion caused by the projection, consider the following query (POINT in Italy):
SELECT
ST_Buffer(
ST_GeomFromGeoJSON('{"type":"Point","coordinates":[11.26,44.42]}')::geography,
1000,'quad_segs=16')::geometry;
Explanation:
Calculations using GEOMETRY and GEOGRAPHY are made differently, and so are their results. GEOGRAPHY calculates the coordinates over an spherical surface (which can be much slower than GEOMETRY) and uses meters as unit of measurement, while GEOMETRY uses a planar projection and uses the SRS unit.
Note: The GEOMETRY casting in the end of the last query is necessary for the OP's use case, see comments bellow.
May be you can try this it is for a zone one kilometer in diameter like. I test it and it works for me:
SELECT ST_Buffer(
ST_MakePoint(-122.325959,47.625138)::geography,
1000)::geometry;
See here for better understanding.
I didn't test it but hope it will help you.
To recap a bit what Abdullah Alger did in the solution that you can see in the link above:
First he has a database called stores with latitude and longitude column no geometry column with Starbuck dataset.
Then he adds geometry with the query:
SELECT AddGeometryColumn('stores', 'geom', 4326, 'POINT', 2);
After that update the geom column
I am using ClusterPoint database to access Open Street Map data (https://github.com/clusterpoint/osm), but I'd like to find POI contained within multiple separate polygons.
Is there any example available how to define and use multiple polygons within query?
To use multiple polygons in one query, you need to define them under <shapes> tag. Each polygon should have individual name. If you want to search within multiple polygons, than use OR operator "{}" in query.
Example with two polygons and one circle could look like:
<query>
{><polygon1 ><polygon2 ><circle1}
</query>
<shapes>
<polygon1>lat1 lon1; lat2 lon2; lat3 lon3; lat4 lon4; lat5 lon5; ...
<coord1_tag_name>lat</coord1_tag_name>
<coord2_tag_name>lon</coord2_tag_name>
</polygon1>
<polygon2>lat1 lon1; lat2 lon2; lat3 lon3; lat4 lon4; lat5 lon5; ...
<coord1_tag_name>lat</coord1_tag_name>
<coord2_tag_name>lon</coord2_tag_name>
</polygon2>
<circle1>
<center>lat lon</center>
<radius>10 km</radius> <!-- here you can define distance in "km" or in "mi" -->
<coord1_tag_name>lat</coord1_tag_name>
<coord2_tag_name>lon</coord2_tag_name>
</circle1>
</shapes>
If polygons are overlapped, then matching points within this area will not "duplicate" in result set (will be displayed once).
In PostGIS you can intersect two geometries using:
geometry ST_Intersection (geometry geomA, geometry geomB);
In my case both geomA and geomB are LINESTRING so ST_Intersection() returns a POINT geometry.
I want to know if the intersection occurs in a begin/end node (the geometries touch) or in the middle (the geometries intersect).
I can compare the (Point.X, Point.Y) with each ending node:
geomA.nodes(0) - geomA.nodes(len-1)
geomB.nodes(0) - geomB.nodes(len-1)
But is very complex. And I would like a simple solution.
There are 3 intersect cases.
Example 1: Two lines in a "L" shape intersect in an end node on both lines on the bottom left.
Example 2: Two lines in a "T" shape where the vertical line intersects in the middle of the horizontal line. In this case the vertical line end node touches a non-end node of the horizontal line.
Example 3: Two lines in a "X" shape. Intersection point isn't an end node for either line.
For my problem I'm only interested in finding the touching scenario like Example 2.
NOTE
This is the pseudo code I use now.
geomM, geomN Linestring
a, b, c, d, z Points.
(a,b) begin/end node for geomM ST_StartPoint(geom) and ST_EndPoint(geom)
(c,d) begin/end node for geomN
z = ST_Intersect(geomM, geomN)
SELECT geomM, geomN, z
FROM Table
WHERE
(A and not ( B or C or D))
OR (B and not ( A or C or D))
OR (C and not ( A or B or D))
OR (D and not ( A or B or C))
A, B, C, D replace ( a=z ) ( b=z ) ( c=z ) ( d=z )
This mean one node {a,b,c,d} is equal to intersection z. But only one
This return all "T" shape intersections.
You need the PostGIS function ST_Touches() here. The function returns true if the geometries touch on their boundaries, but false if they intersect. In terms of your examples, Example 1 and 2 return true, Example 3 returns false.
Relaxed solution
To select the IDs of all pairs of touching geometry(LINESTRING, xxx) records from a single table use this:
SELECT x.id AS idA, y.id AS idB
FROM my_table x
JOIN my_table y ON ST_Touches(y.the_geom, x.the_geom)
WHERE x.id < y.id;
(The WHERE clause avoids duplicate results like (132, 254) and (254, 132).)
Note that the linestrings can also touch on any of their non-node vertices. If you want to strictly follow Example 2 then you have to compare every point on every linestring against every point on all other linestrings, which is obviously going to be a very intensive operation. Example 2 is basically only feasible when you know that the linestrings are very short, preferably just straight lines.
Strict solution, straight lines only
If all LINESTRINGs are straight, i.e. composed of a starting and an ending node only, then this is your solution:
SELECT h.id AS touched, v.id AS touching, ST_Intersection(h.the_geom, v.the_geom) AS touch_point
FROM my_table h -- "horizontal" T bar, being touched
JOIN my_table v ON -- "vertical" T bar, touching
(
-- The "vertical" start node touches, but not on either of the "horizonal" nodes
ST_Equals(ST_Intersection(h.the_geom, v.the_geom), ST_StartPoint(v.the_geom))
AND NOT ST_Equals(ST_StartPoint(h.the_geom), ST_StartPoint(v.the_geom))
AND NOT ST_Equals(ST_EndPoint(h.the_geom), ST_StartPoint(v.the_geom))
) OR (
-- The "vertical" end node touches, but not on either of the "horizonal" nodes
ST_Equals(ST_Intersection(h.the_geom, v.the_geom), ST_EndPoint(v.the_geom))
AND NOT ST_Equals(ST_StartPoint(h.the_geom), ST_EndPoint(v.the_geom))
AND NOT ST_Equals(ST_EndPoint(h.the_geom), ST_EndPoint(v.the_geom))
);
All the requirements are checked in the JOIN ON clause. This will also return the location where the "vertical" bar of the T touches the "horizontal" bar. Note that the conditions are short-circuited when being evaluated and repeated calls to a function with the same input data are optimized to a single call.
When I perform an intersection of a polygon I draw in OpenLayers and a postgis database layer, it seems that I am getting incorrect results.
Intersection works correctly on some layers. For instance, if I intersect a triangle with a layer of polygons that represent crop fields, I get the following:
The query my app generates to produce the above result is:
SELECT ST_AsText(ST_Intersection(%(geometries_0)s::geometry, %(geometry)s::geometry))
where geometries_0 is my triangle:
POLYGON((-104.84928345939991 40.518951354186285,-104.82319093011056 40.51953858115158,-104.83700967095314 40.50707521626648,-104.84928345939991 40.518951354186285))
and geometry is my layer of crop fields, as well-known text:
MULTIPOLYGON(((-104.841309611298 40.5075331998226,-104.84173356681 40.5069932245841,-104.842041204329 40.50640946683,-104.842224948796 40.5057962996657,-104.842280275816 40.5051688207073,-104.842205823049 40.5045424803865,-104.842003423773 40.5039327015263,-104.841678061729 40.5033544995574,-104.841237748411 40.502822112724,-104.840693325791 40.5023486513933,-104.840058199365 40.5019457751149,-104.839348008051 40.5016234053897,-104.838580239118 40.5013894812384,-104.837773797582 40.5012497635973,-104.836948540713 40.501207693373,-104.836124789073 40.5012643066572,-104.83532282616 40.5014182091969,-104.834562398965 40.5016656107496,-104.833862231727 40.5020004184754,-104.833239564888 40.5024143870601,-104.832709730574 40.5028973218633,-104.83228577506 40.5034373300773,-104.831978137541 40.5040211136997,-104.831794393074 40.5046342970926,-104.831739066055 40.5052617810515,-104.831813518821 40.5058881146554,-104.832015918097 40.5064978757385,-104.832341280141 40.5070760506105,-104.83278159346 40.5076084036796,-104.833326016079 40.5080818278834,-104.833961142505 40.5084846673069,-104.834671333819 40.5088070040565,-104.835439102753 40.5090409023397,-104.836245544289 40.5091806037522,-104.837070801158 40.5092226689759,-104.837894552799 40.5091660624086,-104.83869651571 40.509012177646,-104.839456942906 40.5087648031902,-104.840157110143 40.5084300292289,-104.840779776982 40.5080160977709,-104.841309611298 40.5075331998226)))
However, if I perform the same query with a different layer ("soils"), I get an empty result:
The query is the same:
SELECT ST_AsText(ST_Intersection(%(geometries_0)s::geometry, %(geometry)s::geometry))
with a polygon geometries_0 that should overlap:
POLYGON((-104.84627938530097 40.54511058649626,-104.83460641167578 40.545175808723876,-104.84070039055733 40.537283458057615,-104.84627938530097 40.54511058649626))
and a geometry layer representing soils, similar to the crop fields in the above query:
MULTIPOLYGON(((-104.939716 40.258166,-104.939775 40.258174,-104.939963 40.258159,-104.940159 40.258065,-104.940039 40.257671,-104.939917 40.25749,-104.939928 40.257419,-104.94003 40.257404,-104.940265 40.257641,-104.940632 40.257902,-104.940826 40.258061,-104.941051 40.258188,-104.941123 40.258235,-104.941205 40.258283,-104.941246 40.258275,-104.941287 40.258212,-104.941186 40.258094,-104.941186 40.258007,-104.941167 40.257921,-104.941105 40.257858,-104.941044 40.257786,-104.941045 40.257716,-104.941127 40.257676,-104.94122 40.257653,-104.94141 40.257731,-104.941559 40.257671,-104.941255 40.257181,-104.940857 40.256794,-104.940644 40.256478,-104.940319 40.255997,-104.940003 40.255728,-104.939676 40.255561,-104.939419 40.255544,-104.938895 40.255529,-104.938287 40.255512,-104.938046 40.255528,-104.937733 40.255549,-104.937322 40.255533,-104.937012 40.255577,-104.936947 40.255593,-104.936623 40.255774,-104.936581 40.255924,-104.93658 40.256042,-104.936661 40.256223,-104.93671 40.256436,-104.936842 40.256618,-104.937262 40.256753,-104.937662 40.256818,-104.937897 40.257,-104.938181 40.25745,-104.938374 40.257742,-104.938465 40.257931,-104.938782 40.258051,-104.939121 40.258092,-104.939439 40.258133,-104.939716 40.258166)))
I use the postgis ST_AsText function to convert database layers to well-known text, and I checked to make sure that all layers have the EPSG:4326 projection (using the Find_SRID function).
Why would one layer (crop fields) intersect correctly, and another (soils) not? I've tried the same query using geographies instead of geometries, with the same result.
It returns an empty collection because they don't intersect. In fact, they are 32 km away from each other.
SELECT ST_Intersects(A, B), ST_Distance(A, B)/1000 AS dist_km
FROM (
SELECT
'POLYGON((-104.84627938530097 40.54511058649626,-104.83460641167578 40.545175808723876,-104.84070039055733 40.537283458057615,-104.84627938530097 40.54511058649626))'::geography AS A,
'MULTIPOLYGON(((-104.939716 40.258166,-104.939775 40.258174,-104.939963 40.258159,-104.940159 40.258065,-104.940039 40.257671,-104.939917 40.25749,-104.939928 40.257419,-104.94003 40.257404,-104.940265 40.257641,-104.940632 40.257902,-104.940826 40.258061,-104.941051 40.258188,-104.941123 40.258235,-104.941205 40.258283,-104.941246 40.258275,-104.941287 40.258212,-104.941186 40.258094,-104.941186 40.258007,-104.941167 40.257921,-104.941105 40.257858,-104.941044 40.257786,-104.941045 40.257716,-104.941127 40.257676,-104.94122 40.257653,-104.94141 40.257731,-104.941559 40.257671,-104.941255 40.257181,-104.940857 40.256794,-104.940644 40.256478,-104.940319 40.255997,-104.940003 40.255728,-104.939676 40.255561,-104.939419 40.255544,-104.938895 40.255529,-104.938287 40.255512,-104.938046 40.255528,-104.937733 40.255549,-104.937322 40.255533,-104.937012 40.255577,-104.936947 40.255593,-104.936623 40.255774,-104.936581 40.255924,-104.93658 40.256042,-104.936661 40.256223,-104.93671 40.256436,-104.936842 40.256618,-104.937262 40.256753,-104.937662 40.256818,-104.937897 40.257,-104.938181 40.25745,-104.938374 40.257742,-104.938465 40.257931,-104.938782 40.258051,-104.939121 40.258092,-104.939439 40.258133,-104.939716 40.258166)))'::geography AS B
) AS data;
st_intersects | dist_km
---------------+------------------
f | 32.1052124928391
Something with your map is incorrect.
After some debugging (in addition to some helpful troubleshooting steps) I realized that I was building my WKT blobs incorrectly using the ST_AsText function, specifically for my soils layer. As a result, my intersection was not being applied to the entire set of geometries contained within my soils layer.
Currently my soils layer contains a subset of SSURGO soil map units, some of which do not actually contain a geometry. In order to correctly build a text string representing all non-null geometries, I needed to explicitly join the geometries before converting the result to WKT:
SELECT ST_AsText(ST_Union(the_geom)) FROM schema.layer
did the trick.
I Have a table named geofences which stores geometry of Polygon type in column named geometry. I to update the Polygon by removing only one point from the exsisting geometry. For this I Have used the query:
UPDATE gfe_geofences
SET geometry = ST_RemovePoint(geometry, ST_NPoints(ST_GeomFromText(
'POINT(23.1446787840563 96.002746420167)', 0) ) - 1)
WHERE is_active = true
AND ST_IsClosed(the_geom) = true;
But it gives me the error:
ERROR: lwline_deserialize: attempt to deserialize a line which is
really a Invalid type
Can you please help me in updating the geometry.
Thanks In Advance.
ST_RemovePoint will only work with linestrings ( see http://postgis.refractions.net/docs/ST_RemovePoint.html. What I would do, use ST_Boundary to get the boundary of your polygon, call ST_RemovePoint on that, then use ST_MakePolygon to construct a new polygon.