-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Problem description
The current map plugin is great for visualization of a static map.
Since Geovistory deals with historical data, time is an important aspect. In order to show developments of historical phenomena on a map, a map with time filter and time line would be great.
Functional requirement
The time-map-with-circles has to deal with this kind of input data (example):
| pointUri (uri) | pointLabel (xsd:string) | eventUri (uri) | eventLabel (xsd:string) | long (xsd:float) | lat (xsd:float) | start (xsd:date) | end (xsd:date) | type (xsd:string) |
|---|---|---|---|---|---|---|---|---|
<geoplace1> |
Bern | <eventA> |
Laura in Bern | 12.3 | 56.7 | 1597-02-25 | 1597-08-11 | Work |
<geoplace1> |
Bern | <eventB> |
Max in Bern | 12.3 | 56.7 | 1599-01-12 | 1599-07-19 | Work |
<geoplace2> |
Lyon | <eventA> |
Jean in Lyon | 12.3 | 56.7 | 1600-01-21 | 1600-01-21 | Voyage |
<geoplace2> |
Lyon | <eventA> |
Maria in Lyon | 12.3 | 56.7 | 1600-01-01 | 1601-01-01 | Work |
This example data can be interpreted so: Laura worked a few months in Bern in 1597, Max in 1599. Jean travelled through Lyon the January 21st of 1600. Maria worked one year in Lyon in 1600.
The long and lat are geographic coordinates; start and end define the event-time-interval.
The component has these functional requirements:
- The UI consists of a map with circles and a timeline with two handlebars
- The handlebars allow to define a time-interval-filer, consisting of a start and end date.
- The input records displayed on the map are filtered, where the time-interval-filter overlaps with the event-time-interval.
- The map displays circles with variable radius and color.
- The map shows one circle per pointURI and type.
- The location of a circle on the map is defined by lat and long
- The size of a circle depends on the number of events
- On init, the map and the timeline zoom to the extend of the data
- On init, the time-interval-filter sets to the extend of the data, unless another interval was defined by component inputs
- The timeline allows to manipulate the time-interval-filter in these ways:
- drag start date
- drag end date
- drag interval (moving start and end simultaneously)
- nice to have: A play button animates the interval from left to right
- nice to have: The animation speed can be modified
With the above example data and a time-interval-filter of 1590–1610 (showing all 4 records), there would be
- one point for
<geoplace1>with radius 2 (for Laura and May) and color A (for Work) - one point for
<geoplace2>with radius 1 (for Jean) and color B (for Voyage) - one point for
<geoplace2>with radius 1 (for Maria) and color A (for Work)
[EDIT after discussion below]
The map displays one circle per pointURI and type. This means, we group the events per pointURI and type. Each group will be displayed as a circle. The circle radius is proportional to the number of events per group, the color depends on the type.
More technically, each group of pointURI and type aggregates the event attributes in a list: start, end, eventLabel, eventURI and picks one pointLabel, lat, long for each group. The output data structure could look like this (pseudo code):
{
"<geoplace1>_Work": {
"group": {
"pointURI": "<geoplace1>",
"pointLabel": "Bern",
"type": "Work",
"long": 12.3,
"lat": 56.7
},
"events": [
{
"eventUri": "<eventA>",
"eventLabel": "Laura in Bern",
"start": "1597-02-25",
"end": "1597-08-11"
},
{
"eventUri": "<eventB>",
...
}
]
},
"<geoplace2>_Work": {...},
"<geoplace2>_Voyage": {...}
}For each key, the map displays a circle. The color depends on group.type, the radius on events.length.
The above json example could also be expressed as an array of groups instead of an object with a key per group. I chose this approach, because it illustrates, that the groups identity is defined by pointUri and type.
Technical Specification
- The component is called time-map-with-circles.
- The component works standalone and as Yasgui plugin.
- The map is implemented with MapLibre.js
- The timeline can make use of the geov-timeline component, developed in Entity Timeline #103
- The Yasgui plugin uses geov-yasgui-data-validation component to validate data (like here)
The component has these inputs:
data: Parser.Binding[] (as in geov-yasgui-map-circles)
colorScale: string[] (as in geov-yasgui-map-circles)
timeFilterStart: string (in the form of xsd:date, setting the start of time-interva-filter on init)
timeFilterEnd: string (in the form of xsd:date, setting the end of time-interva-filter on init)
This example query can be copied it here to get useful sample data:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX ontome: <https://ontome.net/ontology/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX time: <http://www.w3.org/2006/time#>
SELECT ?s ?event (SAMPLE(?l) as ?label) (SAMPLE(?lo) as ?long) (SAMPLE(?la) as ?lat) (MIN(?date) as ?start) (MAX(?date) as ?end)
WHERE {
# Geographical Place -had presence-> Presence -was at-> Place (lat/long)
?s ontome:p147i/ontome:p148 ?place.
# Geographical Place -label-> label
?s rdfs:label ?l.
# Geographical Place -is arrival place of-> Ship Voyage
?s ontome:p1335i ?event.
# Event has time span
?event ontome:p4 ?timespan.
# time span -> time description -> year;month;day as xsd:date
?timespan ?timeprop ?dtd.
?dtd a time:DateTimeDescription ; time:year ?y; time:month ?m; time:day ?d .
bind(xsd:date(concat(replace(str(?y), "^-", "" ), replace(str(?m), "^-", "" ),replace(str(?d), "^--", "" ))) as ?date)
FILTER(isLiteral(?date)). # filter parsable records
# Extract lat and long from WKT
bind(replace(str(?place), '<http://www.opengis.net/def/crs/EPSG/0/4326>', "", "i") as ?rep)
bind(xsd:float(replace(str(?rep), "^[^0-9\\.-]*([-]?[0-9\\.]+) .*$", "$1" )) as ?lo )
bind(xsd:float(replace( str(?rep), "^.* ([-]?[0-9\\.]+)[^0-9\\.]*$", "$1" )) as ?la )
# Append the project query param to the URI
bind(concat(str(?s), "?p=84760") as ?link )
}
GROUP BY ?s ?event
ORDER BY ?sAcceptance Criteria
The user interface works as described in the functional requirements.