Wednesday 25 November 2015

postgis - pgRouting not returning node with correct z-value


have an issue with pgRouting that I've modified to consider multi-floor indoor areas. I've created a mock floor plan of any typical hotel. I copied the floor plan and assigned a different z-value to essentially mirror the floor plan, with one positioned directly above the other. I then made vertical connections between the floors for elevators and stairs to create a complete 3D network.


Using the SQL code found here https://github.com/mapcentia/geocloud2/blob/master/app/scripts/sql/pgr_createTopology3D.sql, I created the modified pgr_createTopology3d and pgr_pointToIdZ functions to build topology on the 3D network. Following that, I followed normal procedure for building the SQL View to serve the queried results as a layer to GeoServer


When constructing the SQL View, I used a modified version of pgr_fromAtoB to consider z-values. I modified as follows (see @underdark's answer to pgRouting with multiple floors):


-- Find nearest node
EXECUTE 'SELECT id::integer FROM ways_vertices_pgr
ORDER BY the_geom <-> ST_GeometryFromText(''POINT('
|| x1 || ' ' || y1 || ' ' || z1 || ')'',4326) LIMIT 1' INTO rec;
source := rec.id;


EXECUTE 'SELECT id::integer FROM ways_vertices_pgr
ORDER BY the_geom <-> ST_GeometryFromText(''POINT('
|| x2 || ' ' || y2 || ' ' || z2 || ')'',4326) LIMIT 1' INTO rec;
target := rec.id;

However, it doesn't appear that the z-value is being considered. For example, I have nodes lying exactly on top of each other with the same lat/long, but with differing z-values. I can issue the ST_GeometryFromText command and limit the results to 2 and see the both of the nodes are being returned at the lat/long I've specified. However, the z-value for the bottom node is 0 and the upper node is 1. No matter what z-value I specify in the request, the upper node is always returned as the top result.


Does anyone know why?


How can I get it to return the bottom node if I specify the z-value as 0?



Answer




The <-> operator stands for "K-nearest-neighbor" (KNN) search, which does not support 3D but only 2D distances: http://postgis.net/docs/manual-dev/geometry_distance_knn.html


From PostGIS 2.2 you can use <<->> for 3D distances, but that version is not released yet: http://postgis.net/docs/manual-dev/geometry_distance_centroid_nd.html


KNN is very fast and easier to use, but you can also select a BBOX around your point, calculate the distances, order the result by distance and take the smallest one:


SELECT id::integer, 
ST_3DDistance(
the_geom,
ST_GeometryFromText('POINT(x y z)', 4326)
) AS dist
FROM ways_vertices_pgr
WHERE the_geom && ST_Expand(ST_GeomFromText('POINT(x y z)', 4326), 0.1)

ORDER BY dist LIMIT 1";

This is a modified example from the previous pgRouting workshop, so I'm not sure the syntax is 100% correct, but I hope it explains the idea.


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...