public abstract class IlvAnnealingLabelDescriptor
extends java.lang.Object
IlvAnnealingLabelDescriptor
is the abstract
base class of all label descriptors. A label descriptor is used to
describe how a label can move during the Simulated Annealing label
layout. One subclass is for instance the
IlvAnnealingPointLabelDescriptor
that is used to describe
that a label must be placed close to a fixed point, as for instance
needed to label the cities of a map. Another subclass is the
IlvAnnealingPolylineLabelDescriptor
that is used to
describe that a label must be placed near a polyline link of a graph.
Simulated Annealing moves the label basically on a path. It allows the
label to leave the path in a very close area, so the actual position
can be described by a point on the path plus the distance of the label
from this path. For instance, for the
IlvAnnealingPointLabelDescriptor
, the path may be
approximately a circle (in fact, it is an elliptically rounded
rectangle), that is, the label can move along this path around the
reference point of the label. To simplify the implementation of
different paths, the Simulated Annealing does not use Cartesian
coordinates, it only specifies the abstract path location (the
distance you have to go along the path from the start point of the
path to the current path point), and the distance from this path
point. The translation of this abstract location into the
effective Cartesian coordinates of the label is done by the
implementation of the method #setPosition(double, double)
.
This allows you to use the algorithm with different paths, by
subclassing the IlvAnnealingLabelDescriptor
and
implementing your version of #setPosition(double, double)
.
For instance, assume that the label should move on a circle between radius 10 and 15 around the origin. The following code implements a corresponding label descriptor:
public class MyCircleLabelDescriptor extends IlvAnnealingLabelDescriptor { public MyCircleLabelDescriptor(Object label) { super(label); } public void initialize(IlvLabelingModel labelingModel) { // set the maximum location: // circumference of circle with radius 10 maxPathLocation = 2 * Math.PI * 10; // path is at radius 10, hence max distance from path is (15 - 10) = 5 maxDistFromPath = 5; } public void setPosition(double pathLocation, double distFromPath) { // path radius is 10. Radius for position is 10 + distFromPath, // because distFromPath is between 0 and 5 updatePosition( (double)((10 + distFromPath) * Math.cos(pathLocation / 10)); (double)((10 + distFromPath) * Math.sin(pathLocation / 10)) ); actPathLocation = pathLocation; actDistFromPath = distFromPath; } // assume that the preferred position is the path location 0 and distance // 0 from the path. public void setTowardsPreferredPosition( double pathLocation, double distFromPath, int i, int maxI) { if (pathLocation <= maxPathLocation/2) { // clockwise towards the preferred position setPosition(pathLocation - pathLocation * (i+1) / maxI, distFromPath - distFromPath * (i+1) / maxI); } else { // counter-clockwise towards the preferred position setPosition(pathLocation + pathLocation * (i+1) / maxI, distFromPath + distFromPath * (i+1) / maxI); } } }CSS example:
© Copyright 2024 Rogue Wave Software, Inc., a Perforce company.. All Rights Reserved.