Buffering multiple linestrings - postgresql

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.

Related

POSTGIS: Dissolve Multi-polygons to enable joined classification

I have a number of spatial database, through which I have identified particular types of land-cover. The topographic layer [defining land-cover] is made up of multi-polygons and I am using a separate point layer in order to join a classification type to it. However, the areas portrayed in the topographic layer may be formed from several individual polygons, without a total perimeter outline to identify the area. Therefore, the classification point may sit in just one individual polygon of the overall area [see below].
Example. Image is of a park, which consists of over 20 individual polygons. The point that classifies the area as a park sits within one of the polygons and cannot be attached to the entire area.
I would like to be able to apply the point based classification to the whole park area. I have tried to use ST_UNION function in order to do such, but have been unable. Does anyone know of a way to dissolve the area into a single shape/remove the pathways? This is a small example of a much larger data set, where there is little scope of manually defining area sand buffers in order to classify the data, thus I wondered if there was a practicable solution.
If anyone can help, it would be hugely appreciated....
SELECT ST_Collect(t.the_geom) as singlegeom FROM TABLE t; http://postgis.net/docs/ST_Collect.html

Does using the Overpass polygon query have a computational advantage over a bounding box?

For a project on geospatial data analytics, we are currently extracting road type and speed limit data of certain roads along a track by using Overpass' polygon query (where we define the roads by a buffer zone around them). The problem is that in the case of separate tracks, we can end up with disconnected polygons which often lead to a significant increase in computation time. In this situation, we were wondering how Overpass' polygon query actually works. Does the algorithm actually query only the data inside this polygon/these polygons, or does it query inside a bounding box, after which it filters out the data inside the polygons?
The algorithm checks if nodes are inside the defined polygon, or if a way crosses the polygon. It's not based on bounding boxes as you mentioned.
From your description it's not quite clear why disconnected polygons pose an issue. You should get decent performance with a lz4-based backend and a reasonable number of lat/lon pairs in your (poly: ) filter (the more pairs you provide, the more expensive the computation gets).
BTW: The best approach to tackle this issue would be something I described in this blog post: https://www.openstreetmap.org/user/mmd/diary/42055 - unfortunately, this feature is not yet available in the official branch. If you see some use for it, please upvote here: https://github.com/drolbr/Overpass-API/issues/418

Check intersections between points and polygons in QGIS

I have two data layers, one with points and one with polygons. Both layers have ID's and I would like to check whether the points with ID x lay inside or outside the polygon with ID x.
Does someone know how to do this?
Thanks,
Marie
One potential solution which gives you a comma separated list in the python console is to run a small script from the python console:
mapcanvas = iface.mapCanvas()
layers = mapcanvas.layers()
for a in layers[0].getFeatures():
for b in layers[1].getFeatures():
if a.geometry().intersects(b.geometry()):
print a.id(),",",b.id()
This should produce a result of cases where one feature intersects the other. The order of the layers did not matter in my testing, however, both layers had to use the same coordinate reference system, so you might need to re-project your data if both layers have different reference systems. This worked for points in polygons and polygons intersecting polygons (I'm sure it would work with lines as well).
Answers such as this: https://gis.stackexchange.com/questions/168266/pyqgis-a-geometry-intersectsb-geometry-wouldnt-find-any-intersections may help with further refinement of such a script, and was a primary source on this answer.

How do I optimize point-to-circle matching?

I have a table that contains a bunch of Earth coordinates (latitude/longitude) and associated radii. I also have a table containing a bunch of points that I want to match with those circles, and vice versa. Both are dynamic; that is, a new circle or a new point can be added or deleted at any time. When either is added, I want to be able to match the new circle or point with all applicable points or circles, respectively.
I currently have a PostgreSQL module containing a C function to find the distance between two points on earth given their coordinates, and it seems to work. The problem is scalability. In order for it to do its thing, the function currently has to scan the whole table and do some trigonometric calculations against each row. Both tables are indexed by latitude and longitude, but the function can't use them. It has to do its thing before we know whether the two things match. New information may be posted as often as several times a second, and checking every point every time is starting to become quite unwieldy.
I've looked at PostgreSQL's geometric types, but they seem more suited to rectangular coordinates than to points on a sphere.
How can I arrange/optimize/filter/precalculate this data to make the matching faster and lighten the load?
You haven't mentioned PostGIS - why have you ruled that out as a possibility?
http://postgis.refractions.net/documentation/manual-2.0/PostGIS_Special_Functions_Index.html#PostGIS_GeographyFunctions
Thinking out loud a bit here... you have a point (lat/long) and a radius, and you want to find all extisting point-radii combinations that may overlap? (or some thing like that...)
Seems you might be able to store a few more bits of information Along with those numbers that could help you rule out others that are nowhere close during your query... This might avoid a lot of trig operations.
Example, with point x,y and radius r, you could easily calculate a range a feasible lat/long (squarish area) that could be used to help rule it out if needless calculations against another point.
You could then store the max and min lat and long along with that point in the database. Then, before running your trig on every row, you could Filter your results to eliminate points obviously out of bounds.
If I undestand you correctly then my first idea would be to cache some data and eliminate most of the checking.
Like imagine your circle is actually a box and it has 4 sides
you could store the base coordinates of those lines much like you have lines (a mesh) on a real map. So you store east, west, north, south edge of each circle
If you get your coordinate and its outside of that box you can be sure it won't be inside the circle either since the box is bigger than the circle.
If it isn't then you have to check like you do now. But I guess you can eliminate most of the steps already.

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.