postgis st_contains not seems - postgresql

I am new to postgis and I cant figure out why this returns false(in the ST_contains function) for any value I try in the point
select st_astext(geoma),
st_astext(geomb),
st_contains(geoma,geomb)
from (
select
ST_GeomFromGeoJSON('{"type":"Polygon","coordinates":[[[25.64214,-100.27873]],[[25.69505,-100.37006]],[[25.72599,-100.27702]],[[25.680978320466,-100.25384240723]]],"crs":{"type":"name","properties":{"name":"EPSG:4326"}}}') as geomA,
ST_GeomFromGeoJSON('{"type":"Point","coordinates":[25.683096, -100.311577]}') as geomB
) as p
I drew the points in google maps to confirm my data supposedly, but it returns false when according to google maps it should be true

The GeoJSON has several errors, and does not conform to the specification, such as:
You need to flip the axis order to (X Y) or (lng lat). It might not matter now, but it will if you try to do anything else.
The LinearRing for the Polygon is really broken, and needs to consist of a single sequence of closed coordinates.
The CRS property is provided for one geometry but not the other, which would normally raise a "Operation on mixed SRID geometries" error from PostGIS. Provide the CRS for both or none of the geometries.
Try this:
SELECT ST_AsText(geomA),
ST_AsText(geomB),
ST_Contains(geomA, geomB)
FROM (
SELECT
ST_GeomFromGeoJSON('{"type":"Polygon","coordinates":[[[-100.27873,25.64214],[-100.37006,25.69505],[-100.27702,25.72599],[-100.25384240723,25.680978320466],[-100.27873,25.64214]]],"crs":{"type":"name","properties":{"name":"EPSG:4326"}}}') AS geomA,
ST_GeomFromGeoJSON('{"type":"Point","coordinates":[-100.311577,25.683096],"crs":{"type":"name","properties":{"name":"EPSG:4326"}}}') AS geomB
) AS p;
-[ RECORD 1 ]----------------------------------------------------------------------------------------------------------------------------
st_astext | POLYGON((-100.27873 25.64214,-100.37006 25.69505,-100.27702 25.72599,-100.25384240723 25.680978320466,-100.27873 25.64214))
st_astext | POINT(-100.311577 25.683096)
st_contains | t

Related

input geometry has unkown(0) geometry (Although st_transform is used)

I have 2 tables:
A table with 3 fields:
id (text)
geom (geometry)
select ST_SRID(geom)
from A
where geom is not null
result: 32636
B table with 2 fields:
name (text)
geom (geometry)
select ST_SRID(geom)
from B
where geom is not null
result: 0
A.geom contains polygons
B.geom contains points
I want to get all the distances between A.id, A.geom and B.geom.
I tried with:
select id, st_distance(a.geom, ST_Transform(b.geom, 32636)) as dist
from A as a, B as b
where a.geom is not null
group by id, a.geom, b.geom
order by dist desc
But I'm getting error:
"input geom has unkown(0) SRID"
How can it be if I'm using ST_Transform ?
How can I fix it ?
The error message is talking about the SRID of the argument to ST_Transform, which is 0. The message means that the function has no idea in which coordinate system the point is, so it cannot transform it to another coordinate system.
The documentation says:
ST_Transform is often confused with ST_SetSRID. ST_Transform actually changes the coordinates of a geometry from one spatial reference system to another, while ST_SetSRID() simply changes the SRID identifier of the geometry.
That seems to be the case here.
You should probably use ST_SetSRID to interpret b.geom in SRID 32636.

PostGIS Query always brings back all results

I'm playing with PostGIS for the first time and I'm getting all the results back regardless of the distance I use on a distance query. My data looks like this:
Id GeoLocation
8eb63480-4d63-11ea-b06a-8c1645ef6ad2 POINT (52.6323202 1.2947649)
a0f2dde6-4d64-11ea-b06a-8c1645ef6ad2 POINT (52.6294342 1.2936336)
a0f2dde7-4d64-11ea-b06a-8c1645ef6ad2 POINT (52.6277909 1.2909079)
a0f2dde8-4d64-11ea-b06a-8c1645ef6ad2 POINT (52.6260535 1.2952051)
And when I run a query for a point that should be over a mile away:
SELECT * FROM "Locations" WHERE ST_DWithin("GeoLocation", 'POINT(52.6219322 1.2630061)', 1);
I get all of the rows back. My understanding is that the distance parameter should be in metres, so I shouldn't get any results back.
Could it be coordinate format issue? What am I missing?
Using parameters of type geography you get the returned distance in meters, therefore you need to convert it to miles in case you prefer to work with this unit of measurement. If you can cope with degrees, just stick to geometry.
WITH locations (geolocation) AS (
VALUES ('POINT (52.6323202 1.2947649)'),
('POINT (52.6294342 1.2936336)'),
('POINT (52.6277909 1.2909079)'),
('POINT (52.6260535 1.2952051)')
)
SELECT *
FROM locations
WHERE ST_DWithin(
geoLocation::geography,
'POINT(52.6219322 1.2630061)'::geography, 1609*2.2) ;
geolocation
------------------------------
POINT (52.6294342 1.2936336)
POINT (52.6277909 1.2909079)
(2 Zeilen)
EDIT: #JGH pointed out that ST_Distance does not use a spatial index and my previous suggestion was to use it instead of ST_DWithin. It means I was wrong with my preference for ST_Distance :) Here is anyway how to achieve similar results with ST_Distance for those still willing to use it:
WITH locations (geolocation) AS (
VALUES ('POINT (52.6323202 1.2947649)'),
('POINT (52.6294342 1.2936336)'),
('POINT (52.6277909 1.2909079)'),
('POINT (52.6260535 1.2952051)')
)
SELECT *
FROM locations
WHERE ST_Distance(
geoLocation::geography,
'POINT(52.6219322 1.2630061)'::geography) * 0.000621371 > 2.2 ;
geolocation
------------------------------
POINT (52.6323202 1.2947649)
POINT (52.6260535 1.2952051)
(2 Zeilen)
Further reading: Getting all Buildings in range of 5 miles from specified coordinates
Since these seem to be coordinates in longitude and latitude, you should use the geography data type.

Postgis nearest coordinates

I'm trying to make a REST service that returns a list of places ordered by distance from the user coordinate. I found this query using postgis:
SELECT *
FROM your_table
ORDER BY your_table.geom <-> "your location..."
LIMIT 5;
But I'm not able to apply this to my actual database. I have a table that contains these columns:
title, address, description, latitude, longitude
all these values as Strings.
I'll be very happy if someone help me. Thx!
I dont know why, but ORDER BY <-> isnt exact. Sometime the closest link is on the 3rd position. So I get 101 element and then use distance to selected the closest one.
CREATE OR REPLACE FUNCTION map.get_near_link(
x numeric,
y numeric)
RETURNS TABLE(Link_ID int, distance int) AS
$BODY$
DECLARE
strPoint text;
BEGIN
strPoint = 'POINT('|| X || ' ' || Y || ')';
With CTE AS (
SELECT Link_ID,
TRUNC(ST_Distance(ST_GeomFromText(strPoint,4326), geom )*100000)::integer as distance
FROM map.vzla_seg S
ORDER BY
geom <-> ST_GeomFromText(strPoint, 4326)
LIMIT 101
)
SELECT *
FROM CTE
ORDER BY distance
LIMIT 5
In order to use PostGIS you have to enable the extension in the database. Ideally, you just run the CREATE EXTENSION postgis; command and it works. NOTE form the install page: DO NOT INSTALL it in the database called postgres. For more information visit the site.
Adding a geometry column (spatial data can be stored in this type of columns) to your table:
SELECT AddGeometryColumn(
'your_schema',
'your_table',
'geom', -- name of the column
4326, -- SRID, for GPS coordinates you can use this, for more information https://en.wikipedia.org/wiki/Spatial_reference_system
'POINT', -- type of geometry eg. POINT, POLYGON etc.
2 -- number of dimension (2 xy - 3 xyz)
);
UPDATE yourtable t SET t.geom = ST_SetSRID(ST_MakePoint(t.x, t.y), 4326)
-- the x and y is the latitude and longitude
Now you can use spatial queries on your table like this:
SELECT
*
FROM
your_table
ORDER BY
your_table.geom <-> ST_SetSRID(ST_MakePoint(x, y), 4326)
LIMIT 5;
NOTE: as others mentioned, below PostgreSQL 9.5 <-> isn't always reliable.

Selecting and ordering by distance with GeoAlchemy2. Bad ST_AsBinary wrap

I'm trying to select and order stores by their distance to a point with GeoAlchemy2 / PostGIS but for some reason I keep getting an error.
It seems GeoAlchemy2 wraps things with ST_AsBinary, but when I try to select the distance it tries to wrap the result of the distance calculation. I have no idea how to fix this.
I use this ORM query.
distance = (
Store.coordinates.cast(Geometry)
.distance_centroid(query_centroid)
.label('distance')
)
stores = stores.order_by(distance).add_columns(distance)
The model.
class Store(db.Model):
__tablename__ = 'stores'
store_id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
address_details = db.Column(db.String)
coordinates = db.Column(Geography('POINT'))
The error I get.
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) function st_asbinary(double precision) does not exist
LINE 1: ...Binary(stores.coordinates) AS stores_coordinates, ST_AsBinar...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
[SQL: 'SELECT stores.store_id AS stores_store_id,
stores.name AS stores_name,
stores.address_details AS stores_address_details,
ST_AsBinary(stores.coordinates) AS stores_coordinates,
ST_AsBinary(CAST(stores.coordinates AS geometry(GEOMETRY,-1)) <-> ST_GeomFromEWKT(%(param_1)s)) AS distance
FROM stores ORDER BY distance']13 -46.730347)'}]
[parameters: {'param_1': 'POINT(-23.3569
The problem is precisely in this part...
ST_AsBinary(
CAST(stores.coordinates AS geometry(GEOMETRY,-1))
<->
ST_GeomFromEWKT(%(param_1)s)
) AS distance
Notice how ST_AsBinary wraps the distance between the two points instead of wrapping just the geom, for example? (I'm not sure it should wrap the geom in this case, either)
Can anyone help? I just want to know how far things are.
An average user at freenode answered it for me.
GeoAlchemy2 will convert columns of type Geometry if they are in the select statement. Even though the result of the distance expression is a double, and not a Geometry, GeoAlchemy2 isn't smart enough to figure that out.
The column needs to be explicit cast in the ORM.
The fixed query:
distance = (
Store.coordinates.cast(Geometry)
.distance_centroid(query_centroid)
.cast(db.Float)
.label('distance')
)
stores = stores.order_by(distance).add_columns(distance)

PostgreSQL select query to extract latitude and longitude from a point

What SELECT query should be used to extract latitude and longitude from a point?
I cannot use PostGIS.
Example point (point type value) stored in the database:
my_point
--------------
(50.850,4.383)
Expected result after executing the query:
lat | lng
---------------
50.850 | 4.383
The query below works fine but it does not look efficient.
SELECT
split_part(trim(my_point::text, '()'), ',', 1)::float AS lat,
split_part(trim(my_point::text, '()'), ',', 2)::float AS lng
FROM my_table;
Always Read The Fine Manuals
It is possible to access the two component numbers of a point as though the point were an array with indexes 0 and 1. For example, if t.p is a point column then SELECT p[0] FROM t retrieves the X coordinate and UPDATE t SET p1 = ... changes the Y coordinate. In the same way, a value of type box or lseg can be treated as an array of two point values.
Another option would be:
SELECT
ST_X(point) as longitude,
ST_Y(point) as latitude
FROM your_table_name