Postgresql geometry circle instersection - postgresql

I'm trying to know if a circle "cross" another circle in postgreSQL (i.e: 2 circles meeting on 2 points). I'm trying intersection, but does not work :
select circle '((0,0),2)' ?# circle '((1,1),2)';
Result :
Error in query: ERROR: operator does not exist: circle ?# circle
Don't know why... What should I do ?

The ?# operator does not work with circle, but you can use the && operator (From the docs: Overlaps? One point in common makes this true).
You can use the && operator also with circle, without casting to polygon:
select circle '((0,0),2)' && circle '((0,4),2)'; -- true
select circle '((0,0),2)' && circle '((0,4),2.0001)'; -- true,
select circle '((0,0),2)' && circle '((0,4),1.99999)'; -- false
See also http://www.postgresql.org/docs/9.1/static/functions-geometry.html

Ok, I've found:
select polygon(circle '((0,0),2)') && polygon(circle '((1,1),2)');
I "only" have to cast the two circles into 12-point polygon, then use the && (overlaps) operator.

Related

Buffers (Circle) in PostGIS

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

leaflet Check if there is a circle already on map

I wanna know for example if a circle is already on map ?
let circle = L.circle([lat, lng], quake.size);
map.hasLayer(circle);
doesn't work, always returns false even if we already have this circle on map
always returns false even if we already have this circle on map
No, it doesn't.
http://playground-leaflet.rhcloud.com/mum/edit?html,console,output

search for points within a polygon, postgis

I'm trying to find a coordinate in a polygon coordinate, but can not get it to work. How should I?
Points coordinate in table "location" column "latlon":
A: 60.2653608 -3.6923519
B: 60.241668 -3.652401
SELECT latlon, st_contains(latlon, ST_GeomFromText('MULTIPOLYGON(((60.237949 -3.654019,
60.240247 -3.661016,
60.243500 -3.658463,
60.240127 -3.642761,
60.240127 -3.642761)))', 4326)) FROM location
The documentation says:
boolean ST_Contains(geometry geomA, geometry geomB);
St_Contains Returns TRUE if geometry B is completely inside geometry A
Also, you must reverse the order of the arguments: FIRST the polygon, THEN the point

How to find LINESTRINGs that touch in a begin/ending node

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.

Postgresql Update Polygon Geometry using ST_removePoint

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.