You can change the way military symbols are visualized by implementing your own IFeaturePainterIFeaturePainterIFeaturePainter.
The IFeaturePainterIFeaturePainterIFeaturePainter implementation needs to:
-
create/derive a
MilitarySymbolMilitarySymbolMilitarySymbolandGeometryGeometryGeometrythat represent how and where the military symbol needs to be painted. For features that implement the Military Symbology DataTypeMilitary Symbology DataTypeMilitary Symbology DataType, you can useMilitarySymbol::createMilitarySymbol::createMilitarySymbol::create. See this article if you want to visualize features with a data type other than military symbols. -
Use a
MilitarySymbologyCanvasMilitarySymbologyCanvasMilitarySymbologyCanvasto submit the symbol and geometry as a draw command.
For example, the implementation below paints icon symbols with a surrounding rectangle when they are selected, and also adds an additional label below each symbol.
class MyMilitarySymbolPainter : public IFeaturePainter {
public:
MyMilitarySymbolPainter()
// Regular symbols are painted with a default style, while selected symbols are painted with a surrounding rectangle.
: _defaultStyle(MilitarySymbolStyle::newBuilder().build()), _selectedStyle(_defaultStyle->asBuilder().surroundingRectangleEnabled(true).build()) {
}
void configureMetadata(FeaturePainterMetadata& /*metadata*/) const override {
}
void paint(const Feature& feature, const FeaturePainterContext& context, FeatureCanvas& canvas) const override {
// Retrieve the geometry from the feature
auto geometry = feature.findGeometry();
if (!geometry) {
std::cerr << "Ignoring feature '" << feature.getId() << "'. It has no geometry." << std::endl;
return;
}
// Transform the feature to a military symbol.
auto symbol = MilitarySymbol::create(feature);
// Use a MilitarySymbologyCanvas to submit a draw command for the military symbol.
// The submitted symbol style depends on whether the feature is currently selected or not.
MilitarySymbologyCanvas(context, canvas)
.drawMilitarySymbol()
.symbol(symbol)
.geometry(geometry)
.style(context.isFeatureStateEnabled(FeatureState::selected()) ? _selectedStyle : _defaultStyle)
.submit();
// Paint the symbol code as an additional label, with a fixed offset below the symbol.
RelativePosition labelPosition{0, HorizontalAlignment::Center, VerticalAlignment::Top, 0, _defaultStyle->getIconSize() + 50.0};
canvas.drawText().text(symbol->getCode()).position(labelPosition).anchor(geometry).submit();
}
private:
std::shared_ptr<MilitarySymbolStyle> _defaultStyle;
std::shared_ptr<MilitarySymbolStyle> _selectedStyle;
};
public class MyMilitarySymbolPainter : IFeaturePainter
{
private readonly MilitarySymbolStyle _defaultStyle;
private readonly MilitarySymbolStyle _selectedStyle;
public MyMilitarySymbolPainter()
{
// Regular symbols are painted with a default style, while selected symbols are painted with a surrounding rectangle.
_defaultStyle = MilitarySymbolStyle.NewBuilder().Build();
_selectedStyle = _defaultStyle.AsBuilder().SurroundingRectangleEnabled(true).Build();
}
public void ConfigureMetadata(FeaturePainterMetadata metadata)
{
}
public void Paint(Feature feature, FeaturePainterContext context, FeatureCanvas canvas)
{
// Retrieve the geometry from the feature
var geometry = feature.FindGeometry();
if (geometry == null)
{
Console.Error.WriteLine("Ignoring feature '" + feature.Id + "'. It has no geometry.");
return;
}
// Transform the feature to a military symbol.
var symbol = MilitarySymbol.Create(feature);
// Use a MilitarySymbologyCanvas to submit a draw command for the military symbol.
// The submitted symbol style depends on whether the feature is currently selected or not.
new MilitarySymbologyCanvas(context, canvas)
.DrawMilitarySymbol()
.Symbol(symbol)
.Geometry(geometry)
.Style(context.IsFeatureStateEnabled(FeatureState.Selected) ? _selectedStyle : _defaultStyle)
.Submit();
// Paint the symbol code as an additional label, with a fixed offset below the symbol.
var labelPosition = new RelativePosition(0, HorizontalAlignment.Center, VerticalAlignment.Top, 0, _defaultStyle.IconSize + 50.0);
canvas.DrawText().Text(symbol.Code).Position(labelPosition).Anchor(geometry).Submit();
}
}
public static class MyMilitarySymbolPainter implements IFeaturePainter {
private final MilitarySymbolStyle _defaultStyle;
private final MilitarySymbolStyle _selectedStyle;
public MyMilitarySymbolPainter() {
// Regular symbols are painted with a default style, while selected symbols are painted with a surrounding rectangle.
_defaultStyle = MilitarySymbolStyle.newBuilder().build();
_selectedStyle = _defaultStyle.asBuilder().surroundingRectangleEnabled(true).build();
}
@Override
public void configureMetadata(FeaturePainterMetadata metadata) {
}
@Override
public void paint(Feature feature, FeaturePainterContext context, FeatureCanvas canvas) {
// Retrieve the geometry from the feature
Geometry geometry = feature.findGeometry();
if (geometry == null) {
Log.w("milsym", "Ignoring feature '" + feature.getId() + "'. It has no geometry.");
return;
}
// Transform the feature to a military symbol.
MilitarySymbol symbol = MilitarySymbol.create(feature);
// Use a MilitarySymbologyCanvas to submit a draw command for the military symbol.
// The submitted symbol style depends on whether the feature is currently selected or not.
new MilitarySymbologyCanvas(context, canvas)
.drawMilitarySymbol()
.symbol(symbol)
.geometry(geometry)
.style(context.isFeatureStateEnabled(FeatureState.Selected) ? _selectedStyle : _defaultStyle)
.submit();
// Paint the symbol code as an additional label, with a fixed offset below the symbol.
RelativePosition labelPosition = new RelativePosition(new Angle(0), HorizontalAlignment.Center, VerticalAlignment.Top, 0, _defaultStyle.getIconSize() + 50.0);
canvas.drawText().text(symbol.getCode()).position(labelPosition).anchor(geometry).submit();
}
}