-
Notifications
You must be signed in to change notification settings - Fork 3.4k
/
postgis.lua
80 lines (64 loc) · 3.29 KB
/
postgis.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
-- This example shows how to query external data stored in PostGIS when processing ways.
-- This profile assumes that OSM data has been imported to PostGIS using imposm to a db
-- with the name 'imposm', the default user and no password. It assumes areas with
-- landusage=* was imported to the table osm_landusages, containting the columns type and area.
-- Seee http://imposm.org/ for more info on imposm.
-- Other tools for importing OSM data to PostGIS include osm2pgsql and osmosis.
-- It uses the PostGIS function ST_DWithin() to find areas tagged with landuse=industrial
-- that are within 100 meters of the way.
-- It then slows down the routing depending on the number and size of the industrial area.
-- The end result is that routes will tend to avoid industrial area. Passing through
-- industrial areas is still possible, it's just slower, and thus avoided if a reasonable
-- alternative is found.
-- We use the osm id as the key when querying PostGIS. Be sure to add an index to the colunn
-- containing the osm id (osm_id in this case), otherwise you will suffer form very
-- bad performance. You should also have spatial indexes on the relevant gemoetry columns.
-- More info about using SQL form LUA can be found at http://www.keplerproject.org/luasql/
-- Happy routing!
-- Open PostGIS connection
lua_sql = require "luasql.postgres" -- we will connect to a postgresql database
sql_env = assert( lua_sql.postgres() )
sql_con = assert( sql_env:connect("imposm") ) -- you can add db user/password here if needed
print("PostGIS connection opened")
-- these settings are read directly by osrm
take_minimum_of_speeds = true
obey_oneway = true
use_restrictions = true
ignore_areas = true -- future feature
traffic_signal_penalty = 7 -- seconds
-- nodes processing, called from OSRM
function node_function(node)
return 1
end
-- ways processing, called from OSRM
function way_function (way, result)
-- only route on ways with highway=*
local highway = way.tags:Find("highway")
if (not highway or highway=='') then
return 0
end
-- Query PostGIS for industrial areas close to the way, then group by way and sum the areas.
-- We take the square root of the area to get a estimate of the length of the side of the area,
-- and thus a rough guess of how far we might be travelling along the area.
local sql_query = " " ..
"SELECT SUM(SQRT(area.area)) AS val " ..
"FROM osm_ways way " ..
"LEFT JOIN osm_landusages area ON ST_DWithin(way.geometry, area.geometry, 100) " ..
"WHERE area.type IN ('industrial') AND way.osm_id=" .. way:id() .. " " ..
"GROUP BY way.id"
local cursor = assert( sql_con:execute(sql_query) ) -- execute querty
local row = cursor:fetch( {}, "a" ) -- fetch first (and only) row
result.forward_speed = 20.0 -- default speed
result.forward_mode = 1
if row then
local val = tonumber(row.val) -- read 'val' from row
if val > 10 then
-- reduce speed by amount of industry close by
result.forward_speed = way.forward_speed / math.log10( val )
end
end
cursor:close() -- done with this query
-- set other required info for this way
result.name = way.get_value_by_key("name")
return 1
end