How to filter points in postgres? - postgresql

I have a table with points in the Postgres. The points are from the flight path. I need to filter out some points.
.
My question would be how can I select only points which are in line and then make a line from the selected points only if parallel lines are in no more then 20m distance in between lines. Turning points should be ignored.
What I have done so far is to select points that are in one line
WITH routes as (
SELECT
geom,
heading-lag(heading) over (order by time) AS direction
FROM mytable
)
SELECT direction, geom
FROM routes WHERE direction between -10 AND 10;
In my query, I calculated direction from heading, and selected points with a minor difference in the heading.
However, I don't know how to continue.
EDIT
Link to fiddler data table http://sqlfiddle.com/#!17/3262c/9/0
With my query from above, I can filter the points which are marked in red lines. How can I add those points in variables like line1=...
line2=... line3=... line4=... and line5=... ?
Thank you for any help.

Related

how to perform a selective ST_Split?

I need to cut different lines with an identical geometry but different attributes (eg. colour) with a set of points. The points also have the attribute colour.
My knife points should only cut the lines with the same colour value. Red points should cut only red lines, green points should only cut green lines and so on...
I tried the following:
with knife as(
select st_union(geom) as geom, colour
from points
group by colour)
select lines.colour,(st_dump(st_split(lines.geom,knife.geom))).geom as geom
from lines, knife
where lines.colour=knife.colour
Sadly, my 'selective knife' isn't so selective and cuts all lines regardless of their colour.
Can anybody help?
Edit:
#JimJones I couldn't find a SQL-fiddle that supports the PostGIS extension. But with my data sample the knife somehow works perfectly.
I have no idea why whats wrong with my real data. The real data lines are in fact multilinestrings, could that be a problem? (I somehow struggling in creating multilinestrings with the insert-statement)
Edit2:
found a fiddle with PostGIS
db<>fiddle here
create table points(
id serial,
colour varchar,
geom geometry(point,4326)
);
create table lines(
id serial,
colour varchar,
geom geometry(linestring,4326)
);
insert into lines(colour, geom)
VALUES
('red','linestring(1 1,10 1)'),
('green','linestring(1 1,10 1)'),
('blue','linestring(1 1,10 1)');
insert into points(colour, geom)
VALUES
('red',(st_makepoint(2,1))),
('red',(st_makepoint(4,1))),
('red',(st_makepoint(6,1))),
('red',(st_makepoint(8,1))),
('green',(st_makepoint(2.5,1))),
('green',(st_makepoint(5,1))),
('green',(st_makepoint(7.5,1))),
('blue',(st_makepoint(3,1))),
('blue',(st_makepoint(6,1))),
('blue',(st_makepoint(9,1)));
with knife as(
select st_union(geom) as geom, colour
from points
group by colour)
select lines.colour,(st_dump(st_split(lines.geom,knife.geom))).geom as geom
from lines, knife
where lines.colour=knife.colour
ยดยดยด
[1]: https://dbfiddle.uk/?rdbms=postgres_12&fiddle=8642640bb690dfee7d31006a673e2dcf
Disclaimer: Im a postgres beginner. Even though I'm quite sure that I found the solution to my problem, there could be something wrong. So feel free to correct me if necessary
If you want to ST_Split a line, which you formerly merged by using ST_Union, you sould use ST_Linemerge before the ST_Split and ST_Dump.
Even after a ST_Union, PostGIS seems to 'remember' that theese lines were formerly playing for different teams. So when you ST_Slit with you new knife and ST_Dump the GeometryCollection, the linestring is cut at the 'old soldering points' as well.
If you ST_Linemerge after the ST_Union, PostGIS seems to iron out theese connection points and you can safely use your knife.
In this fiddle, I created 2 linetypes and some knife points. There is one solid line (blue) and some yellow line segments which are partly overlapping but all together have the same spatial extent as the blue line.
I used ST_Union and ST_Collect respectively (grouped by colour) to merge the yellow line segments into one single line (with no effect on the blue line, obviously).
In a second step I splitted and dumped the lines again with my knife points, one time with st_linemerge and one time without st_linemerge for the 'unioned' und 'collected' lines respectively.
The results (I counted the number of new segments and the cummulated line length for each colour) show, that only the split after the linemerged st_union gives the correct result. Using only St_Union results in the right length, but the number of linesegments is wrong. ST_Collect will keep the formerly overlapping parts,so the length as well as the number of segments are not usefull at all(for my purpose).

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.

Convert Points to Polygon using PostGIS from a table with multiple points for one attribute

I want to create a polygon table using PostGIS. Each row intest_table has points x and y. Table 'test_table' has the location information of points which is the column origin.
I tried this
SELECT ST_MakePolygon(ST_MakeLine (432099.197021 , 6736122.29126 , 432099.197021 , 6747306.948242 , 427835.719238 , 6747306.948242 , 427835.719238 , 6736122.29126, 23031));
FROM test_table
where origin = '126af84e-0a9b-407d-8036-1ffc316106dd'
XMAX,YMIN
XMAX,YMAX
XMIN,YMAX
XMIN,YMIN
No luck I was wondering if someone can explain it better to me
and is it possible to add a bounding box to the geometry? for all my attributes with points
You can make a line either from array of points or from WKT representation, and if you want to convert it to polygon the last point of the line should be the same as the first one (so that the polygon is closed). If I understand correctly you'd like to build bounding boxes for point clouds that share the same value of origin. This might be done like that:
with
bounds as (
select
origin
,min(x) as xmin
,min(y) as ymin
,max(x) as xmax
,max(y) as ymax
from test_table
group by 1
)
select
origin
,st_makepolygon(st_makeline(array[
st_makepoint(xmin,ymin)
,st_makepoint(xmax,ymin)
,st_makepoint(xmax,ymax)
,st_makepoint(xmin,ymax)
,st_makepoint(xmin,ymin)
]))
from bounds

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.

Finding Records in a Radius postgresql

I am not sure what wrong with below query:
SELECT id, earth_distance(ll_to_earth( 41.273147, -75.896858 ),
ll_to_earth(business_address_latitude, business_address_longitude)) as distance_from_current_location FROM events
WHERE earth_box( ll_to_earth(41.273147, -75.896858), 20000.00) #> ll_to_earth(business_address_latitude, business_address_longitude);
as trying to search the records in the radius of 20000 but as i checked the result it give me the records which is more then 20000 mtr distance like 24286 meter distance.
I am not sure whats wrong at the above query.
Any suggestion plz.
There is nothing wrong, you're just using the box instead of circle so it's normal. The manual states clearly:
Some points in this box are further than the specified great circle
distance from the location, so a second check using earth_distance
should be included in the query.
So just select the points that have distance <=20000 in the an outer query.