3

Using localhost page generated by osm2po roteamente noticed that the link is made to link even disabling snapping.

enter image description here

Logically thought to create more nodes in the network, but how can I do this without losing the topology of the data?

2 Answers 2

5

I had the same problem few weeks ago and solved it by manually drawing lines from nearest node. I don't know if it's one and only resolution, it's quite hard and tricky but its working quite good.

Firstly I'm selecting start edge, stop edge and result (path from routing) into record variables, then doing some post-procesing:

  1. Cut the result road if it's near start and end point

    if st_within(start_edge.geom_way, result.geom) then
      result.geom = ST_Difference(result.geom, start_edge.geom_way);
      result.km = result.km - start_edge.km;
      result.cost = result.cost - start_edge.cost;
    end if;
    
    if st_within(stop_edge.geom_way, result.geom) then
      result.geom = ST_Difference(result.geom, stop_edge.geom_way);
      result.km = result.km - stop_edge.km;
      result.cost = result.cost - stop_edge.cost;
    end if;
    
  2. Draw missing pieces by splitting start_edge and stop_edge. Unfortunately PostGIS is having troubles with splitting line by a point (case of rounding), so you have to draw the line from starting point intersecting cutting edge (I'm drawing line from point of start to point that is in direction of nearest point on line and 2xdistance)

    select foo.geom 
    from (
    select (st_dump(
       st_split(start_edge.geom_way, 
       st_makeline(ST_setsrid(ST_makepoint(start_x_4326,start_y_4326),4326), 
       (st_project(
         ST_setsrid(ST_makepoint(start_x_4326,start_y_4326),4326)::geography, 
         ST_distance(ST_setsrid(ST_makepoint(start_x_4326,start_y_4326),4326)::geography,st_closestpoint(start_edge.geom_way,ST_setsrid(ST_makepoint(start_x_4326,start_y_4326),4326)))*2, 
         ST_azimuth(ST_setsrid(ST_makepoint(start_x_4326,start_y_4326),4326)::geography,st_closestpoint(start_edge.geom_way,ST_setsrid(ST_makepoint(start_x_4326,start_y_4326),4326)))))::geometry)))).geom as geom) as foo 
    where st_touches(foo.geom, result.geom) 
    into add_start_edge;
    
    
    select foo.geom 
    from (
      select (st_dump(
       st_split(stop_edge.geom_way, 
         st_makeline(ST_setsrid(ST_makepoint(stop_x_4326,stop_y_4326),4326), 
       (st_project(
         ST_setsrid(ST_makepoint(stop_x_4326,stop_y_4326),4326)::geography, 
         ST_distance(ST_setsrid(ST_makepoint(stop_x_4326,stop_y_4326),4326)::geography,st_closestpoint(stop_edge.geom_way,ST_setsrid(ST_makepoint(stop_x_4326,stop_y_4326),4326)))*2, 
         ST_azimuth(ST_setsrid(ST_makepoint(stop_x_4326,stop_y_4326),4326)::geography,st_closestpoint(stop_edge.geom_way,ST_setsrid(ST_makepoint(stop_x_4326,stop_y_4326),4326)))))::geometry)))).geom as geom) as foo 
      where st_touches(foo.geom, result.geom) 
    into add_stop_edge;
    
  3. Now all you have to do is add this lines to result

    result.km = result.km + (start_edge.km * (ST_Length(add_start_edge) / ST_Length(start_edge.geom_way)));
    result.cost = result.cost + (start_edge.cost * (ST_Length(add_start_edge) / ST_Length(start_edge.geom_way)));
    result.geom = ST_Union(result.geom, add_start_edge);
    
    result.km = result.km + (stop_edge.km * (ST_Length(add_stop_edge) / ST_Length(stop_edge.geom_way)));
    result.cost = result.cost + (stop_edge.cost * (ST_Length(add_stop_edge) / ST_Length(stop_edge.geom_way)));
    result.geom = ST_Union(result.geom, add_stop_edge);
    
  4. And return result from procedure

    return query select result.km, result.cost, ST_Transform(result.geom, epsg);
    

PS. Keep in mind that if closest edge of your starting or target point is one-way not always the closest vertex of an edge is good point to paste into routing query. In your example if Riberio would be shortest your routing will end on Real-Riberio crossing and then you have to drive counter the road direction... :)

3
  • 1
    Thanks for posting your solution! As you said, this is not as easy as it initially may look like, because you need to care about various cases. If you want to share a good solution with the community (and hopefully receive valuable feedback), then you're welcome to publish your code on Github as described here: github.com/pgRouting/pgrouting/wiki/…
    – dkastl
    Commented Aug 6, 2014 at 21:55
  • Your solution is great thanks for sharing !! Really this is a serious problem in obtaining routes was hindering my work. I will adapt and test in my code ... I still think about creating more nodes in the network to avoid overloading coom sql queries and problems with variants like Street Sense. From your experience, do you think this idea feasible?
    – csf
    Commented Aug 7, 2014 at 12:43
  • @CassiaFreitas - It's hard to tell without performing few tests, but adding extra nodes to your graph means adding lots of extra edges thus your routing algorithm will have to check more edges then now and will work a lot slower (IMO). If you (for test of course) add to your procedure time measuring of each step (catch start time to variable + raise notice current_timestamp - start_time) You'll see this calculations not taking lots of time...
    – Jendrusk
    Commented Aug 8, 2014 at 7:59
1

Putting extra nodes to the static graph is no good idea. One reason is that the graph may be shared by parallel routing request. Another is that the graph will grow with each request.

One solution is to overlay the graph with virtual edges and nodes and to write a router which is able to distiguish between them. This is the technique used by osm2po.

Disabling snapping in osm2po's WebTestUI (screenshot above) only affects some routers - not the DefaultRouter which is a simple vertex-based Dijkstra/AStar. In order to see a correct picture, enable one of the "Ovl.."-routers in the config file.

1
  • I want to test the performance of my query routing by inserting more nodes. I'm viewing my tables and vertices_tmp ways. In vertices_tmp in atibrutos table so has the id field filled. How can I create multiple points in vertices_tmp at once ?? This does not have to do that manually.
    – csf
    Commented Aug 11, 2014 at 13:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.