Class TLspContinuousLabelingAlgorithm

java.lang.Object
com.luciad.realtime.lightspeed.labeling.TLspContinuousLabelingAlgorithm
All Implemented Interfaces:
ILcdCloneable, ILspLabelingAlgorithm, Cloneable

public class TLspContinuousLabelingAlgorithm extends Object implements ILspLabelingAlgorithm
Implementation of 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:

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 implements ILspStampLocationLabelPainter 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
  • 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
    • getLabelMovementBehavior

      public TLspContinuousLabelingAlgorithm.LabelMovementBehavior 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 override getOrientation(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

      public ILcdInterval 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

      public void setReuseLocationsScaleRatioInterval(ILcdInterval aReuseLocationsScaleRatioInterval)
      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 in ALspLabelLocations). 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 to new 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 to null, label locations are never reused.

      Parameters:
      aReuseLocationsScaleRatioInterval - The scale ratio interval.
    • getDesiredRelativeLocation

      public Point getDesiredRelativeLocation()
      Returns the desired relative location.
      Returns:
      the desired relative location.
      See Also:
    • setDesiredRelativeLocation

      public void setDesiredRelativeLocation(Point aDesiredRelativeLocation)
      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 to new 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 also retrieveDesiredLocation(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 state
      aContext - 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

      public ILspLabelDependencyProvider 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

      public void setMasterSlaveDependencyProvider(ILspLabelDependencyProvider aDependencyProvider)
      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 be null.
    • 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 than 0.
      See Also:
    • clone

      Description copied from interface: ILcdCloneable

      Makes Object.clone() public.

      When for example extending from 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 interface ILcdCloneable
      Overrides:
      clone in class Object
      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 corresponding TLspLabelID

      The returned List of TLspLabelPlacements 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 the label placer

      Specified by:
      placeLabels in interface ILspLabelingAlgorithm
      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

      protected double getOrientation(Object aDomainObject)
      Retrieves a domain object's orientation. The orientation is used when a disallowed angle is specified (see setDisallowedAngle(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, or Double.NaN otherwise.

      Parameters:
      aDomainObject - the domain object
      Returns:
      the domain object's orientation, in degrees, clockwise starting from 12 o'clock.
      See Also: