ORBIS
A model of and for digital publication in the humanities
What is it?
ORBIS is a multimodal, time-aware network model of the Roman world, representing an idealized "entire" empire using GIS data to simulate roads, rivers and sea routes, which can change depending on the vehicle chosen or time of year of travel.
Contrast this with a traditional historical GIS (hGIS) project, such as DARMC http://darmc.harvard.edu
How did we build it?
Started in July 2011, ORBIS was created by collecting datasets for sites and routes; building models to simulate sea travel; and developing functions to simulate historical pathfinding based on duration- and expense-based priorities.
It's all Greek to me.
PostGIS + pgRouting allows for reasonable levels of complexity in network creation and pathfinding functions both in the creation of sea routes and discovering routes through the network once created.
o_routing_cheapest "source" integer, "target" integer, "month" integer, "vehicle" character varying, "mode" character varying
SELECT
s.label as source,
t.label as target,
s.objectid as source_id,
t.objectid as target_id,
s.rank as source_rank,
t.rank as target_rank,
(st_length(Geography(ST_Transform(o_routing.the_geom,4326))) / 1000)::numeric(10,3) as length,
(o_speed($4,o_routing.type,o_routing.the_geom,o_routing.cost) + o_alt_adjust($4,o_routing.restricted))::numeric(10,3) as duration,
o_expense('wagon',o_routing.type,o_routing.the_geom,o_routing.cost)::numeric(10,3) as expense_wagon,
o_expense('donkey',o_routing.type,o_routing.the_geom,o_routing.cost)::numeric(10,3) as expense_donkey,
o_expense('carriage',o_routing.type,o_routing.the_geom,o_routing.cost)::numeric(10,3) as expense_passenger,
o_routing.gid,
o_routing.type,
o_routing.the_geom
FROM
shortest_path('
SELECT DISTINCT ON (source,target)
gid as id,
source::integer,
target::integer,
o_expense('''||$4||''',type,the_geom,cost) as cost
FROM
o_routing WHERE month IN(0,'||$3||')
AND
('''||$5||''' LIKE (''%''||type||''%''))
AND (restricted NOT LIKE ''%''||type||''%'' OR restricted IS NULL)
ORDER BY
source,
target,
o_expense('''||$4||''',type,the_geom,cost)
',$1,$2,true,false)
LEFT JOIN o_routing ON o_routing.gid = edge_id
LEFT JOIN o_sites as s ON s.objectid = o_routing.source
LEFT JOIN o_sites as t ON t.objectid = o_routing.target
INSERT INTO o_fastsea (source, target, slabel, tlabel, total, the_geom, month, note)
SELECT
source, target, s_label.label as slabel, t_label.label as tlabel,
(SELECT SUM(calcost)
FROM
(SELECT ( case
when o_mesh.direction = 'N' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.n * 1852)
when o_mesh.direction = 'NE' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.ne * 1852)
when o_mesh.direction = 'E' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.e * 1852)
when o_mesh.direction = 'SE' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.se * 1852)
when o_mesh.direction = 'S' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.s * 1852)
when o_mesh.direction = 'SW' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.sw * 1852)
when o_mesh.direction = 'W' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.w * 1852)
when o_mesh.direction = 'NW' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.nw * 1852)
when o_mesh.direction = 'A' then o_mesh.cost
when o_mesh.direction = 'PT' then o_mesh.cost
else 3
end)::double precision / 24 as calcost FROM shortest_path('
SELECT DISTINCT
o_mesh.gid as id,
o_mesh.source::integer,
o_mesh.target::integer,
( case
when o_mesh.direction = ''N'' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.n * 1852)
when o_mesh.direction = ''NE'' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.ne * 1852)
when o_mesh.direction = ''E'' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.e * 1852)
when o_mesh.direction = ''SE'' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.se * 1852)
when o_mesh.direction = ''S'' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.s * 1852)
when o_mesh.direction = ''SW'' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.sw * 1852)
when o_mesh.direction = ''W'' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.w * 1852)
when o_mesh.direction = ''NW'' then st_length(Geography(ST_Transform(o_mesh.the_geom,4326))) / (ship.nw * 1852)
What can it
do?
Find the fastest route from one point to another
Or all fastest routes, say, to Rome, from the rest of the Roman world...
...and compare it to Constantinople...
...and compare it to Constantinople... in Winter.
More importantly, we can examine least "expensive" routes--Cheapest instead of Fastest.
And display it in a variety of ways, such as this isophoretric map
Or this distance cartogram
We can also perform geographic network analysis, such as this use of Delaunay triangles to compare plausible route density to actual route density.
How do we publish it?
orbis.stanford.edu
ORBIS is an example of a synthetic, digital scholarly publication that integrates narrative explanation with data-driven explanation of historical phenomena and attempts to make visible each of these components using modern web technology.
How did we do it?
Walter Scheidel identified, synthesized and explained the historical phenomena modeled here
Elijah Meeks developed the geographic information system representing the ORBIS multimodal network
Karl Grossner conceived and built the ORBIS web site as a digital scholarly publication.
Full credits are listed in the ORBIS Credits