When you are drawing a polyline, or any other shape, it may be useful to add labels to some of the points that make up the
shape. You can use those to display intermediate distances between points for example, like the TLspRulerController
does, or you can display way points that make up a trajectory.
How to do it?
If you are using a Lightspeed view, you can easily add labels to points with a custom label styler. Such a styler can:
-
Submit a label for the entire polyline
-
Submit a label for each individual point
This is demonstrated by the following code:
private static class PolylineStyler extends ALspStyler {
@Override
public void style(Collection<?> aObjects, ALspStyleCollector aStyleCollector, TLspContext aContext) {
if (!(aContext.getModelReference() instanceof ILcdGeoReference)) {
throw new IllegalArgumentException("Model reference should implement ILcdGeoReference");
}
ILcdGeoReference geoReference = (ILcdGeoReference) aContext.getModelReference();
// Display the polyline with a line style
aStyleCollector.objects(aObjects).style(TLspLineStyle.newBuilder().width(2).build()).submit();
for (Object object : aObjects) {
if (object instanceof ILcdPointList) {
// Display a circle on each individual point
ILcdPointList pointList = (ILcdPointList) object;
for (int i = 0; i < pointList.getPointCount(); i++) {
ILcdPoint point = pointList.getPoint(i);
TLcdLonLatCircle circle = new TLcdLonLatCircle(point, 5000.0, geoReference.getGeodeticDatum().getEllipsoid());
aStyleCollector.object(object).geometry(circle).style(TLspLineStyle.newBuilder().width(2).color(Color.orange).build()).submit();
}
}
}
}
}
The result is the following image:
The image was generated using the code at the end of this article.
When developers implement functionality like this, they often run into this problem: only one of the labels is shown, or even none of the labels are visible. To learn why that happens, and how you can fix the problem, see My object has multiple labels, but only one appears.
Full code
package samples.lightspeed.labels.polyline;
import java.awt.Color;
import java.io.IOException;
import java.util.Collection;
import com.luciad.model.ILcdModel;
import com.luciad.model.TLcdModelDescriptor;
import com.luciad.model.TLcdVectorModel;
import com.luciad.reference.ILcdGeoReference;
import com.luciad.reference.TLcdGeodeticReference;
import com.luciad.shape.ILcdPoint;
import com.luciad.shape.ILcdPointList;
import com.luciad.shape.shape2D.TLcdLonLatCircle;
import com.luciad.shape.shape2D.TLcdXYPolyline;
import com.luciad.view.lightspeed.TLspContext;
import com.luciad.view.lightspeed.layer.ILspInteractivePaintableLayer;
import com.luciad.view.lightspeed.layer.TLspPaintState;
import com.luciad.view.lightspeed.layer.shape.TLspShapeLayerBuilder;
import com.luciad.view.lightspeed.painter.label.style.ALspLabelTextProviderStyle;
import com.luciad.view.lightspeed.style.TLspLineStyle;
import com.luciad.view.lightspeed.style.TLspTextStyle;
import com.luciad.view.lightspeed.style.styler.ALspLabelStyleCollector;
import com.luciad.view.lightspeed.style.styler.ALspLabelStyler;
import com.luciad.view.lightspeed.style.styler.ALspStyleCollector;
import com.luciad.view.lightspeed.style.styler.ALspStyler;
import samples.lightspeed.common.FitUtil;
import samples.lightspeed.common.LightspeedSample;
import samples.lightspeed.labels.util.FixedTextProviderStyle;
/**
* Sample that paints a label for every point on a polyline.
*/
public class LabelPointsOfPolylineSample extends LightspeedSample {
@Override
protected void addData() throws IOException {
TLcdXYPolyline polyline = new TLcdXYPolyline();
polyline.insert2DPoint(0, 0, 0);
polyline.insert2DPoint(1, 1, 1);
polyline.insert2DPoint(1, 2, 0.5);
TLcdVectorModel model = new TLcdVectorModel();
model.setModelDescriptor(new TLcdModelDescriptor());
model.setModelReference(new TLcdGeodeticReference());
model.addElement(polyline, ILcdModel.NO_EVENT);
ILspInteractivePaintableLayer layer = TLspShapeLayerBuilder.newBuilder()
.model(model)
.label("Polyline")
.bodyStyler(TLspPaintState.REGULAR, new PolylineStyler())
.labelStyler(TLspPaintState.REGULAR, new PolylineLabelStyler())
.build();
getView().addLayer(layer);
FitUtil.fitOnLayers(this, layer);
}
private static class PolylineStyler extends ALspStyler {
@Override
public void style(Collection<?> aObjects, ALspStyleCollector aStyleCollector, TLspContext aContext) {
if (!(aContext.getModelReference() instanceof ILcdGeoReference)) {
throw new IllegalArgumentException("Model reference should implement ILcdGeoReference");
}
ILcdGeoReference geoReference = (ILcdGeoReference) aContext.getModelReference();
// Display the polyline with a line style
aStyleCollector.objects(aObjects).style(TLspLineStyle.newBuilder().width(2).build()).submit();
for (Object object : aObjects) {
if (object instanceof ILcdPointList) {
// Display a circle on each individual point
ILcdPointList pointList = (ILcdPointList) object;
for (int i = 0; i < pointList.getPointCount(); i++) {
ILcdPoint point = pointList.getPoint(i);
TLcdLonLatCircle circle = new TLcdLonLatCircle(point, 5000.0, geoReference.getGeodeticDatum().getEllipsoid());
aStyleCollector.object(object).geometry(circle).style(TLspLineStyle.newBuilder().width(2).color(Color.orange).build()).submit();
}
}
}
}
}
private static class PolylineLabelStyler extends ALspLabelStyler {
private final TLspTextStyle fTextStyle = TLspTextStyle.newBuilder().build();
private final ALspLabelTextProviderStyle fMainTextProviderStyle = FixedTextProviderStyle.newBuilder().text("Line Label").build();
private final ALspLabelTextProviderStyle fPointTextProviderStyle = new ALspLabelTextProviderStyle() {
@Override
public String[] getText(Object aDomainObject, Object aSubLabelID, TLspContext aContext) {
return new String[]{aSubLabelID.toString()};
}
};
@Override
public void style(Collection<?> aObjects, ALspLabelStyleCollector aStyleCollector, TLspContext aContext) {
// Draw a label on the shape (e.g. polyline) itself
aStyleCollector.objects(aObjects).label("mainLabel").styles(fTextStyle, fMainTextProviderStyle).submit();
for (Object object : aObjects) {
if (object instanceof ILcdPointList) {
// for point lists, draw a label for every point that makes up the point list
ILcdPointList pointList = (ILcdPointList) object;
for (int i = 0; i < pointList.getPointCount(); i++) {
ILcdPoint point = pointList.getPoint(i);
aStyleCollector.object(object).geometry(point).label("pointLabel_" + i).styles(fTextStyle, fPointTextProviderStyle).submit();
}
}
}
}
}
public static void main(String[] aArgs) {
startSample(LabelPointsOfPolylineSample.class, "Display labels on points of a polyline");
}
}