Specific global parameters

The following global parameters are specific to the IlvAnnealingLabelLayout class:

Label offset

The label offset controls the desired minimum distance between two neighboring labels (see Label and obstacle offsets, left). To avoid labels being placed too close to each other, you can increase the label offset. This conceptually pushes the labels farther apart. However, depending on the available space, the minimum distance between labels cannot always be maintained.
Example of specifying label offset
To set the label offset:
In CSS
Add to the LabelLayout section:
labelOffset: "25";
In Java™
Call:
layout.setLabelOffset(25f);

Obstacle offset

The obstacle offset controls the desired minimum distance between a label and an unrelated obstacle. The obstacle offset is usually more important than the label offset because, if the obstacle offset is too small, the label may be placed so close to an unrelated obstacle that it incorrectly appears to be assigned to that obstacle (see Label and obstacle offsets, right: does, for example, the green label belong to the upper yellow node or to the green node?). Increasing the obstacle offset conceptually pushes the label away from the obstacle. However, depending on the available space, the minimum distance between label and obstacle cannot always be maintained.
The obstacle offset should not be set to an unreasonably large value (such as Float.MAX_VALUE ) because this can cause computational problems inside quadtree operations.
Example of specifying node placement iterations and allowed time (GL algorithm)
To set the obstacle offset:
In CSS
Add to the LabelLayout section:
obstacleOffset: "25";
In Java
Call:
layout.setObstacleOffset(25f);
The specified obstacle offset works globally for all labels.
In Java, it is also possible to specify a smaller obstacle offset for specific label/obstacle pairs. You need to install an obstacle offset interface that returns the obstacle offset for a specified pair:
layout.setObstacleOffsetInterface(new IlvObstacleOffsetInterface() {
    public float getOffset(IlvLabelingModel m, Object label, Object obstacle)
    {
        if (label instanceof IlvZoomableLabel &&
            obstacle instanceof IlvIcon)
            return 3f;
        else
            // use the global obstacle offset
            return Float.MAX_VALUE;
    }
});
The effective offset is the lower of the values returned by the obstacle offset interface and the globally specified offset respectively. Hence, the obstacle offset interface in the previous example means that IlvZoomableLabel labels can be placed up to 3 units near IlvIcon obstacles, while they are placed away from all other obstacles by at least the amount specified by the call layout.setObstacleOffset .
Picture
illustrating the obstacle offset and the label offset parameters
Label and obstacle offsets

Label movement policy

The label movement policy is an easy way to define which labels should be moved by the label layout algorithm.
Example of specifying label movement policy
In CSS
It is not possible to specify the label movement policy in CSS, but you can integrate a label movement policy into the label layout renderer by subclassing the renderer. An example showing how to subclass renderers is provided in Writing a new layout renderer to clip links.
In Java
The following code installs a label movement policy such that the layout moves only labels with a height greater than 100:
layout.setLabelMovementPolicy(new IlvLabelMovementPolicy() {
    public boolean allowMove(IlvLabelingModel labelingModel, Object label)
    {
        return (labelingModel.boundingBox(label).height > 100);
    }
});
Labels with smaller heights are not moved. However, they are also not completely ignored, because the layout tries to position the movable labels so that they do not overlap the immovable labels, and the label offset is respected between movable and immovable labels.
A more general useful example is a movement policy that prohibits moving labels that initially do not overlap anything. This predefined movement policy is available through the class IlvOverlappingLabelMovementPolicy. You can use this class in applications that have their own label positioning mechanism and use the Annealing Label layout only as a postprocessing step to improve the positions of overlapping labels. To install this policy, call:
layout.setLabelMovementPolicy(new IlvOverlappingLabelMovementPolicy());

Automatic update

After layout, the labels are placed close to the related obstacle according to the label descriptor. For instance, a link label is placed close to its link. However, if you move the link interactively, the label normally stays at the old position, which may be far away from the link after the movement. The label loses the connection to the link, and a new layout is necessary.
Because it is too time-consuming to redo the layout after each single interactive move, the Annealing Layout algorithm has a feature that automatically updates the labels on geometric changes, that is, the label follows the link when the link moves.
Example of specifying automatic update
To enable this feature:
In CSS
Add to the LabelLayout section:
autoUpdate: "true";
In Java
Call:
layout.setAutoUpdate(true);
If automatic update is enabled, the algorithm does not perform a full layout of all labels during each interactive change. It repositions only the label whose related obstacle has moved in one step. Thus it may produce more overlaps than a full layout. The automatic update mechanism is much faster, however, and hence better suitable for interactions.
Note
The automatic update feature works only if the labeling model provides LabelingModelEvent objects on each obstacle movement. The IlvDefaultLabelingModel provides these events. If you implement your own labeling model, you must provide these events in order to use the automatic update feature.

Expert parameters

A few parameters are available for an advanced use of the Annealing Label Layout.

Quadtree

To speed up the layout, the Annealing Label Layout algorithm uses a quadtree data structure. The quadtree enables a very efficient check for overlaps. The layout algorithm automatically detects from the graph model whether the quadtree can be used. You can switch it off explicitly by calling:
layout.setUseQuadtree(false);
Normally, it is not useful to switch the quadtree off because it slows down label positioning. However, if you implement your own labeling model, you may want to use this flag to verify that the labeling model is correct.

Simulated annealing

Simulated annealing is an iterative mechanism. In each iteration step, all labels are tested for better positions. Usually, the algorithm is capable of detecting automatically when to stop. The algorithm stops if:
  • The maximum number of iterations is reached.
  • After several iterations, no better position was found for any label.
  • After several iterations, the quality did not improve by a specified percentage.
In a few cases, it may be necessary to limit the number of iterations, which can be done by calling:
layout.setAllowedNumberOfIterations(100);
As a general hint, to obtain a reasonable layout, the allowed number of iterations should not be considerably lower than the number of labels.
Simulated Annealing stops if, after several iterations, no better position was found for any label. Because the search is randomized, this does not necessarily mean that the best position was already found; however, it indicates that finding the best position would require too much layout time. The number of ineffective iterations before stopping can be changed by calling:
layout.setMaxNumberOfFailIterations(maxNumber);
The default value is 20. If you set it to a higher value, the layout slows down but may find better positions for the labels. If you set it to a lower value, the layout stops sooner, but the label positions may be far from optimal.
In some cases, the algorithm improves the quality in each step, but the amount of improvement gets smaller in each step. In this situation, the previous fail-iteration criteria does not work well because there is an improvement in each step, but the amount of the improvement is so negligibly small that we want to stop. Therefore, it is also possible to require that the quality must improve in each step by a minimum percentage.
For example, to specify that the algorithm must improve over ten rounds by at least 2%, call:
layout.setNumberIterationsForMinImprovement(10);
layout.setMinImprovementPercentageToContinue(2);
By default, the layout stops if the quality did not improve by 0.5% over five iterations. If you set the required improvement percentage higher or the number of iterations lower, the layout stops sooner, but the label positions may be far from optimal. If you set the required percentage to 0%, this stop criterion is disabled and will no longer have any effect.