Skip to content

Instantly share code, notes, and snippets.

@worthlutz
Last active July 8, 2016 14:23
Show Gist options
  • Save worthlutz/72fce4ba32093754c1d4f819707e595a to your computer and use it in GitHub Desktop.
Save worthlutz/72fce4ba32093754c1d4f819707e595a to your computer and use it in GitHub Desktop.
pgrw_xyroute is an example of a wrapper around the pgr_trsp function to require only x/y inputs for source and target points. Routing is then done by pgr_trsp using the nearest location on the closest edges to the source and target points.
/*
pgrw_xyroute is an example of a wrapper around the pgr_trsp function to require only x/y inputs
for source and target points. Routing is then done by pgr_trsp using the nearest location on
the closest edges to the source and target points. To achieve this result, the details of the
specific routing network are hard-coded as constants in the wrapper. Modification to your
specific situation should be simple.
*/
CREATE OR REPLACE FUNCTION pgrw_xyroute(source_x double precision, source_y double precision,
target_x double precision, target_y double precision)
RETURNS SETOF pgr_costresult
AS
$BODY$
DECLARE
edge_tbl_name CONSTANT TEXT = '_rt_geom_streets_base'; -- edge table name
srid CONSTANT INTEGER = 2264; -- edge table and x,y srid
cost_column CONSTANT TEXT = 'cost_len'; -- cost_len | cost_time
rcost_column CONSTANT TEXT = 'rcost_len'; -- rcost_len | rcost_time
local_radius CONSTANT DOUBLE PRECISION = 5280.0; -- radius in ft. for selecting all edges around point
-- sql to locate the closest edge to the source and target points is built from sql1, sql2, sql3 & sql4
-- SELECT
-- id,
-- ST_LineLocatePoint(the_geom, ST_SetSRID(ST_Point( source_x, source_x), srid)) AS fraction
-- FROM edge_tbl_name
-- WHERE ST_DWithin(the_geom, ST_SetSRID(ST_Point(source_x, source_x), srid), local_radius)
-- ORDER BY ST_Distance(the_geom, ST_SetSRID(ST_Point(source_x, source_y), srid)) ASC
-- LIMIT 1
-- returns a record (id, fraction)
sql1 CONSTANT TEXT = 'SELECT id, ST_LineLocatePoint(the_geom, ';
-- point definition sql goes here
sql2 CONSTANT TEXT = ') AS fraction FROM ' || edge_tbl_name || ' WHERE ST_DWithin(the_geom, ';
-- point definition sql goes here
sql3 CONSTANT TEXT = ', ' || local_radius || ') ORDER BY ST_Distance(the_geom, ';
-- point definition sql goes here
sql4 CONSTANT TEXT = ') ASC LIMIT 1';
-- this defines the select for ALL edges in the edge table
edge_select CONSTANT TEXT = 'SELECT
id, source, target, ' || cost_column || ' AS cost, ' || cost_column || ' AS reverse_cost
FROM ' || edge_tbl_name;
-- WHERE clause to limit edges to major roads
major_roads_where CONSTANT TEXT = $$ WHERE sd_flag = 'ROADS' $$;
source_point TEXT; -- point definition sql for source point
target_point TEXT; -- point definition sql for target point
source_edge RECORD; -- nearest edge to source point
target_edge RECORD; -- nearest edge to target point
edge_sql TEXT; -- sql to select edges to use for routing
BEGIN
-- point definition sql for source point
source_point = 'ST_SetSRID(ST_Point(' || source_x || ',' || source_y || '), ' || srid || ')';
EXECUTE sql1 || source_point || sql2 || source_point || sql3 || source_point || sql4
INTO source_edge;
IF source_edge.id IS NULL THEN
RAISE NOTICE '** source_edge.id IS NULL **';
END IF;
-- point definition sql for target point
target_point = 'ST_SetSRID(ST_Point(' || target_x || ',' || target_y || '), ' || srid || ')';
EXECUTE sql1 || target_point || sql2 || target_point || sql3 || target_point || sql4
INTO target_edge;
IF target_edge.id IS NULL THEN
RAISE NOTICE '** target_edge.id IS NULL **';
END IF;
-- there are three edge selects unioned here:
-- all edges within 'local_radius' of the source point
-- all 'Major' roads in the table (marked with sd_flag='ROADS')
-- all edges within 'street_radius' of the target point
edge_sql := edge_select || ' WHERE ST_DWithin(the_geom, ' || source_point || ', ' || local_radius || ')
UNION '|| edge_select || major_roads_where || '
UNION '|| edge_select || ' WHERE ST_DWithin(the_geom, ' || target_point || ', ' || local_radius || ')
';
RETURN QUERY SELECT *
FROM pgr_trsp(edge_sql, source_edge.id, source_edge.fraction, target_edge.id, target_edge.fraction, TRUE, TRUE);
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE
COST 100
ROWS 1000;
/*
-- test function only
SELECT (pgrw_xyroute(2088111,731419,2088111,700700)).*;
-- get all edge data for route
WITH route AS (
SELECT (pgrw_xyroute(2088111,731419,2088111,700700)).*
)
SELECT *
FROM _rt_geom_streets_base edges
JOIN route
ON edges.id = route.id2
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment