.. _rfc60:

====================================================================================================
MS RFC 60: Labeling enhancement: ability to skip ANGLE FOLLOW labels with too much character overlap
====================================================================================================

:Date: 2009/06/26
:Authors: Daniel Morissette (dmorissette at mapgears.com)
:Authors: Alan Boudreault (aboudreault at mapgears.com)
:Last Edited: 2010-09-02
:Status:  Adopted on 2010-09-23
:Version: MapServer 6.0

Overview
------------------------------------------------------------------------------

At the moment, ANGLE FOLLOW labels on very sharp curved lines can result
in labels on which some characters overlap, resulting in either bad looking or
sometimes completely unreadable labels.

This RFC proposes a mechanism to detect overlapping characters in ANGLE FOLLOW
labels and simply skip the labels, leaving room for other/better labels to fall
around the same spot, leading to better looking maps.

In ticket `#2221 <https://github.com/mapserver/mapserver/issues/2221>`__, several 
options were discussed to improve problematic ANGLE FOLLOW labels, including 
line smoothing, or increasing the spacing between the characters when 
overlaps are detected, those approaches may have potential but will be 
dealt with separately (i.e. in their own RFCs). 

This RFC deals specifically with skipping bad labels with too much character 
overlap and ticket `#3523 <https://github.com/mapserver/mapserver/issues/3523>`__ 
has been created for it.

Background
------------------------------------------------------------------------------

This issue was found as part of the FOSS4G 2010 Benchmarking exercise where one
of the layers to render was contours with labels. We've seen that MapServer  
did a poor job of labeling some contours with sharp curves using ANGLE FOLLOW,
resulting in overlapping characters and unreadable labels.

OTOH, we found that GeoServer for instance didn't have this type of 
problematic labels because it simply detected the overlapping chars and 
skipped those labels. This is the approach we propose to implement here.

Here are two maps of the same area, the first produced by MapServer with the
bad labels and the second by GeoServer without the bad labels:

http://trac.osgeo.org/mapserver/attachment/ticket/3523/mapserver-wms.png

http://trac.osgeo.org/mapserver/attachment/ticket/3523/geoserver-wms.png

Experiments
------------------------------------------------------------------------------

We have found that it is of no use to test the character bboxes for 
overlap since most of them overlap in normal situations as we can see in 
the following images:

http://trac.osgeo.org/mapserver/attachment/ticket/3523/mapserver-label-boxes.png

OTOH we found that we could compare the angles of consecutive characters 
within a given label and use that as a better indicator of 
possible overlap. In most cases, a overlap of more than 22.5 degrees 
is a good threshold to use to decide to skip a given label.

The following image shows the same contours in which labels with character
overlap larger than 22.5 degrees are skipped:

http://trac.osgeo.org/mapserver/attachment/ticket/3523/mapserver-label-with-fix.png

Here is another example with a street map:

http://trac.osgeo.org/mapserver/attachment/ticket/3523/maxoverlapangle-2.png


Technical Solution
------------------------------------------------------------------------------

A new MAXOVERLAPANGLE keyword will be added to the LABEL object, whose
value is the angle threshold to use in filtering out ANGLE FOLLOW labels in 
which characters overlap (floating point value in degrees). 

This filtering will be enabled by default starting with MapServer 6.0. The 
default MAXOVERLAPANGLE value will be 22.5 degrees, which also matches the
default in GeoServer. Users will be free to tune the value up or down 
depending on the type of data they are dealing with and their tolerance 
to bad overlap in labels.

Setting MAXOVERLAPANGLE == 0 will completely disable filtering of labels
based on this criteria, restoring the pre-6.0 behavior.

Usage example
------------------------------------------------------------------------------

This feature is enabled by default with a default value of 22.5 degrees, 
so no mapfile changes are required to enable it.

This example will increase the MAXOVERLAPANGLE to 30 degrees, resulting in 
less labels being skipped:

::

  MAP
    ...
    LABEL
       ANGLE FOLLOW
       ...
       MAXOVERLAPANGLE 30
    END
    ...   
  END


Keep in mind that this option can be combined with REPEATDISTANCE and 
MINDISTANCE to produce maps with even more labels. Here is an example:

::

  MAP
    ...
    LABEL
       ANGLE FOLLOW
       ...
       MAXOVERLAPANGLE 22.5
       REPEATDISTANCE 400
       MINDISTANCE 100
    END
    ...   
  END

... and here is the resulting contour map with the above settings:

http://trac.osgeo.org/mapserver/attachment/ticket/3523/mapserver-collisions-repeatdistance-400-min-100.png


Backwards Compatibility Issues
------------------------------------------------------------------------------

This new feature will be enabled by default with a default MAXOVERLAPANGLE 
value of 22.5 degreees. Existing mapfiles will work without any change, but 
may end up producing maps with less labels if they contain several bad labels 
with overlapping characters. It is always possible to come back to the old
behavior (disabling filtering) using MAXOVERLAPANGLE 0 or to tune the value
up or down to get better results.

There is no other backwards compatibility issue.

Files Impacted
------------------------------------------------------------------------------

* mapfile.c
* mapfile.h
* mapserver.h
* maplexer.c
* maplexer.l
* mapprimitive.c


Ticket Id
------------------------------------------------------------------------------

Main ticket:

* http://trac.osgeo.org/mapserver/attachment/ticket/3523

See also:

* http://trac.osgeo.org/mapserver/attachment/ticket/2221



Voting History
------------------------------------------------------------------------------

Adopted on 2010-09-23 with +1 from DanielM, SteveL, FrankW, TomK, PericlesN, ThomasB, SteveW, HowardB, AssefaY, JeffM and TamasS.
