Class TLspContinuousLabelingAlgorithm
- All Implemented Interfaces:
ILcdCloneable
,ILspLabelingAlgorithm
,Cloneable
ILspLabelingAlgorithm
that
offers continuously decluttered labels, ideally suited for moving objects (e.g., tracks).
When the objects move, the labels move along and avoid overlap in a continuous fashion by moving the representations around gently. The locations of the representations are not limited to a fixed number of possible locations, instead a representation can be put everywhere on the map. By default there is no hard constraint on the distance between the representation and the object. The representations do tend to move to their desired location though.
Using this class, the desired location of the representations can be specified for all representations at once or for every representation individually.
Which representations are
removed in the process is defined by the max coverage
property. Which representations should be dropped first is influenced by the priorities returned
by LabelContext.getPriority
. The default is to never drop any labels.
You can configure the positioning of the labels in various ways:
- Use
setPadding(double)
to add space between labels. - Use
setReuseLocationsScaleRatioInterval(com.luciad.util.ILcdInterval)
to keep the relative location after zooming in the view. - Use
setClampOnScreenEdges(boolean)
to specify if labels can be partially outside the view. - Use
setLabelMovementBehavior(com.luciad.realtime.lightspeed.labeling.TLspContinuousLabelingAlgorithm.LabelMovementBehavior)
to specify when labels should be moved. - Use
setMinDistance(float)
to ensure labels are never too close to their object. - Use
setMaxDistance(float)
to ensure labels are never too far from their object. - Use
setDisallowedAngle(float)
to specify where a label can be positioned around its object.
This algorithm uses the
obstacles and placements from the given ILspLabelConflictChecker
to avoid placing representations at these locations.
For smooth
visual results, this algorithm should be triggered regularly. This can for example be done by
using the TLcdSimulator
, or by refreshing the label
location placement using a timer, e.g. :
Timer timer = new Timer( 50, new ActionListener() {
public void actionPerformed( ActionEvent e ) {
ILsp view = ...;
view.getLabelPlacer().invalidate( "refresh" );
view.getLabelPlacer().placeLabels( view );
}
});
timer.setRepeats( true );
timer.start();
Notes:
- This labeling algorithm never drops labels. This means that in some cases, when many labels need to be displayed, labels can overlap.
- This algorithm assumes the
ILspLabelPainter
of the layer implementsILspStampLocationLabelPainter
as it can only declutter labels if they can be placed freely, not when placement is limited to a fixed number of locations. - The dimensions of the bounds returned by the
ILspLabelPainter
need to be independent of the location of the label for this algorithm to work well. - This class supports rotated labels and rotated obstacles. However for performance reasons the axis aligned bounds of these labels are used in most calculations. Because of this, labels might not be optimally placed.
- The implementation of this algorithm is thread-safe if the set master-slave dependency provider is thread-safe, the label priority provider is thread-safe and all overridden methods are implemented in a thread-safe manner.
- Since:
- 2012.0
-
Nested Class Summary
Modifier and TypeClassDescriptionstatic enum
Indicates when labels should be moved.Nested classes/interfaces inherited from interface com.luciad.view.lightspeed.label.algorithm.ILspLabelingAlgorithm
ILspLabelingAlgorithm.LabelContext
-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionclone()
MakesObject.clone()
public.Returns the desired relative location.float
Returns the size of the disallowed range.Indicates when labels are moved.Returns the dependency provider that defines the master-slave dependency between view representations.double
Returns the maximum coverage ratio.int
Returns the maximum declutter time.float
Returns the configured maximum allowed distance.float
Returns the configured minimum allowed distance.protected double
getOrientation
(Object aDomainObject) Retrieves a domain object's orientation.double
Returns the padding around the labels.Returns the scale ratio interval in which label locations are reused.boolean
Indicates whether labels are clamped against screen edges.placeLabels
(List<TLspLabelID> aLabelIDs, ILspLabelingAlgorithm.LabelContext aLabelContext, ILspLabelConflictChecker aConflictChecker, ILspView aView) protected void
retrieveDesiredLocation
(TLspLabelID aLabel, TLspPaintState aPaintState, TLspContext aContext, Point aRelativeLocationSFCT) Retrieves the desired view location for the given label.void
setClampOnScreenEdges
(boolean aEnabled) Enable or disable clamping labels against screen edges.void
setDesiredRelativeLocation
(Point aDesiredRelativeLocation) Sets the desired relative view location: the location the labels tend to move to.void
setDisallowedAngle
(float aArcAngle) Set a range, relative to the object's heading, where labels cannot be placed.void
Indicate when labels should be moved.void
setMasterSlaveDependencyProvider
(ILspLabelDependencyProvider aDependencyProvider) Sets the dependency provider that defines the master-slave dependency between view representations.void
setMaxCoverage
(double aMaxCoverage) Sets the maximum coverage ratio.void
setMaxDeclutterTime
(int aMaxDeclutterTime) Sets the maximum time (in ms) that should be spend in decluttering the labels.void
setMaxDistance
(float aMaximumDistance) Set the maximum allowed distance of a label to its anchor point.void
setMinDistance
(float aMinimumDistance) Set the minimum allowed distance of a label to its anchor point.void
setPadding
(double aPadding) Sets the padding around the labels.void
setReuseLocationsScaleRatioInterval
(ILcdInterval aReuseLocationsScaleRatioInterval) Sets the scale ratio interval in which the label locations are reused.
-
Constructor Details
-
TLspContinuousLabelingAlgorithm
public TLspContinuousLabelingAlgorithm()
-
-
Method Details
-
setLabelMovementBehavior
public void setLabelMovementBehavior(TLspContinuousLabelingAlgorithm.LabelMovementBehavior aBehavior) Indicate when labels should be moved.- Use
MINIMAL_MOVEMENT
to avoid moving labels as much as possible - Use
REDUCED_MOVEMENT
to avoid moving labels when they are near other labels, but keep them close to their object - Use
OPTIMAL_SPREAD
to ensure an optimal spread of labels
The default is
OPTIMAL_SPREAD
.- Parameters:
aBehavior
- The desired behavior- Since:
- 2012.1
- Use
-
getLabelMovementBehavior
Indicates when labels are moved.- Returns:
- The current setting
- Since:
- 2012.1
- See Also:
-
setMinDistance
public void setMinDistance(float aMinimumDistance) Set the minimum allowed distance of a label to its anchor point.If set, a label cannot move closer to its anchor point than this distance. The distance is calculated from the point of the label closest to the anchor.
By default, the minimum distance is disabled (
0
).- Parameters:
aMinimumDistance
- the minimum distance, in pixels.
-
getMinDistance
public float getMinDistance()Returns the configured minimum allowed distance.- Returns:
- The configured minimum allowed distance.
- See Also:
-
setMaxDistance
public void setMaxDistance(float aMaximumDistance) Set the maximum allowed distance of a label to its anchor point.If set, a label cannot move further from its anchor point than this distance. The distance is calculated from the point of the label closest to the anchor.
By default, the maximum distance is disabled (
Float#POSITIVE_INFINITY
).- Parameters:
aMaximumDistance
- the maximum distance, in pixels.
-
getMaxDistance
public float getMaxDistance()Returns the configured maximum allowed distance.- Returns:
- The configured maximum allowed distance.
- See Also:
-
setDisallowedAngle
public void setDisallowedAngle(float aArcAngle) Set a range, relative to the object's heading, where labels cannot be placed.If set, a label cannot move inside the disallowed area. A label's arc is calculated between its center of the label, the anchor point and the orientation.
For example, to ensure a label is never "in front of" its object, use
setDisallowedAngle(120)
.Domain objects must implement
ILcdOriented
to use this feature, or you can overridegetOrientation(Object)
to use a custom implementation.By default, the disallowed range is disabled (0 degrees).
- Parameters:
aArcAngle
- The size of the range in which labels should not be positioned, in degrees, spread evenly around the object's orientation.
-
getDisallowedAngle
public float getDisallowedAngle()Returns the size of the disallowed range.- Returns:
- The size of the range in which labels should not be positioned, in degrees, spread evenly around the object's orientation.
- See Also:
-
setClampOnScreenEdges
public void setClampOnScreenEdges(boolean aEnabled) Enable or disable clamping labels against screen edges.If enabled, labels for visible objects are always fully visible. If disabled, labels can be partially outside the view.
By default, this is enabled.
- Parameters:
aEnabled
-true
if it should be enabled,false
otherwise.
-
isClampOnScreenEdges
public boolean isClampOnScreenEdges()Indicates whether labels are clamped against screen edges.- Returns:
true
if enabled,false
otherwise.- See Also:
-
getReuseLocationsScaleRatioInterval
Returns the scale ratio interval in which label locations are reused.- Returns:
- the scale ratio interval in which label locations are reused.
- See Also:
-
setReuseLocationsScaleRatioInterval
Sets the scale ratio interval in which the label locations are reused. To avoid labels suddenly jumping from one location to another, the previous label locations are reused (as stored inALspLabelLocations
). If large changes in scale occur (e.g., zooming in/out), trying to reuse those locations is no longer useful as visual contact with the labels is lost anyway. Using this interval, one can specify for which scale changes the label locations should be reused, using a lower and an upper ratio. For example setting this value tonew TLcdInterval(0.8, 1.2)
means that the label locations are reused if new scale (e.g., after zooming) divided by the old scale (e.g., before zooming) is within the interval [0.8, 1.2]. If this interval is set tonull
, label locations are never reused.- Parameters:
aReuseLocationsScaleRatioInterval
- The scale ratio interval.
-
getDesiredRelativeLocation
Returns the desired relative location.- Returns:
- the desired relative location.
- See Also:
-
setDesiredRelativeLocation
Sets the desired relative view location: the location the labels tend to move to. The location of the representation is relative to the anchor point of the object it belongs to. So if for example the relative location is set tonew Point( 10, 10 )
, all representations (that is, their anchors) tend to move to an offset of (10, 10) to the object they belong to. See alsoretrieveDesiredLocation(com.luciad.view.lightspeed.painter.label.TLspLabelID, com.luciad.view.lightspeed.layer.TLspPaintState, com.luciad.view.lightspeed.TLspContext, java.awt.Point)
.- Parameters:
aDesiredRelativeLocation
- The desired location relative to the anchor point of the object.- See Also:
-
retrieveDesiredLocation
protected void retrieveDesiredLocation(TLspLabelID aLabel, TLspPaintState aPaintState, TLspContext aContext, Point aRelativeLocationSFCT) Retrieves the desired view location for the given label. The desired location is specified relative to the anchor point of the object, and it is the representation anchor point that tends to move there.By default, aRelativeLocationSFCT is modified to equal the result of
getDesiredRelativeLocation
.Override this method to specify the desired location differently for every label. This for example can be used to avoid that labels would like to be at the location where a track is heading to.
- Parameters:
aLabel
- the label for which a desired location is returned.aPaintState
- the paint stateaContext
- the context.aRelativeLocationSFCT
- The location this method adapts as a side effect, relative to the anchor point of the object.- See Also:
-
getMaxCoverage
public double getMaxCoverage()Returns the maximum coverage ratio.- Returns:
- the maximum coverage ratio.
- See Also:
-
setMaxCoverage
public void setMaxCoverage(double aMaxCoverage) Sets the maximum coverage ratio. It controls when to start dropping labels if the view contains too many of them.It is defined as the surface used by the labels (approximated by their bounds) divided by the total surface of the view, so typical values are in the range of ]0,1]. To for example start dropping representations if more than 30% of the view would be covered by view representation, set this property to 0.3. A value of for example 2 means the labels can use the available screen space twice (so possibly a lot of overlap). Set it to
Double.MAX_VALUE
to never drop any labels (the default value).- Parameters:
aMaxCoverage
- The maximum coverage, must be larger than or equal to 0.
-
getMaxDeclutterTime
public int getMaxDeclutterTime()Returns the maximum declutter time.- Returns:
- the maximum declutter time.
- See Also:
-
setMaxDeclutterTime
public void setMaxDeclutterTime(int aMaxDeclutterTime) Sets the maximum time (in ms) that should be spend in decluttering the labels. Providing a smaller limit may cause positioning to be less optimal.This time value is a hint, not a hard limit.
- Parameters:
aMaxDeclutterTime
- The maximum time that can be spend in decluttering, in ms.
-
getMasterSlaveDependencyProvider
Returns the dependency provider that defines the master-slave dependency between view representations.- Returns:
- the dependency provider that defines the master-slave dependency between view representations.
- See Also:
-
setMasterSlaveDependencyProvider
Sets the dependency provider that defines the master-slave dependency between view representations.The master-slave dependency is defined as follows. The slave always follows the master. If the master representation is translated, the slave representation is translated by the same amount. If the master representation is sticky, so is the slave representation, and vice-versa.
- Parameters:
aDependencyProvider
- the dependency provider that defines the master-slave dependency between labels. Can benull
.
-
getPadding
public double getPadding()Returns the padding around the labels.- Returns:
- the padding around the labels, in pixels.
- See Also:
-
setPadding
public void setPadding(double aPadding) Sets the padding around the labels. This padding is added to the bounds of the labels, enlarging it during placement.
In practice this means that the bigger the padding, the more space between the labels.
By default, this value is
0.0
.- Parameters:
aPadding
- the padding, in pixels.- Throws:
IllegalArgumentException
- when the given padding is smaller than0
.- See Also:
-
clone
Description copied from interface:ILcdCloneable
Makes
When for example extending fromObject.clone()
public.java.lang.Object
, it can be implemented like this:public Object clone() { try { return super.clone(); } catch ( CloneNotSupportedException e ) { // Cannot happen: extends from Object and implements Cloneable (see also Object.clone) throw new RuntimeException( e ); } }
- Specified by:
clone
in interfaceILcdCloneable
- Overrides:
clone
in classObject
- See Also:
-
placeLabels
public List<TLspLabelPlacement> placeLabels(List<TLspLabelID> aLabelIDs, ILspLabelingAlgorithm.LabelContext aLabelContext, ILspLabelConflictChecker aConflictChecker, ILspView aView) Description copied from interface:ILspLabelingAlgorithm
This method computes a list of label placements for the given
List
of labels. The returned label placements should contain a valid label location and label bounds. They should also point to their correspondingTLspLabelID
The returned
List
ofTLspLabelPlacement
s contains label placements that are either visible or invisible. When a placement is present in the list, it means that the location should be stored. When a placement in the list is marked as visible, it means that its location should be marked as visible in thelabel placer
- Specified by:
placeLabels
in interfaceILspLabelingAlgorithm
- Parameters:
aLabelIDs
- the labels to be placed.aLabelContext
- provides context information, such as priorities, PaintState, ...aConflictChecker
- the conflict checker that can be used to detect conflicts between labels.aView
- the view.- Returns:
- a list of label placements.
-
getOrientation
Retrieves a domain object's orientation. The orientation is used when a disallowed angle is specified (seesetDisallowedAngle(float)
).The result must be expressed as an azimuth, in degrees, clockwise starting from 12 o'clock.
Return
Double.NaN
if no orientation can be calculated or if it is not applicable.The default implementation returns an orientation if the object is
ILcdOriented
, orDouble.NaN
otherwise.- Parameters:
aDomainObject
- the domain object- Returns:
- the domain object's orientation, in degrees, clockwise starting from 12 o'clock.
- See Also:
-