Monday, July 3, 2017

Path Labels (Part Five)

I ended the last posting with this map:
Although the labels look generally good here, "Chukor" and "R.Tertitdul" fall on mountains and are hard to read as a result.

The obvious way to address this problem is to add mountains to the list of features that the labeling algorithm is trying to avoid.  Labels will then gravitate to spots where they don't overlap mountains. But mountains are big features, and on many maps, that would make label placement very difficult. On this map, for example, it's not obvious that there's anywhere you can put the "R.Tertitdul" label without overlapping the mountains, the coast, or a city.  It's inevitable that labels are going to at least occasionally overlap map features, so I need a way to make labels more readable when they do.

The usual approach is to mask out the features in the area of the label.  Jonathon Roberts talks about this technique a bit over at Fantastic Maps, and that's worth reading.  For those of you who aren't familiar with the idea of masking, the basic concept is to create an area where something (the mountains in this case) won't be shown, i.e., it will be "masked out" of the image.  In many cases, it's easier to draw everything and then block out portions we want to remove than to not draw them in the first place.  For example, at the time I'm creating and drawing the mountains, I don't know if or where text will overlap the mountains.  So it's much more convenient to just draw the mountains and later "erase" the parts I don't want.  The mask is also separate from the image, so we can change the mask without changing the image.  For example, during label placement I can just slide the mask around with the text.

In SVG, you can add a mask to just about anything.  The mask itself is a grayscale image.  Everywhere the mask is white the image shows through; everywhere the mask is black the image is blocked out; and gray scales correspond to partial opacity.  For text, you can create a useful mask by drawing the same text in black with a fatter pen -- that masks out around the edges of the text to whatever distance you've chosen.  Then you place the mask not on the text, but on the image you want to block out.  So in my case, I need to place the mask on the image of the mountains.  Here's what the "R.Tertitdul" label looks like with and without this masking:
You can see that this makes a big difference in the readability of the label.  Jonathon Roberts recommends blurring the mask into the background, and letting some of the background show through. That looks like this (compared to the "normal" mask):
This is a more subtle effect while still making the label more readable.  Jonathon Roberts actually does a white overlay on the background rather than a mask.  This has the advantage of also popping out a label even on a plain background (where the mask has no effect).  Here is a similar effect, compared to just the subtle masking:
I didn't expect to like this effect -- and I may continue to tweak it -- but I find that it does improve the definition and readability of the labels.  One problem is that the effect is much more pronounced on a dark background like a forest:
Unfortunately, SVG doesn't provide a full array of compositing functionality.  If I could use a screen blend mode, as Jonathon Roberts recommends, it would look better over a dark background.

No comments:

Post a Comment