public class TLcdGXYLocationListLabelingAlgorithm extends ALcdGXYDiscretePlacementsLabelingAlgorithm
ILcdGXYLabelPainter2
)
to determine label locations. It tries to place labels in the order provided by the input
TLcdCollectedLabelInfoList
object (see TLcdCollectedLabelInfoList.getLabels()
).
It tries to place the labels one by one, and when a label cannot be placed without overlap,
it is omitted.
This algorithm uses free placements to determine the location and bounds of the labels. So this algorithm gives full control over where labels are actually placed. This labeling algorithm can be extended to provide custom locations for a label. To do this, 2 methods need to be overridden :
getMaxLocationCount()
: Override this method to set the number
of locations that are tried for a label.getLocationBounds()
: Override this method to return label bounds
associated with a location. This method should be able to return
getMaxLocationCount
bounds.TLcdLabelLocation
. One of these label location is eventually chosen for
the label.
The default implementations of these methods use the following methods : getLocationList()
and getShiftLabelLocation()
. So the default behavior of this class can be customized
by using setLocationList(Location[])
and setShiftLabelLocation(int)
. When overriding
getMaxLocationCount()
and getLocationBounds()
,
getLocationList()
and getShiftLabelLocation()
will not be used anymore.
This algorithm also uses a forced painting threshold priority to force labels to be placed,
even if they overlap with other labels, see setForcedPaintingThresholdPriority(int)
.
The used label painter must be an ILcdGXYLabelPainter2
.
If not, labels will be painted at an incorrect location.
The implementation of this labeling algorithm is thread-safe.
Modifier and Type | Class and Description |
---|---|
static class |
TLcdGXYLocationListLabelingAlgorithm.Location |
Constructor and Description |
---|
TLcdGXYLocationListLabelingAlgorithm() |
Modifier and Type | Method and Description |
---|---|
TLcdGXYLocationListLabelingAlgorithm |
clone()
Makes
Object.clone() public. |
TLcdCollectedLabelInfoList |
collectLabelInfo(List<TLcdLabelIdentifier> aLabelsToCollect,
Graphics aGraphics,
ILcdGXYView aGXYView)
This method returns a
TLcdCollectedLabelInfoList object based
on the given list of TLcdLabelIdentifier s. |
protected Iterator<TLcdCollectedLabelInfo> |
createLabelIterator(TLcdCollectedLabelInfoList aLabelInfoList,
ILcdLabelConflictChecker aBoundsConflictChecker,
ILcdGXYView aView)
Creates a new
Iterator that iterates over the TLcdCollectedLabelInfo s. |
protected ILcdLabelPlacementEvaluator |
createLabelPlacementEvaluator(TLcdCollectedLabelInfoList aLabelInfoList,
ILcdLabelConflictChecker aBoundsConflictChecker,
ILcdGXYView aView)
Creates a new
ILcdLabelPlacementEvaluator using the given parameters. |
protected Iterator<TLcdLabelPlacement> |
createLabelPlacementIterator(TLcdCollectedLabelInfo aLabel,
TLcdCollectedLabelInfoList aLabelInfoList,
ILcdLabelConflictChecker aBoundsConflictChecker,
ILcdGXYView aView)
Creates a new
Iterator that iterates over the TLcdLabelPlacement s
for the given label. |
int |
getForcedPaintingThresholdPriority()
Returns the threshold priority for forced label painting.
|
ILcdGXYMultiLabelPriorityProvider |
getLabelPriorityProvider()
Returns the label placing priority provider.
|
protected double |
getLocationBounds(TLcdCollectedLabelInfo aLabelInfo,
int aLocationIndex,
TLcdCollectedLabelInfoList aLabelInfoList,
Rectangle aBoundsSFCT)
This method calculates the bounds for the given label using the given location index.
|
TLcdGXYLocationListLabelingAlgorithm.Location[] |
getLocationList()
Returns the list of possible locations to place the labels.
|
protected int |
getMaxLocationCount(TLcdCollectedLabelInfo aLabelInfo,
TLcdCollectedLabelInfoList aLabelInfoList)
Returns the maximal number of locations to be tried for the given label.
|
int |
getShiftLabelLocation()
Returns how many pixels the label must be removed from the anchor point of the domain object.
|
void |
setForcedPaintingThresholdPriority(int aPriority)
Sets the threshold priority for forced label painting.
|
void |
setLabelPriorityProvider(ILcdGXYMultiLabelPriorityProvider aLabelPriorityProvider)
Sets the label placing priority provider, specifying the priority for individual
labels.
|
void |
setLocationList(TLcdGXYLocationListLabelingAlgorithm.Location[] aLocationList)
Sets a new location list.
|
void |
setShiftLabelLocation(int aShift)
Sets how many pixels the label must be removed from the anchor point of the domain object.
|
computeLabelPlacements
public TLcdGXYLocationListLabelingAlgorithm()
public TLcdGXYLocationListLabelingAlgorithm clone()
ILcdCloneable
Makes Object.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 );
}
}
clone
in interface ILcdCloneable
clone
in class ALcdGXYDiscretePlacementsLabelingAlgorithm
Object.clone()
public void setForcedPaintingThresholdPriority(int aPriority)
-1
,
in which case no forced painting is done.aPriority
- the threshold priority for forced label painting.getForcedPaintingThresholdPriority()
public int getForcedPaintingThresholdPriority()
setForcedPaintingThresholdPriority(int)
public ILcdGXYMultiLabelPriorityProvider getLabelPriorityProvider()
setLabelPriorityProvider(com.luciad.view.gxy.ILcdGXYMultiLabelPriorityProvider)
public void setLabelPriorityProvider(ILcdGXYMultiLabelPriorityProvider aLabelPriorityProvider)
When no label priority provider is set, a default label priority provider is used
which returns Integer.MAX_VALUE
for all labels.
The priority provider is used to sort the list of labels before their placements are computed.
aLabelPriorityProvider
- The priority provider to set.protected int getMaxLocationCount(TLcdCollectedLabelInfo aLabelInfo, TLcdCollectedLabelInfoList aLabelInfoList)
getLocationBounds
method can create the same number of
location bounds as returned by this method.
The default implementation uses the length of the array returned by getLocationList()
.
aLabelInfo
- the label for which the maximum placement count is returned.aLabelInfoList
- the label infos object.protected double getLocationBounds(TLcdCollectedLabelInfo aLabelInfo, int aLocationIndex, TLcdCollectedLabelInfoList aLabelInfoList, Rectangle aBoundsSFCT) throws IllegalArgumentException
The default implementation of this method uses the positions returned by getLocationList()
,
combined with the offset retrieved by getShiftLabelLocation()
.
aLabelInfo
- the label for which placement bounds are calculated.aLocationIndex
- the placement index.aBoundsSFCT
- the bounds to be initialized.aLabelInfoList
- the label infos object.IllegalArgumentException
- this exception can be thrown when certain data to calculate
the bounds is not available.public void setLocationList(TLcdGXYLocationListLabelingAlgorithm.Location[] aLocationList)
This method is used by the default implementation of getLocationBounds
.
By default, all TLcdGXYLocationListLabelingAlgorithm.Location
values are offered.
aLocationList
- the list of possible locations to place the labels.getLocationList()
,
getLocationBounds
,
getMaxLocationCount
public TLcdGXYLocationListLabelingAlgorithm.Location[] getLocationList()
By default this method returns an array containing
TLcdGXYLocationListLabelingAlgorithm.Location.SOUTH_EAST
.TLcdGXYLocationListLabelingAlgorithm.Location.NORTH_WEST
.TLcdGXYLocationListLabelingAlgorithm.Location.NORTH_EAST
.TLcdGXYLocationListLabelingAlgorithm.Location.SOUTH_WEST
.TLcdGXYLocationListLabelingAlgorithm.Location.EAST
.TLcdGXYLocationListLabelingAlgorithm.Location.WEST
.TLcdGXYLocationListLabelingAlgorithm.Location.NORTH
.TLcdGXYLocationListLabelingAlgorithm.Location.SOUTH
.TLcdGXYLocationListLabelingAlgorithm.Location.CENTER
.
This method is used by the default implementation of getLocationBounds
.
setLocationList(com.luciad.view.gxy.labeling.algorithm.discrete.TLcdGXYLocationListLabelingAlgorithm.Location[])
,
getLocationBounds
,
getMaxLocationCount
public void setShiftLabelLocation(int aShift)
east
or west
, this
shift is applied in horizontal direction; if the location is north
or
south
, this shift is applied in vertical direction. In case of
north east
, south east
,
south west
or north west
, this
shift is applied in both directions. If the location of the label is center
,
the shift is ignored.
The default for this value is 4
pixels.
This method is used by the default implementation of getLocationBounds
.
aShift
- the distance, expressed in pixels, that the label must be removed
from the domain object.getShiftLabelLocation()
,
getLocationBounds
public int getShiftLabelLocation()
This method is used by the default implementation of getLocationBounds
.
setShiftLabelLocation(int)
,
getLocationBounds
public TLcdCollectedLabelInfoList collectLabelInfo(List<TLcdLabelIdentifier> aLabelsToCollect, Graphics aGraphics, ILcdGXYView aGXYView)
ILcdGXYLabelingAlgorithm
TLcdCollectedLabelInfoList
object based
on the given list of TLcdLabelIdentifier
s. The returned
TLcdCollectedLabelInfoList
should contain a TLcdCollectedLabelInfo
object for each label that should be placed.
Each TLcdCollectedLabelInfo
should also contain all information needed by
computeLabelPlacements
to place the labels. In order to enable
correct asynchronous label placing, all calls to the layer and the (label) painters should be
done in this method. The results should then be stored in the info objects.
It is possible that the returned TLcdCollectedLabelInfoList
doesn't contain a
TLcdCollectedLabelInfo
object for every given TLcdLabelIdentifier
.
In that case the missing labels are not placed.
collectLabelInfo
in interface ILcdGXYLabelingAlgorithm
aLabelsToCollect
- the labels for which a TLcdCollectedLabelInfoList
should
be created.aGraphics
- the graphics.aGXYView
- the view.TLcdCollectedLabelInfoList
which contains all the information needed to
place the labels.protected Iterator<TLcdCollectedLabelInfo> createLabelIterator(TLcdCollectedLabelInfoList aLabelInfoList, ILcdLabelConflictChecker aBoundsConflictChecker, ILcdGXYView aView)
ALcdGXYDiscretePlacementsLabelingAlgorithm
Iterator
that iterates over the TLcdCollectedLabelInfo
s.
The abstract labeling algorithm will continue iterating over TLcdCollectedLabelInfo
s
as long as Iterator.hasNext()
returns true
. When it returns false
,
no more labels will be tried, and computeLabelPlacements
returns.
Iterator.hasNext()
should always be called before calling Iterator.next()
, and
if it returns true
, Iterator.next()
should never return null
.
The implementation of this method should be as independent as possible. It should not rely on
createLabelPlacementIterator
or
createLabelPlacementEvaluator
.
Not respecting this might result in unexpected behaviour when wrapping or extending this class.
The returned TLcdCollectedLabelInfo
should be correctly initialized, i.e. it should
contain all information needed to create valid TLcdLabelPlacement
s using
createLabelPlacementIterator
. It should also always point
to its corresponding TLcdCollectedLabeledObjectInfo
.
Override this method to provide a custom implementation.
createLabelIterator
in class ALcdGXYDiscretePlacementsLabelingAlgorithm
aLabelInfoList
- the label infos object that contains all information needed to place the labels.aBoundsConflictChecker
- the bounds conflict checker to be used when evaluating label placements.aView
- the view.Iterator
that iterates over TLcdCollectedLabelInfo
s.protected Iterator<TLcdLabelPlacement> createLabelPlacementIterator(TLcdCollectedLabelInfo aLabel, TLcdCollectedLabelInfoList aLabelInfoList, ILcdLabelConflictChecker aBoundsConflictChecker, ILcdGXYView aView)
ALcdGXYDiscretePlacementsLabelingAlgorithm
Iterator
that iterates over the TLcdLabelPlacement
s
for the given label. The abstract labeling algorithm will continue iterating over
TLcdLabelPlacement
s as long as Iterator.hasNext()
returns true
.
When it returns false
, a new label will be tried. Iterator.hasNext()
should
always be called before calling Iterator.next()
, and if it returns true
,
Iterator.next()
should never return null
.
The implementation of this method should be as independent as possible. It should not rely on
createLabelIterator
or createLabelPlacementEvaluator
.
Not respecting this might result in unexpected behaviour when wrapping or extending this class.
The returned TLcdLabelPlacement
should be correctly initialized, i.e. it should at
least be able to return a valid label location, bounds rectangle and bounds rotation. It should
also reference its corresponding TLcdCollectedLabelInfo
.
Override this method to provide a custom implementation.
createLabelPlacementIterator
in class ALcdGXYDiscretePlacementsLabelingAlgorithm
aLabel
- the label for which an iterator should be created.aLabelInfoList
- the info object that contains all information needed to place the labels.aBoundsConflictChecker
- the bounds conflict checker to be used when evaluating label placements.aView
- the view.Iterator
that iterates over TLcdLabelPlacement
s.protected ILcdLabelPlacementEvaluator createLabelPlacementEvaluator(TLcdCollectedLabelInfoList aLabelInfoList, ILcdLabelConflictChecker aBoundsConflictChecker, ILcdGXYView aView)
ALcdGXYDiscretePlacementsLabelingAlgorithm
ILcdLabelPlacementEvaluator
using the given parameters. It evaluates
the placements returned by createLabelPlacementIterator
,
and returns a PlacementResult
to denote if the placement should be used for its
label or not.
The following actions are undertaken for the following placement results :
PlacementResult.SUCCESS
:
the given label placement will be used for its label, it will be added to the list of placed
labels, and it will be added to the given ILcdLabelConflictChecker
. After that,
ILcdLabelPlacementEvaluator.placementApplied
will be called and no more placements are tried for the label.PlacementResult.FALLBACK
:
the abstract algorithm will try to find an other placements which returns
PlacementResult.SUCCESS
.
When no such placement is found, this placement will be added to the list of placed labels,
and it will be added to the given ILcdLabelConflictChecker
. After that,
ILcdLabelPlacementEvaluator.placementApplied
will be called.PlacementResult.TRY_NEW_PLACEMENT
:
the abstract algorithm will try to find an other placement which returns
PlacementResult.SUCCESS
or
PlacementResult.FALLBACK
.
When no such placement is found, ILcdLabelPlacementEvaluator.noPlacementApplied
is called.PlacementResult.FAILED
: the
abstract algorithm will immediately call ILcdLabelPlacementEvaluator.noPlacementApplied
and will not try to find other placements for the label.Override this method to provide a custom implementation.
createLabelPlacementEvaluator
in class ALcdGXYDiscretePlacementsLabelingAlgorithm
aLabelInfoList
- the info object that contains all information needed to place the labels.aBoundsConflictChecker
- the bounds conflict checker to be used when evaluating label placements.aView
- the viewILcdLabelPlacementEvaluator