OpenStreetMap

Wrapping up GSoC 2019 - The current state of OSM2World

Posted by JasonManoloudis on 26 August 2019 in English (English). Last updated on 13 November 2019.

Introduction

So, this is the final entry of a what has come to be a 6 entries series, regarding this year’s Google Summer of Code project and the work that has been done on the 3D Renderer OSM2World. This post will summarize the last 2 tasks that did not get their own separate entries as well as give an overview of the whole summer work, starting from the latest. The two tasks in question are those of Rendering Destination Signs and Guessing the positions of non-explicitly defined signs, as stated in the application document, which have proved to be particularly challenging to say the least; we will go through them later on this post.
So without further ado, let’s present what has been done so far in this Summer of Code, in a chronological order:

  1. Font rendering for signs with custom text: https://github.com/tordanik/OSM2World/pull/147
  2. Human readable traffic sign values: This particular task does not have a pull request of its own as its TODOs, mentioned in the application document, where gradually being implemented as parts of the other tasks (a good example of this can be found in this entry)
  3. SVG texture support: https://github.com/tordanik/OSM2World/pull/151
  4. Traffic sign catalogues: https://github.com/tordanik/OSM2World/pull/153
  5. Destination signs: https://github.com/tordanik/OSM2World/pull/154
  6. Guessing the positions of non-explicitly defined signs: https://github.com/tordanik/OSM2World/pull/155 (may be changed)

A summary is available for each of the first 4 tasks, in their corresponding diary entries, listed below in the same order:

  1. Font rendering for signs with custom text
  2. Human Readable traffic sign values
  3. SVG texture support
  4. Traffic sign catalogues

Let’s now see what the remaining 2 tasks are all about!

Rendering of Destination signs

Destination signs was the first time it was required to take into account something other than explicitly defined nodes for rendering traffic signs, as the information about them is found in “type” = “destination_sign” relations. Destination sign relations include ways & nodes around junctions, as this also tends to be the places you find such signs in real life.
It would be useful to break down the important (to this project) members of such relations, at this point, before moving forward:

  • From: The (usually) way before coming to the junction
  • To: The (usually) way after the junction
  • Intersection: The node of the junction
  • Sign: The point where the sign is

I would also like to make clear that by “destination signs” we refer to this type of signs: Destination sign 1 Destination sign 2

As one can tell, destination signs could not really “fit” into the existing mechanism for traffic sign rendering; they are a type on their own. That translates into a new private class, in TrafficSignModule

private final class DestinationSign extends NoOutlineNodeWorldObject
			implements RenderableToAllTargets

that of course has its own renderTo() method (although one can find similarities with TrafficSign’s renderTo()).
The concept for this task is as follows:
First of all, such sign’s textures consist of 2 texture layers, an image type background and a text type. The coloring of the signs makes use of the colorable mechanism, which essentially “paints” the bottom texture layer with the material’s color. In our case, the material’s color is extracted from the colour:back tag of the relation (indicates the sign’s background color) and is set to the corresponding material using the newly introduced, for the needs of this task, method

        /**
	 * returns a material that is the same as this one,
	 * except with a different color
	 */
	public Material withColor(Color color)

in Material.java .
What differentiates the signs and allows the application to know which material to use every time is the color of the arrow around each sign, tagged with colour:arrow in the relation. So a relation with

“colour:back” = “white”
“colour:arrow” = “black”

would result in the first of the 2 signs pictured above while

“colour:back” = “yellow”
“colour:arrow” = “black”

would result in the second one.
The text depicted on the signs is extracted from the “destination =’’ and *“distance =” tags of the relation, using the renewed

private static Material configureMaterial(ConfMaterial originalMaterial, Map<String, String> map, MapElement element)

method of TrafficSignModule, as updated to cover the needs of the previous, Traffic sign catalogues, task while the text color is extracted from the “colour:text” = relation tag and is set in the appropriate text texture layer using the also newly introduced

/**
 * returns a copy of {@code material} with its {@link TextTextureData} layer
 * No. {@code numberOfTextLayer} changed with a replica with textColor={@code color}
 */
public Material withTextColor(Color color, int numberOfTextLayer)

method, of Material.java .
The result of the above, for 4 “type” = “destination_sign” relations around the same intersection & sign nodes (and dummy text for demonstration purposes) is this:

Destination signs sample

The facing side of each sign on the pole is calculated using the direction angle of the relation’s from member while the pointing sides take the into account the position of the relation’s to member, checking whether is it to the right or left of from .
Material variants for left & right pointing sides are now available in Germany’s traffic sign catalogue configuration file and the materials are being defined and parsed in a Traffic sign catalogues task way!

Guessing the positions of non-explicitly defined signs

That brings us to the last, and arguably GSoC’s hardest, task of this summer.
The context of this task is as follows:
Traffic signs can be mapped on openstreetmap in 3 different ways + one special case:

  • Mapped on explicitly defined nodes usually next to ways, where the node’s positions indicate the actual positions of the signs
  • Mapped as tags on ways in a manner of maxspeed=50 or traffic_sign=De;101-11 which indicates that the sign’s rules apply to the whole extend of this way
  • Mapped on nodes that are part of ways where the actual position of the sign is to the right/left of this node
  • Special cases highway=give_way & highway=stop where a number of specific rules apply to them

Up until now only the 1st of those cases was supported in OSM2World and it was the goal of this task to support the remaining 3.
What justifies this task as GSoC’s hardest is the large number of rules that has to be followed for the positions and facing directions of the signs, as many cases equals many lines of code, making it quite hard to keep everything in mind while avoiding code duplication. Those rules are:

  • For signs mapped as tags on a way:

    1. If the sign is tagged as “traffic_sign:forward = “ or “traffic_sign:backward = “ , only 1 sign is rendered, that faces the defined direction.
      If the sign is simply tagged as “traffic_sign” = , 2 signs are rendered, one at the beginning and one at the end of the way, which face opposite directions.
    2. If side=left/right is defined on the way, it indicates the side of the way the sign is placed on
    3. If the way is oneway, only one sign is required, at the beginning of the road.
    4. If a way that is an extension of the one we are working with, also contains the exact same traffic sign mapped on it, then the sign must not be rendered in between them.
  • For traffic signs mapped on a way node:

    1. side=left/right/both again applies. If side=both then 2 signs are rendered, on each side of the node
    2. traffic_sign:forward/backward also applies
  • For the special cases

    1. Their facing direction is extracted by finding the closest intersection to the node they are mapped on. To not confuse anyone any further, here is their wiki documentation

To make things easier, a TrafficSignModel class is introduced that represents a sign with all its traffic sign types on it (a pole can have more than one signs).
TrafficSignModule’s applyToNode() method was also restructured and now has the following shape:

@Override
protected void applyToNode(MapNode node) {

  /* if sign is a destination sign */

  isDestinationSign(node);

  /* if "traffic_sign = *" or any of the human-readable signs (maxspeed|overtaking|maxwidth|maxweight|maxheight) are mapped as a way tag */

		
  isTagOnWay(node, signsOnWaysState);
		

  /* hardcoded special cases highway=give_way & highway=stop */

  isSpecialCase(node);

  /* if sign is a simple traffic sign mapped on a node (not a destination sign or a human-readable value mapped on a way) */

  isMappedOnNode(node);

}

with method names that speak for themselves.
An example of maxspeed=30 sign extracted from way tags can be seen below, with it’s counterpart facing the opposite direction at the other end of the way visible at the distant end of the road

signs from way tags

What is left to be done

The links provided at the beginning of this entry will change in the following days as the last 2 tasks are changing towards their final form. That mostly means writing tests for some relatively complex methods created during GSoC and putting some final touches where this is required.
There are of course things that could be done under the scope of supporting traffic signs in OSM2World, like rendering of street name signs based on name=* tags and signs derived from routing-related tags like oneway and access but for now, this is as far as this Summer of Code project goes! It would be great though to continue being a contributor to OSM2World, now that I have an understanding of it up to a point, and maybe implement these tasks without being under the pressure of time and I am pretty sure many students would feel like now that their own GSoC projects are also coming to an end!

Conclusion

From my perspective, GSoC has definitely been a unique experience, different from what I’ve come across so far work-wise, thus the reason I craved to take part in it, and of course with its ups and downs, as pretty much everything has (?)
It may sound somewhat “childish” but one of the biggest satisfactions the Summer of Code has given me is actually being a contributor to a large scale project used by a lot of people, giving meaning, in a way, to my presence on GitHub as well as to code I’ve written! It is also a nice opportunity to get a taste of what working remotely might be like and get to know if that work/life style actually suits you.
To conclude and also give two well deserved shout-outs , I honestly was glad to be participating with OpenStreetMap in this initiative as well as with this specific project and mentor!

Application document

https://github.com/JayGhb/GSoC-2019-Application


Login to leave a comment