How to fill in gaps between polygons using postgis functions - postgresql

I have a similar case as shown in the below question.
https://gis.stackexchange.com/questions/293695/filling-gaps-between-polygons-using-qgis
That solution uses qgis, but I want to use a postgis function on a table on the geometry column. The solution talks about convex hull but not sure how to use the convex_hull postgis function here. I want to fill the gap by moving/merging the gap to the neighboring polygon.

As long as you have a column to group them by (e.g., "postal_code"), you can do:
SELECT
st_convexhull(st_collect(geom_column))
FROM
my_geom_table
GROUP BY
grouping_column -- e.g., "postal_code"

Related

How to run st_difference for complete table?

I have 2 postGIS tables CITIES and WATERBODIES, I want to remove waterbody geometry from cities, I'm trying to use
CREATE TABLE usa_No_water_100 AS
SELECT ST_Difference(usa_100.geom, water_100.geom) AS geom
FROM usa_100, water_100
but this creates a table with 10000 entries, I'm looking for the same 100 rows which I have in cities shape but with waterbodies geometry subtracted.
Geometry layer is as follows
Water layer is as follows
I want to remove the cities shape which is under the water shape, so that geometry will be reduced
PS: I'm open to doing this via python as well, if you have any suggestions
You can to compare the geometries of usa_100 with water_100 table using ST_Difference as you suggested, but to avoid getting the product of both tables you have to put one in a subquery or CTE, e.g.
WITH j (geom) AS (
SELECT ST_Union(geom) FROM water_100
) SELECT ST_Difference(usa_100.geom,j.geom)
FROM usa_100,j
Note: keep in mind what the ST_Difference documentation says:
If A is completely contained in B then an empty geometry is returned.
So, if a polygon on usa_100 entirely lies on a the result of ST_Union of water_100, it will return an empty geometry. If they do not spatially overlap, you do not have to worry about it.

How to merge disjoint polygons into a single polygon in Postgis using Postgresql

I have a table with polygon geometries. The polygons are separate to each other like the picture below:
I want to get a single polygon formed after merging these polygons using Postgresql. Below is the expected polygon:
Please ignore the buffer in boundaries of red polygon, it is just to make the picture clearer.
My polygon table has two columns, id and geom. I have tried using ST_Collect, ST_MakePolygon, and ST_ExteriorRing but using these I only get MULTIPOLYGON having these polygons as it is. I need a single polygon. Any help would be appreciated.
You can use similar SQL to this
SELECT
ST_ConcaveHull(
ST_Collect( ARRAY(
select
"Poly"
from table_name
where "OBJECTID" in (5,15,2)
)
),0.99
)
and add some pic to better illustrate

Trying to figure out how to clip a vector with another vector (a rectangle box) using postgis

Technologies: PostGIS, QGIS
I have a vector box named "study_area", and another vector data "floodplain". Now I need to clip the floodplain vector data to produce a floodplain layer that is within in the study area. I am required to use postgis, writing queries for this specific job.
However, I checked the doc, it seems like the st_clip function only works for rasters.
Here is my attempt:
select r.geom as clipped
from study_area as s, usrname."Regulatory_Floodplain" as r
where st_within(r.geom, s.geom) or st_intersects(s.geom, r.geom)
The problem is that it is not entirely in the box:
Any alternatives? Any help will be appreciated, thanks!
You probably want ST_Intersection function, something like
select st_intersection(r.geom, s.geom) as clipped
from study_area as s, usrname."Regulatory_Floodplain" as r
where st_intersects(s.geom, r.geom)

How to find all points within polygon in postgis?

I have locations stored in location_table (point_location geometry), now i draw a polygon on google map and pass that polygon (geometry) to backend, I want to find all the locations that are within that polygon.
SELECT POINT_LOCATION
FROM LOCATIONS_TABLW
WHERE ST_Contains(GeomFromEWKT(?), POINT_LOCATION);
This is giving me random results when I pass the polygon from google maps to backend. Its not giving me all points that are exactly within the polygon. It gives me points that are even outside the polygon.
What is the correct way to find all points within polygon in postgis with accuracy (including border cases also)
Update :
we tried with st_intersects() it did not work as well.
UPDATE
Please find below queries
SRID=4326;POLYGON((-103.30549637500008 20.852735681153252,-103.08103481249998 20.612974162085475,-101.6261045 20.537532106266806,-99.83567868749998 20.395877027062447,-99.80306537500002 22.0572706994358,-99.64994812500004 28.918636198451633,-121.1212769375 8.69559423007209,-103.30549637500008 20.852735681153252))
SRID=4326;POINT(-103.496956 20.722446)
SRID=4326;POINT(-103.4955 20.723544)
select ST_Intersects(GeomFromEWKT('SRID=4326;POINT(-103.496956 20.722446)'), GeomFromEWKT('SRID=4326;POLYGON((-103.30549637500008 20.852735681153252,-10
3.08103481249998 20.612974162085475,-101.6261045 20.537532106266806,-99.83567868749998 20.395877027062447,-99.80306537500002 22.0572706994358,-99.64994812500004 28.918
636198451633,-121.1212769375 8.69559423007209,-103.30549637500008 20.852735681153252))'));
This Should Return False, but it's returning true.
You can use
SELECT POINT_LOCATION
FROM LOCATIONS_TABLE
WHERE ST_Contains(ST_GEOMFROMTEXT('POLYGON((P1.X P1.Y, P2.X P2.Y, ...))'), LOCATIONS_TABLE.POINT_LOCATION);
Note: Polygon must be closed (that means the last coordinate == first coordinate). Second parameter POINT_LOCATION must be the geometry column in your point table.
UPDATE:
I have tried to replay your steps in my pg database. I created 2 tables, LOCATIONS_TABLE (id, geom) and POLYGON (id, geom). After that i filled the LOCATIONS_TABLE with the 2 points
SRID=4326;POINT(-103.4955 20.723544)
SRID=4326;POINT(-103.496956 20.722446)
After that i inserted the polygon in the POLYGON table
SRID=4326;POLYGON((-103.305496375 20.8527356811533,-103.0810348125 20.6129741620855,-101.6261045 20.5375321062668,-99.8356786875 20.3958770270624,-99.803065375 22.0572706994358,-99.649948125 28.9186361984516,-121.1212769375 8.69559423007209,-103.305496375 (...)
I visualized the situation in qgis, see picture below:
As you can see, the 2 points are inside the polygon. So i manually created a point outside the polygon. After that, you can use the following sql query, to see if the points are inside the polygon:
SELECT ST_Contains(polygon.geom, point.geom)
FROM public."LOCATIONS_TABLE" point, public."POLYGON" polygon
It returns t for the 2 points inside and false for the third point.

Postgres spatial index for LAB colours?

I have a Postgres database containing photographs and I want to let people search them by colour. I already have multiple colours (1-5) defined for each photograph, and I'm using LAB colours (perceptual colour space, defined in three dimensions: lightness plus two colour dimensions).
My question is: what is the best way to do this in Postgres? It's essentially a three-dimensional search, so should I use a spatial index?
My requirements are:
run a bounding box search by colour (find photos with colours within distance X of colour Y).
rank results by distance from colour X (return photos with colours closest to colour Y first)
r-tree-like performance.
I've built a proof-of-concept using an rtree index in Python, and it's working pretty well. I'm just not sure how to replicate it using Postgres tables.
I see a couple of options. PostGIS has multi-dimensional geometry types which may give exactly what you are looking for. You could do bounding boxes over 3d points, for example. That would be easiest.
PostGIS is a Geospacial add-on but it can be used for a large number of other things too. What you are looking at doing is spacial even if not GIS and this may be the best tool for the job. PostGIS would handle all your indexing needs also including distance searches and the like.
If this is not acceptable you could write your own types. You'd probably want to write GiST operators as well for them and there is a fairly large learning curve there.