libosmscout libosmscout.sf.net

Render on top of the map

Goal of the tutorial

This tutorial describes how you can render on top of the map. How to

Solution 1: Inject custom objects

If you just want to inject additional map primitives (nodes, ways, areas) that are not part of the original OSM data returned by the Database and want to use the existing style hseet engine, you can inject your own objects.

If you want them to be drawn differently, just define your own type, assign this type to the objects and assign custom rendering via the style sheet.

To create your own type, just create a TypeInfo instance, make sure you mark the type as internal and add it to the TypeConfig, here is an slightly modified example from TypeConfig.cpp itself, registering a custom type used for rendering the current route:

TypeInfoRef route=std::make_shared<TypeInfo>("_route");

route->SetInternal().CanBeWay(true);

typeConfig->RegisterType(route);

Make sure, that the types are registered to the TypeConfig for the importer and for the rendering engine in the same order (they get a running number internally).

Later on you can create (in this case) a way, assigning the route type to it:

TypeConfigRef typeConfig=database->GetTypeConfig();
Way           way;

if (!typeConfig) {
  return false;
}

TypeInfoRef routeType=typeConfig->GetTypeInfo("_route");

assert(routeType!=typeConfig->typeInfoIgnore);

way.SetType(routeType);
way.SetLayerToMax();

Make sure that you fill way.nodes afterwards with valid data to build the actual path. You need to call SetLayerToMax() to make sure that this way is drawn on top of all other ways.

In the next step you can now inject this way into the MapData:

data.poiWays.push_back(way);

Finally make sure that you have some style definition attached:

[MAG world-] {
  [TYPE _route] WAY {color: @routeColor; displayWidth: 1.5mm; priority: 100; }
}

Solution 2: Just draw it

If you need more power the solution is to use the rendering engine of the backend itself. If you are e.g. using the Qt backend, you pass a QPainter* ot the painter and your MapPainterQt instance draws the map into passed painter. After the map has been rendered you can use the Qt graphics routines like painter.setPen() and painter.fillRect() to draw on top of the map.

This makes sense for drawing complex things like