Why ST_Intersection from Postgis returns multilinestring for self-intersecting linestrings? - postgresql

I am trying on PostgreSQL with the extension Postgis to get the geometry of a gps_trace that intersects a box, then i want to get one linestring for each distinct part of the trace in the box. In the following example with 1 trace and 1 box , that would mean ST_intersection returns me a multilinestring with 2 linestrings inside, so that i can extract each of them with ST_Dump()
The geometries are in epsg 4326, I use the request SELECT ST_Intersection(gps_traces.geom, grid.box)
FROM gps_traces, grid
But as a result, i get a multilestring with 34 geometries inside. After zooming a little, i discovered that when the line self-intersects, it seems to consider and register each part as a separate linestring although at the beginning, the trace was a linestring in one go.
I am extremely surprised of this behavior, and didn't find any documentation on the subject nor topics that talked about it, so i'm asking here how is build the geometry resulting from an intersection and why I get this behavior ?
This is the first time i get to use stackoverflow, so I apologize if some elements are missing

Related

Geopoints: From Single Coordinate to Bounds on map

I try to figure out how to come from a single given coordinate (lat/lon) to the nearest bounds which enclose this coordinate on a map e.g. streets or sea.
Here two examples to give you a better understanding of what I mean:
What i tried already or thought about:
Setting up a Nominatim server and search for the given coordinate via the reverse-function to get the bbox and/or the geojson polygon of this coordinate. -> this only works when the given coordinate is within a POI or for example directly on a street.
Writing an algorithm to walk in all 4 or 8 directions (n/e/s/w) and 'stop' when the map layer/surface changes (change = stop for this direction and mark a bounding-point)
Building up an image-recognition system using TensorFlow to detect the different colors and 'draw' the polygon. Worked with TensorFlow a couple of times but this seems to be the most tricky solution to implement (but at my current understanding the most precise one)
Does someone of you have any other ideas to get a solution for this problem? Would appreciate any kind of approaches
Cheers!
If I got your question right, you might wanna first select all polygons in which the given point is inside of using ST_Contains, and then compute the distance to this point using ST_Distance. If you ORDER BY distance and LIMIT to 1 result you'll get the nearest polygon, e.g.
Data Sample
CREATE TABLE t (gid int, geom geometry);
INSERT INTO t VALUES
(1,'POLYGON((-4.47 54.26,-4.44 54.28,-4.41 54.24,-4.46 54.23,-4.47 54.26))'),
(2,'POLYGON((-4.48 54.25,-4.40 54.25,-4.41 54.23,-4.48 54.23,-4.48 54.25))'),
(3,'POLYGON((-4.53 54.23,-4.44 54.29,-4.38 54.22,-4.53 54.23))');
Query
SELECT gid,ST_AsText(geom) FROM t
WHERE ST_Contains(geom,ST_MakePoint(-4.45, 54.25))
ORDER BY ST_Distance(geom,ST_MakePoint(-4.45, 54.25))
LIMIT 1;
gid | st_astext
-----+------------------------------------------------------------------------
1 | POLYGON((-4.47 54.26,-4.44 54.28,-4.41 54.24,-4.46 54.23,-4.47 54.26))
(1 Zeile)

Can't extract geo keys when inserting large polygon

I have been battling this for the past 2 days and can't seem to get it working.
I have the polygon in this gist, which I'm trying to insert into collection with '2dsphere' index on the polygon field. I've gone through quite a few itterations, removing some points from the polygon, trying to sort it so that it's 100% counter-clockwise (which resulted in malformed polygon) and mongo still won't let me insert it. The error I'm seeing is just Can't extract geo keys: without any extra information at the end.
I went for help to geo json validator, which told me, that I need to have the first point at the end of the polygon, but that results in a Edges 0 and 395 cross.. I'm kinda getting hopeless, as I have about 1000 of these polygons from external API and can't go through them 1 by 1. Also the wierd thing is, if I swap latitude with longitude, mongo is able to insert them, but that's not a solution, even the documentation says longitude first. And as can be observed in the gist, pretty much every map I tried can display the polygon and I wasn't able to observe any kind of "disruption" or wierd edges.
I would love if someone could point out what's wrong with the polygon or gime me a nudge in the right direction.
Also this probably shouldn't change anything, but I'm using mongoose and I did try to insert this polygon manualy via the mongo shell.

Creating Postgis Polygon using ST_ConcaveHull from Geometry Points

I have a postgis 2.2 table with 20 columns of type geometry(Point,4326)
I'd like to generate a polygon which covers the outer boundary of the points - it seems like ST_ConcaveHull is a good option, but I can't see how to do it without first converting my points back to text (which seems to be missing the point).
Is st_concavehull the right option, and how do I go about constructing the query?
Thanks!
You first need to collect your points, then pass this collection to ST_ConcaveHull:
ST_ConcaveHull(ST_Collect(geom), 1)
Per the ST_ConcaveHull documentation:
Although it is not an aggregate - you can use it in conjunction with ST_Collect or ST_Union to get the concave hull of a set of points/linestring/polygons ST_ConcaveHull(ST_Collect(somepointfield), 0.80).

Buffering multiple linestrings

I'm pretty new to postgresql, so there might be a pretty simple answer to my question, at least I hope so.
I have imported a table with thousands of single linestrings that represent the main roads of a country.
I'd like to buffer every single one of them and intersect the results with another polygon (Basically just a circle, but the thing is, that the position of the circle is dynamic, depending on the preferences of the user).
However, I don't know how to buffer all linestrings at once. It works just fine when I buffer and intersect just one linestring, but it's kinda crucial that I buffer all of them.
And importing the roads as a multilinestring with SPIT doesn't work at all.
So ... how do I make that happen? Any hints?
I'd really appreciate any help.
The best approach would be to simply add another column that represents the buffers of the roads and add a spatial index, ie,
alter table roads add column road_buffer geometry(POLYGON, SRID);
update table roads set road_buffer = st_buffer(roads, distance);
create index ix_spatial_road_buffer on roads using gist(road_buffer);
where POLYGON and SRID indicate the type and spatial reference ID of the column. You can omit this, although it is good practice to use a specific type and SRID. YOU could also use AddGeometryColumn for the same end.
You can now run a query against the buffered roads, which will be fast, as it is indexed, but return the actual roads, eg,
Select road_id, road from roads where st_intersects(road_buffer, circle);
Now, if you wanted to do it the other way, without actually having a pre-buffered linestring, you could do somthing like,
select road_id, road, road_buffer from
(select st_buffer(road, dist) as road_buffer, road, road_id
from roads where
st_intersects(st_expand(st_envelope(road), dist), circle)
) road_buff
where st_intersects(road_buffer, circle);
The trick here is that you compute the buffer in a subquery, but only for those linestrings/roads whose envelope (ie, minimum bounding rectangle) intersects with your circle -- a much faster calculation than buffering all linestrings. Note, also, the use of st_expand, by the same amount as the buffer distance, which basically expands the mbr and ensures you don't miss any potential candidates. I did a quick test on half a million random lines, and this approach was much faster (10x) than simply checking for circle intersections against the buffer of all points.
Actually I came up with a solution that works just fine.
I just buffered my linestrings externally (used qgis) and reuploaded the entire thing as one big polygon.
However, I'd still like to know how it is done while maintaining the linestring structure.
Both approaches that John Barça suggested would work for me.

How to find all points away from some polygon?

What I need is to find all points away from rectangle for 10km. Points geometry is the_geom1, rectangles (polygon) geometry is the_geom2. SRID of them is 4258.
I tried:
SELECT *
FROM table1,table2
WHERE ST_DWithin(table1.the_geom1,table2.the_geom2,10000)
and table1.gid=2;
But the result is not Ok. I get way too many results (everything is returned).
What am I doing wrong?
Your query should work. The big issue may be as described in https://gis.stackexchange.com/questions/32711/how-do-i-use-st-dwithin-with-meters which discusses unit conversion issues.
You may have an issue with unit selection or configuration.
If you are telling it, for example, that the geometries must be within 10000 miles, you would get just about everywhere. Even 10000km would likely return everything on the same continent.