-5

I have postgis road network table data base with speed limits based on type of road. I can able to get shortest path/route between two points by using Dijkstra or any other algorithm. Now I want to get possible paths that can be travelled from a location (point) in 10 minutes of time. Because of I'm having a speed limits based on road type the resultant paths may not be of same length.in this case single source all destinations algorithms may be helpful but my destination points are may or may not available as a nodes in the network because of my time as cost. Please help me.

Satya Chandra
  • 728
  • 2
  • 12
  • 26
  • 2
    Please show examples of your data structures. Without it is is rather hard to write exact answer. There is many possible ways to do that . Easiest is just calculate time for each edge as distance/"speed limit" and use as cost in pgr_dijkstra(). And very important what version of Postgis do you have? – Grzegorz Grabek Aug 03 '18 at 10:46
  • I'm using PostGIS 2.0, for calculate time for each edge is some how suitable but for 10 minutes the end point may not be the end of a edge. – Satya Chandra Aug 03 '18 at 14:38
  • I assume you want to check if you can go from one point to another in 10 mins in your graph. If so if you cannot move by whole edge then you cannot travel to end point of it in 10 mins. So it can be possible to reach start of edge before 10 mins but not possible to go to end point of it during 10 mins. If you want exact shape in your graph of this 10 minuts travel (exactly to miniseconds) it is much more complicated task then just finding way from one point to another. Is this really your point here - create exact shape of 10 mins travel or check to what POIs you can travel in 10 mins? – Grzegorz Grabek Aug 03 '18 at 19:46
  • 1
    if so read about pgr_drivingdistance - you will get all edges that are in range of 10 minutes. and then you will have to join part of edges connected to them. Part will be calculated as ST_Line_Substring(edge_geom, 0, 10mins-(calculated time of reaching last vertex)*speed_limit) / (length of new edge) ) – Grzegorz Grabek Aug 03 '18 at 19:52
  • Exactly I want a shape that can be travelled from a point in 10 mins with all possible directions. Because of speed limits I can't specify a constant distance in pgr_Drivingdistance functions. I need to give distance according to type of road. – Satya Chandra Aug 04 '18 at 02:01

1 Answers1

2

pgr_drivingDistance uses the cost value you provide, and in the units you implicitly specify, meaning that when you add a column <traveling_time> (note that I use seconds in my example) as the time needed to traverse an edge (given the length and speed limit) and select that as cost, the functions result will represent the equal driving time limits.

As for the parts where the algorithm couldn´t fully traverse the next edge 'in time', you will need to add those yourself. The general idea here is to identify all possible edges connected to the end vertices in the result set of pgr_drivingDistance, but not equal to any of the involved edges, and interpolate a new end point along those lines.

- Updated -

The following query is an out-of-my-head attempt and not tested at all, but in theory should is tested and returns a polygon all full and partial edges representing a 600 seconds trip along your network:

WITH
  dd AS (
    SELECT pg.id1 AS node,
           pg.id2 AS edge,
           pg.cost
    FROM pgr_drivingDistance('SELECT id,
                                     source,
                                     target,
                                     <travel_time_in_sec> AS cost
                              FROM <edge_table>',
                             <start_id>,
                             600,
                             false,
                             false
         ) AS pg

  ),
  dd_edgs AS (
    SELECT edg.id,
           edg.geom
    FROM <edge_table> AS edg
    JOIN dd AS d1
      ON edg.source = d1.node
    JOIN dd AS d2
      ON edg.target = d2.node
  ),
  dd_ext AS (
    SELECT edg.id,
             CASE
               WHEN dd.node = edg.source
               THEN ST_LineSubstring(edg.geom, 0, (600 - dd.cost) / edg.<travel_time>)
               ELSE ST_LineSubstring(edg.geom, 1 - ((600 - dd.cost) / edg.<travel_time>), 1)
             END AS geom
    FROM dd
    JOIN <edge_table> AS edg
      ON dd.node IN (edg.source, edg.target) AND edg.id NOT IN (SELECT id FROM dd_edgs)
  )

SELECT id,
       geom
FROM dd_ext
UNION ALL
SELECT id,
       geom
FROM dd_edgs;

The CASE statement decides if, for any follow-up edge, the fraction of line length will be calculated from the start or end point.

As a sidenote: the current version of pgRouting provides a set of functions where inter-edge-points are to be considered; if updating your (rather outdated) PostGIS/pgRouting versions is an option, consider those functions instead.

geozelot
  • 517
  • 3
  • 13
  • @Hyma btw, why didn´t you post this on GIS.SE? you´ve been active there for quite a while, and this question would definetely get more attention with us over there... – geozelot Aug 04 '18 at 13:49
  • @Hyma also, as I just read you might want the actual (and partial) edge geometries, if the query above returns correct points, it's easy ro rewrite it to return a set of lines. just say a word. – geozelot Aug 04 '18 at 14:21
  • For ST_LineInterpolatePoint(edg.geom, (600 - dd.cost) / edg., it is giving an error saying that 2nd argument not within [0,1]. Actually it is giving value between 0,1 but it's not taking . I have tried with static value like 0.2 , it is taking and giving result as expected. Please help – Satya Chandra Aug 05 '18 at 04:10
  • @Hyma hm..I don´t have a setup to test right now. to rule out that `NULL` values are breaking the function, try the `dd_ext` CTE with an `INNER JOIN`. also try with a direct cast to *float8*, i.e. `((600 - dd.cost) / edg.)::DOUBLE PRECISION`. if you simply return the calculation value instead of using the `ST_LineINterpolatePoint` function, are there some unexpected values in the result? and, I read your former comment before you deleted it; did you solve the *dd.node has to be grouped or aggregated* issue? you could use `..ON ST_Intersects(dd.geom, edg.geom) AND ...` instead. – geozelot Aug 05 '18 at 09:13
  • The previous comment problem was solved. I have tried above problem as :: double precision also but same issue. – Satya Chandra Aug 05 '18 at 09:21
  • Same error line_interpolate_point :2nd arg isn't with in [0,1]. SQL state xx000 – Satya Chandra Aug 05 '18 at 15:15
  • @Hyma try the whole query...I didn´t even use `ST_LineInterpolatePoint` anymore...this time, you´ll get the lines. – geozelot Aug 05 '18 at 16:29