Posts Tagged ‘PostGIS’

How to use the new distance related functions in PostGIS Part1

Sunday, February 7th, 2010

As described earlier there is also some new distance related functions in new PostGIS release. Since I am in some way responsible for their existance I feel a need to give some examples of how they can be used.

Example 1 Snap GPS-points to roads

If collecting GPS-points along a road you will get them placed on the side of the roadline because of the inaccurancy of the GPS and the road on the map. One way to get the points on the road is to use ST_Closestpoint.

We have a table with our roads called ….. roads (why not) and another table called gpspoints with pour GPS points. The gepspoints are as expected placed, not on the road, but next to the road. There is also a GPS point that probably have been collected when walking in the forest since it is to far away from the road.


roads and GPS points

Now lets do a first attempt to move the points to the roads. We do:

Select ST_Closestpoint(a.the_geom, b.the_geom) as the_geom
from roads a inner join gpspoints b
on ST_Dwithin(a.the_geom, b.the_geom, 100);

We count on that no GPS points should be more than 100 meters away from the road if it is collected from the road. That much error should never be from the GPS, but it is possible if it is just started and so on. The result from our query will be the green dots below:


Gps Points moved to road 1

But there is a problem. Not the point out in the forest. That one we have abandoned since it is more than 100 meters from the road. But the point between two road parcels a little bitdown from the middle of the map. That GPS point did get two new points insted of just one. What has happened is that every road feature closer than 100 meters of a GPS point has had a point from that GPS point.

This can be solved by collecting all road features that is within those 100 meters from the GPS point into a geometry collection which we put into the ST_Closestpoint function. Since grouping by geometries often is a bad idea we group by the id of the road features but also group by the geometriy just to avoid the need of aggregating also the GPS points. The query will look something like:

Select ST_Closestpoint(ST_Collect(a.the_geom), b.the_geom) as the_geom
from roads a inner join gpspoints b
on ST_Dwithin(a.the_geom, b.the_geom, 100)
group by b.gid, b.the_geom;

and the result will be, again like the green dots:


roads3

That’s better. Now it looks like expected.

Shortest line and other new functionality in PostGIS 1.5

Tuesday, December 22nd, 2009

One and a half year ago I found PostGIS. I did fast become a fan. Handling spatial data with sql is a wonderful way of doing it. PostGIS also have a great amount of functionality and if something is missing no one will be stopped from creating that functionality. When I realized that I understood that I no longer could complain about a functionality I have missed in other GIS systems. I have done some avenue scripting in Arcview 3.x and solved a lot of tasks that way. But I have missed an easy way to get the information about between which points the distance-function gets that min distance.

Let’s say you are working with linestrings of rivers and you want to know how close a linestring that represents a road is to that river. Ok, the distance-function tells you that the minimum distance is 20 meters. Great, but the next question will be, where. Where is the road only 20 meters away from the river. In a couple of times I have wanted that information and I have always imagined that the information have to be somewhere in there, in the function. To find the minimum distance you first have to identify where to measure, was my thought. That was partly right I found.

That’s the great thing about open source, if you are wondering how it is done the code is there to read. Since I have never studied C before I didn’t have very high expectations of understanding anything. But from quite good commenting and clean structure I successes to put this together
http://www.jordogskog.no/distance.html
The minimum distance between to geometries have to be between two vertexes or between one vertex and one edge. The distance calculation iterated through the vertexes and edges defining the inputted geometries comparing their relations one by one. How to find the distance between two vertexes is just done with the Pythagorean theorem. Little bit worse is it to calculate the distance between one vertex and an edge. Search for “How do I find the distance from a point to a line?” in this link
http://www.faqs.org/faqs/graphics/algorithms-faq/
There is a description how to get the distance from the line to the point. That is the way it was done before. But there is also a description how to identify the point on the edge (line) from where the shortest distance is found. Time for copy and paste. When the overall shortest distance is found the points defining that distance is returned to the user as a line. I found a line being the best way of returning the information because than the user can get both first and last point from that and the distance from the length of the line. The use of this functionality will probably, as described in the beginning be to identify where the minimum distance is found. Let’s say you are sitting on an big Island with your laptop and asking yourself from where you should swim to get the shortest way to shore. Now that problem is solved. For convenience the first point of ST_Shortestline can also be found with function ST_Closestpoint.

From this rewriting a also successes to get maximum distance calculation working, ST_Maxdistance. Then it was natural to also add longest line function which relates to ST_Maxdistance as ST_Shortestline relates to ST_Distance.
To make the symmetry complete I also added ST_DFullywithin. That function returns true if the maxdistance between two geometries is smaller or the same as the inputted last parameter. Just like ST_DWithin but with maximum distance instead of minimum distance.

So as summary
the old functions working with minimum distance, ST_Distance and ST_DWithin has now got a new friend ST_Shortestline and there is also the corresponding functions for max distance, ST_Maxdistance, ST_Longestline and ST_DFullywithin.

I will get back soon and tell about how I found the maybe fastest distance calculation, included in 1.5