Level Map/How-to

From OpenStreetMap Wiki
Jump to navigation Jump to search

This is a page showing how to use the currently proposed level map mechanism, including vertical ways (vways). For more details, see Relations/Proposed/Level Map.

Important: The level map is not (yet) accepted as a standard means of mapping. This page is to support the discussion whether or not to use it. So please do not use this instructions for your every-day mapping.

for current links try: searches for indoor mapping such as: Indoor Mapping

What is a level map?

In the 3D reality, things are usually not all side-by-side as on our printed maps. Instead, they are overlapping and many of them are hidden below others. OSM provides the layer=* tag to code which one of a set of overlapping objects is to be seen on top of the other one. This works quite well, as long as these objects are not exactly on top of each other. The most outstanding example are true vertical ways, such as vertical elevators. All points of these ways are on top of each other.

A level map is a relation relation in the OSM database, defining a set of so-called levels and assigning one or more of these levels to all of its members. The members are normal other OSM database objects, usually ways or nodes. This way, one and the same database object can represent a number of more or less identical real-life objects that are 'stacked' on top of each other. All members of a level map relation share its set of levels. However, an object does not need to be represented on all of these levels.

Many level map relation members are wholly assigned to one or more of the levels defined in a level map, such as a way occurring on multiple floors of a building. Others are connected to one level at one end and to another level at another end. This is usually used for stairways. Of course, identical stairways can be stacked on top of each other.

The representations or occurrences of one and the same database object on different levels are called 'instances' of the database object. So there are three instances of a way if it occurs on three floors of a building.

If you are here because you have found a level map and want to understand it quickly, skip to the Understanding an existing level map section.

If know that you want to create a new level map, have a look at the contents box first. If you are lucky, you find a good example there.

If, for some reason, you are still here, continue reading through the sections below.

When to use a level map?

Use a level map if you want to map

  • Multiple identical or similar objects that are exactly on top of each other at the same place
  • True vertical ways, such as vertical elevators
  • A number of ways or nodes that happen to be at exactly the same place, even if they are all on one and the same level
    • Example: a highway with a tram line in the middle
  • You want do encode exact height differences between components of a structure

Do not use a level map if you need only to map

  • crossing structures that do not share many of their nodes
    • Bridges, tunnels; use layer tagging here
  • Elevators that are not exactly vertical; map them as normal highways, plus elevator=yes

General steps when creating a level map

The steps listed

  1. Map all parts of your structure in 2D as you always did it.
  2. Create a new relation, with type=level_map
  3. Add the members, one by one
  4. Find vertical ways and tag them as needed
  5. Have a look at the connections to the outside of the level map

A first example

Let's create a vertical lift near a cliff with one footway to a road on top of the cliff and one footway to the beach.

  1. Map all parts of your structure in 2D as you always did it.
    • Map the footway from the beach to the lift. The endpoint of that footway will become the lift node later.
    • Map a footway bridge from the road on top of the cliff to the lift (the end of the previous way).
    • Tag the lift node as elevator=yes
  2. Create a new relation, with type=level_map
    • Create a new, empty relation
    • Add the tag type=level_map
    • Add a tag levels=* with a semicolon separated list of levels. List the levels from the lowest to the topmost one. In our case, the levels are locally labelled "Beach" and "Cliff Top", so our tag is levels=Beach;Cliff Top.
  3. Add the members, one by one
    • The main member of our new relation is the elevator, of course. So we add it to the relation. The membership role is empty, because the elevator belongs to all (in our case both) levels that are defined in the level map.
    • As there are no other pieces occurring on multiple levels, we are done for now. Close the relation.
  4. Find vertical ways and tag them as needed
    • We have got an obvious vertical way here, which is the elevator itself. In our case, it is used as a footway, so we would tag a similar horizontal way as highway=footway. As we are tagging a node here and adding vertical way attributes, the corresponding tag for it is vway:highway=footway.
    • There are no other vertical ways in our environment, so there is nothing more to do here.
  5. Have a look at the connections to the outside of the level map
    • There are two other objects connected to our elevator. One of them is the footway to the beach. We can leave it as it is, because it touches our level map on ground level. This is the default for objects connected to level map members, so there is nothing to do.
    • The other interesting way has to be handled specially, because it is not connected to the ground level occurrence of the lift node. So we add the footbridge to the level map relation. This footbridge does not occur on all levels, so we have to select the level where it occurs. The easiest way is often to use the level name for it. We use the level name as the membership role. So we add the footbridge to the relation, with a membership role of "Cliff top".
    • We have extended our level map now. If the newly connected object occured on more than one level, we would have to check every one of its junctions for which level the connected ways or nodes belong to. As our footbridge occurs on only one level, this is not needed. We can end our examination here.

The job is done now. We have got an elevator with named levels. Routing software knows about the elevator and can give instructions which level to go to, similar to street names or refs when turning left or right. Of course, this is not very interesting as long as there is only one level to go to. But it is no challenge at all to add a third level to the elevator.

This is a summary of all we had to do:

No. Description Tags Members (no., role) Remark
1 way Way to the beach Highway=Footway N/A As without level maps
2 way Way from the upper road highway=footway
bridge=yes
level=1
N/A As without level maps
3 node the elevator elevator=yes
vway:highway=Footway
N/A As without level maps, plus a vway tag
4 relation the level map type=level_map
levels=Beach; Cliff Top
node3, <empty>
way2, "Cliff Top"}}
This one is new

The general steps in more detail

  1. Map all parts of your structure in 2D as you always did it.
    • Map all parts that occur on at least one level
    • Interconnect them with junction nodes whereever an interconnection on at least one level is needed
    • Tag them as usual
    • If there are overlapping parts, use layer tags to guarantee a good rendering by non level map aware software.
      • When using layers, make sure that it looks correct from the top.
      • No additional layer tagging for level maps is needed.
  2. Create a new relation, with type=level_map
    • Add the key levels=first level;second level;..., with a semicolon separated list of the existing levels
      • use short level names, numbers or abbreviations as values, as you find them locally on signs or elevator buttons
      • order the levels - lowest level first, highest level last
  3. Add the members, one by one
If the object then
appears role example remarks further information
on one level only level name G as mentioned in the level definition (here it means the ground floor)
on the topmost level only top top special level alias special level aliases
on the lowest level only bottom bottom special level alias special level aliases
completely on all defined levels (empty)
Beginning on the bottom level, ending one level above, repeated on all levels above, except the topmost one link_up link_up No instance starts on the topmost level, because there is nothing it could connect to.
Beginning on the top level, ending one level below, repeated on all levels below, except the lowest one link_down link_down No instance starts on the lowest level, because there is nothing it could connect to.
completely on any set of levels custom EastWingCorridors Role to be defined in a simple role definition simple role definitions
Beginning on an arbitrary level, ending on another arbitrary level, optionally touching a third level in between custom CustomerStairs Role to be defined in a complex role definition complex role definitions
with more complex level connections (N/A) (N/A) Break the object up into parts that match one of the conditions above
  1. Find vertical ways and tag them as needed
    • True vertical lifts (mapped as a node) are the typical vertical ways. However, if needed, any way can be made a vertical way if it would be mapped as a horizontal way otherwise, but is vertical.
    • Add the tags you would normally add to the way to the node instead, prefixed with "vway:", for example vway:highway=service if the node represents an elevator for cars.
    • If the vertical way would not be tagged (typically because it is a part of a multipolygon), simply use vway=yes instead.
  2. Have a look at the connections to the outside of the level map
    • Most of these connections will be on some 'ground level'.
    • If the ground level is not the lowest one, you will probably want to mark the 'ground level' with a height value of zero, appending '@0' to its definition in the level map's levels=* tag. Example: levels=B;G@0;1-3
    • By default, all ways that are connected to level map members will be connected to the level marked as 'ground level'. If no level is marked that way, they will be connected to the lowest instance of the respective level map member.
    • If there are external ways that in reality that are connected to a level other the 'ground level', they fall into the second category of members (Objects that occur only once and are connected to exactly one level). Connect them to the correct level by adding them to the level map, with the correct level name as membership role

Other things to consider

If instances of an object are not identical (for example one instance is male toilets, another one is female), tag the level map member in a general (least restrictive) way and use Instance Tagging to add the needed tags to the more specific instances.

Understanding an existing level map

Basic Understanding

If you come across an existing level map in an OSM editor and want to understand it, have a look at the level map relation properties first.

Hint: In some editors, such as Merkaartor, a rectangular bounding box with the relation outline appears as soon as you hover the mouse over a relation member. Just click directly on the relation bounding box. In other editors you will reach the relation by clicking on a member (a way or node that is part of the level map) and select the relation in its properties, which will open the level map relation.

There are two important level map relation tags to look at:

  • type=level_map: This value must be there. If it isn't, you are not looking at a level map, but at something else.
  • levels=*: This is a semicolon separated list of the levels defined in this level map.
    • While they might be complex in rare cases, they are usually quite simple.
    • Don't be scared if you see complex ones. If you aren't determined to understand every small detail that the mapper has added, just look for the words after the semicolons and remember which one is suffixed with "@0".
    • Examples:
      • levels=G; 1: Two levels. One is locally known as "G" (in this case for "ground floor"), the upper one is referred to as "1".
        As no special ground level is defined, the level "G" will play the ground level role.
      • levels=G; 1-3: The same as above, but with a second and a third floor. Identical to

After having seen the level definitions, go through the level map relation members and have a look at their membership roles:

  • In Potlatch, [to be done]
  • In the JOSM relation editor, the role is given in the left column of the members list. Double-click on a the relation member there to select it the map.
  • In Merkaartor, while keeping the level map relation selected, just select its members in the members list (they are already "focused", because the relation is selected) and look at the member "highlighted" on the map.
Hint: With the Merkaartor default settings, it may be hard to see which member of a selected relation is highlighted. You may want to change the stroke width for "Highlight" in the colour preferences to be one pixel less than the "focus" stroke width and possibly also to change one of the two colours.

Some membership roles are predefined:

  • The empty role defines that the member occurs on all levels defined in the level map's "level" tag.
  • If the member role is the short name of a level defined in the level map's "level" tag, the member occurs on that level only.
  • The membership role "bottom" defines that the member (way or node) occurs on the lowest level defined in the level map's "level" tag only.
  • The membership role "top" defines that the member (way or node) occurs on the upmost level defined in the level map's "level" tag only.
  • The membership role "link_up" defines a set of links (typically stairs) stacked on top of each other, linking every floor to the floor directly above (if there is one). The first node of the member way is linked to the lower level and the last node of the same way is linked to upper level.
  • The membership role "link_down" is the same, but with the stairway pointing into the other direction. So it defines a set of links stacked on top of each other, linking every floor to the floor directly below (if there is one). The first node of the member way is linked to the upper level and the last node of the same way is linked to lower level.

Other role memberships are custom roles. They are defined in the level map relation itself.

  • Role membership definitions might be complex, but the main things are easy:
    • Look for level names at the beginning of entries in the semicolon separated list.
    • Some level names may be prefixed with a selector and an "=" sign. If so, the selector usually indicates which part of the member (way) the level applies to.
  • For more details see Understanding Custom Role Tags
  • Examples:
    • role:west_wing=G;1-3: This definition seems to be for parts that occur at all west wing floors of a building and nowhere else. Obviously, the west wing has got less floors than other parts of the building: G, 1, 2 and 3. (Otherwise, the mapper would have used the predefined empty role, which makes the respective relation members (ways, nodes) part of all levels.).
    • role:west_wing_stairs=first=G;last=1;repeat=2: This is a typical stairs definition for stairs that do not connect all floors. In our west wing case from above, the the west wing stairs does not go above the third floor.
      • One stairs connects the ground floor with the first floor: Its first node is connected to the ground floor "G", while the last node is connected to the first floor "1".
      • A second stairs is an exact copy of the first one, but one level above it (connecting the first floor with the second one). A third one connects the second floor with the third floor.
      • This repetition is defined by the "repeat" component of the definition.

Vertical Ways:

  • Level map relation member nodes or nodes that are part of member ways may have vway=* or vway:[[Key:|]]=* tags. These define vertical ways.
  • A simple vway=yes defines an (untagged) vertical way at a node's location.
  • One or more vway:[[Key:|]]=* tag define a vertical way at a node's location, along with tags for that vertical way.
  • The vertical occurrences of the node in the level map defined by the node or way's membership role are the vertical way's nodes.
  • Example:
    • vway:highway=footway defines a vertical footway. It is usually used in conjunction with elevator=yes at the same node.

Connections between level map members and non-members:

  • All non-members that are connected to level map members at junction nodes are connected at the special ground level only. This ground level is defined as follows:
    • IF (in rare, exceptional cases) the level map membership role happens to be a custom role with a level defined to be "@0", this is the relevant ground level for the member and external ways will be connected to that level (only)
    • ELSE IF there is a level defined to be "@0" AND the member occurs on that level, this is the relevant ground level
    • ELSE (by default) the lowest level defined in the level map is the relevant ground level.

Understanding Advanced "levels" Tags

  • levels=*: This is a semicolon separated list of the levels defined in this level map. Spaces after a semicolon are optional.
    • The list contains names, which may or may not be numbers.
    • A range of numbered levels can be defined by using a hyphen between the lowest and the highest number in the range
    • The levels are ordered from the bottom to the top.
    • Some entries may contain a "=". If so, the name left of the "=" is a short level name, usually used on elevator buttons and the right side contains a longer name that is also used locally.
    • After the name(s), an entry might contain an @aNumber suffix. This number specifies a relative elevation of the respective level above some local ground level.
    • The suffix "@0" is special, because it means that the respective level is the ground level of the level map, which has a special meaning. If no level is tagged that way, the special role will apply to the lowest defined level.
    • Examples:
      • levels=G; 1: Two levels. One is locally known as "G" (in this case for "ground floor"), the upper one is referred to as "1".
        As no special ground level is defined, the level "G" will play the ground level role.
      • levels=G; 1-3: The same as above, but with a second and a third floor. Identical to levels=G;1;2;3.
      • levels=B=Parking; G@0; 1-3: The same as above, but with a basement below. The basement is locally referred as both "B" and "Parking". As the basement is not at ground level and we want the special ground level role to be connected to the "G" level, we add the "@0" suffix to that level.
      • levels=B=Parking@-3; G@0; 1@5; 2@9; 3@12: The same as above, plus elevations mentioned for all levels. In the vase majority of cases, there is no need to map this level of details. The only reason why this example is mentioned here is that somebody might want to map it. So don't be scared if you see it. So if you are confused, just look for the words after the semicolons and remember which one is suffixed with "@0".

Understanding Custom Role Tags

  • role:role_name=*: This is a custom membership role definition.
    • In level maps, membership roles are used to define which member (usually a way or node) occurs on which level(s). Some roles are predefined, others (custom roles) can be defined here.
    • The important points here are the role name (after the "role:" tag prefix) and a the set of levels mentioned in the value.
    • Like the "levels" tag, the value of a role name tag is a semicolon separated list of levels. The levels mentioned here define on with levels the relation members (ways and nodes, etc.) occur.
    • Some entries may contain a "=".
      • If so, the word left of the "=" usually defines which part of the member way is connected to the level mentioned after the "=".
      • There are special keys "repeat=" and "step=" that might be used as a shortcut if a special level assignment combination reoccurs.
    • After the name(s), an entry might contain an @aNumber suffix. The meaning is exactly the same as in the level definition, but here it applies to the level map relation members (ways or nodes) using the role defined here. In so far, this definition overrides the more global definition in a level.
    • A level name (or "@" suffix) might be followed by a semicolon separated list of assignments in square brackets. If it occurs, it is a list of special tags for the occurrences defined hers, see Instance Tagging.
    • Examples:
      • role:general_layout=1-3;5-10: The name of this role definition suggests that the role is to be used for all ways and nodes that occur on all floors (levels) with "the general layout" and nowhere else. The floors 1, 2, 3, 6, 7, 8, 9 and 10 are obviously floors that share this layout.
      • role:rear_side=B;G;1@0;2-10: This might be a role definition for all parts that make up the rear side of a building that is built into a slope. In this case, the ground level at the rear is what inside the building is referred to as the first floor.

Further Details

Simple Custom Role Definitions

  • add a tag role:role name=first occurrence level;second occurrence level;... to the level map relation itself. The value is a semicolon separated list of levels where the object occurs.

Complex Custom Role Definitions

Nodes can be selected according to their position inside the way (first, intermediate, middle, last) and assigned separately.

The definition can be completed with a "repeat" selector, allowing us to create multiple, stacked instances of the stairway.

Define a custom role name for the object (or the set of objects sharing the same level connections)

  • add a tag role:role name=selector1=first occurrence level;selector2=second occurrence level;... to the level map relation itself; if needed, followed by a ;repeat=repeat count.


Examples

To do

  • Examples
  • Extending a level map
  • Interconnecting two level maps