OpenStreetMap logo OpenStreetMap

Advanced rendering of tags

Posted by pieleric on 25 March 2013 in English.

The french OSM team has been playing with improved rendering in mapnik. Recently, they’ve introduced the idea of rendering sport tags for known sports by displaying the lines of the field. I like it a lot, it gives a much nicer display than having an icon of the sport :-)

You can see an example here, with tennis, football (soccer) and rugby fields:

They’ve also improved the rendering of golf:

I hope it’ll be picked up by other tile renderers :-)


Comment from DaCor on 25 March 2013 at 15:15

ha, love it!

using the layer switcher on the right and melding the images of the golf course together is a great way to show what can be done with the same set of data in terms of rendering whats important to specific groups e.g. a golf website could use that type of rendering when including slippy maps showing the locations of golf courses.

Very nicely done

Comment from Rovastar on 25 March 2013 at 21:05

Excellent stuff. Looks great.

There is a CartoCSS code/style for this? Then maybe we could merge it with what will eventually go on

I would be nice if the lines on the pitches where relative to the pitch size as they seem fixed and sometimes outside the green pitch render.

Comment from Rovastar on 25 March 2013 at 21:11

Sorry that should say

Is there a CartoCSS code/style for this?

Comment from pieleric on 25 March 2013 at 21:24

I’m absolutely not involved in the project, but indeed it seems it’s based on CartoCSS:

You can contact Christian Quest for more information :-)

Comment from Rovastar on 26 March 2013 at 00:36

Thanks pieleric

I’ll get a message to him at some point.

Looking at it I think it might be able to scale it better

First off I have never even used CartoCSS and not even installed it all yet but logically you could

Brain dumping my initial thoughts here.

[zoom=16] { point-transform: “rotate([angle]) scale([way_area]0.00001)”; } [zoom=17] { point-transform: “rotate([angle]) scale([way_area]0.00002)”; } [zoom=18] { point-transform: “rotate([angle]) scale([way_area]0.00004)”; } [zoom=19] { point-transform: “rotate([angle]) scale([way_area]0.00008)”; }

or even

[zoom>=16] { point-transform: “rotate([angle]) scale([way_area]0.00001([zoom]-16)^2)”; } (no idea on the syntax of that one for powers)

instead of all the [way_area<12000] , [way_area>=12000][way_area<17000] etc in the code. So it could just be a couple of lines.

Probably some technical reason why you cannot but logically that makes sense.

[sport='soccer'] { [surface='grass']::surface { polygon-fill: @sport-surface-grass; } [d12>130][d12<200][d23>68][d23<160][d13>150][d13<250] { /* 1>2 = length / 2>3 = width */ point-file: url('symbols/fr/sports-soccer.svg'); point-ignore-placement: true; [way_area<12000] { [zoom=16] { point-transform: "rotate([angle]) scale(0.1125)"; } [zoom=17] { point-transform: "rotate([angle]) scale(0.225)"; } [zoom=18] { point-transform: "rotate([angle]) scale(0.45)"; } [zoom=19] { point-transform: "rotate([angle]) scale(0.9)"; } [zoom=20] { point-transform: "rotate([angle]) scale(1.8)"; } } [way_area>=12000][way_area<17000] { [zoom=16] { point-transform: "rotate([angle]) scale(0.15)"; } [zoom=17] { point-transform: "rotate([angle]) scale(0.3)"; } [zoom=18] { point-transform: "rotate([angle]) scale(0.6)"; } [zoom=19] { point-transform: "rotate([angle]) scale(1.2)"; } [zoom=20] { point-transform: "rotate([angle]) scale(2.4)"; } } [way_area>=17000] { [zoom=16] { point-transform: "rotate([angle]) scale(0.175)"; } [zoom=17] { point-transform: "rotate([angle]) scale(0.35)"; } [zoom=18] { point-transform: "rotate([angle]) scale(0.7)"; } [zoom=19] { point-transform: "rotate([angle]) scale(1.4)"; } [zoom=20] { point-transform: "rotate([angle]) scale(2.8)"; } } }

[d23>130][d23<200][d12>68][d12<160][d13>150][d13<250] { /* 1>2 = length / 2>3 = width */ point-file: url(‘symbols/fr/sports-soccer.svg’); point-ignore-placement: true; [way_area<12000] { [zoom=16] { point-transform: “rotate([angle]+90) scale(0.1125)”; } [zoom=17] { point-transform: “rotate([angle]+90) scale(0.225)”; } [zoom=18] { point-transform: “rotate([angle]+90) scale(0.45)”; } [zoom=19] { point-transform: “rotate([angle]+90) scale(0.9)”; } [zoom=20] { point-transform: “rotate([angle]+90) scale(1.8)”; } } [way_area>=12000][way_area<17000] { [zoom=16] { point-transform: “rotate([angle]+90) scale(0.15)”; } [zoom=17] { point-transform: “rotate([angle]+90) scale(0.3)”; } [zoom=18] { point-transform: “rotate([angle]+90) scale(0.6)”; } [zoom=19] { point-transform: “rotate([angle]+90) scale(1.2)”; } [zoom=20] { point-transform: “rotate([angle]+90) scale(2.4)”; } } [way_area>=17000] { [zoom=16] { point-transform: “rotate([angle]+90) scale(0.175)”; } [zoom=17] { point-transform: “rotate([angle]+90) scale(0.35)”; } [zoom=18] { point-transform: “rotate([angle]+90) scale(0.7)”; } [zoom=19] { point-transform: “rotate([angle]+90) scale(1.4)”; } [zoom=20] { point-transform: “rotate([angle]+90) scale(2.8)”; } } } }

Comment from Rovastar on 26 March 2013 at 00:38

umm posting css type code here doesn’t work well

Comment from seav on 26 March 2013 at 18:41

It seems there’s a projection scaling bug for the tennis courts. Here’s a tennis pitch area, but the tennis court image is too big!

The tennis pitch there actually contains 2 tennis courts. Do we need to split up the leisure=pitch polygon into 2? I don’t think we should, since it’s just 1 pitch area.

Comment from mackerski on 27 March 2013 at 11:02

It depends what we mean by “a” pitch. In my mind, a pitch is the playing area for one game. A piece of land accommodating several playing areas would be a field or park or some other noun.

Comment from Bruno_Remy on 27 March 2013 at 12:32

Scaling problems are results on a “bad” mapping: I mean: This SVG files applies on pitch area itself, and NOT on the largest landuse around. So, if we want this render works fine, we have no choice to adjust every single polygon to the lines of each single pitch. Examples: If a large grass field is mostly used by a soccer pitch, ther should be a large polygon for the park (barrier=fence, landuse=park) and a “tight” one just close the white stripes of pitch (leisure=pitch, sport=soccer) For a tennis court witch have four(4) courts: one polygon for the area (barrier=fence) and four polygons with (leisure=pitch,sport=tennis,surface=clay)

I experiment this in Quebec city, Canada and it works fine this way.

Comment from pieleric on 27 March 2013 at 13:00

@seav: My main advice is: “take it easy” :-)

Currently, all this has to be taken with a grain of salt. * Firstly, the rendering you’re seeing has been coded by Christian, on his own initiative, and mostly for demonstration purpose. It’s not the most clever rendering ever (yet), and doesn’t set in stone the meaning of any tag. * Secondly, like most of the tags in OSM, the semantic of the leisure=pitch tag is not fully specified. The wiki page gives a pretty good rough idea, but what matters most is how contributers use it to map the reality to the OSM database. I’m sure currently you can find in OSM both interpretations of what a “pitch” represents: either the whole group of courts (easier to map), or just one court (easier to render, and more precise).

In my opinion, every contributor has his own right to pick the interpretation he likes most, at least until there is a consensus which emerges. So I think for now the most important rules are: try to stay consistent with yourself (decide how you want to tag things and try to stick to it for some time), and respect the work done by other contributors by not changing their tagging just to fit your interpretation.

Comment from AndersAndersson on 27 March 2013 at 15:14

Looking great!

But some pitches are not rendered with lines. For example is only one the left pitch rendered here. Surface tag and maybe lit tag seams to be a problem.–

Comment from seav on 29 March 2013 at 08:36

Regarding my comment about the “projection scaling bug”, I confirmed that this is indeed a bug due to the mercator projection not having a uniform scale throughout the map. Despite that, the courts are rendered in a uniform scale per zoom level. The courts look great in France but would have the wrong size in other latitudes.

I’m guessing that these courts are rendered as if they were SVG icons, but rotated to match the general orientation of the pitches. If we really want scale-correct courts, I think that would require some complicated processing in the PostGIS DB. But as a proof-of-concept, this initial rendering of courts is actually great.

Note: I’m not complaining, just pointing out (probably already known) oddities.

As for the meaning of “leisure=pitch”, I was actually hoping to spark a discussion. But maybe it’s best discussed on the tagging@ mailing list. :-)

Log in to leave a comment