Map decorations are implemented as MapGraphic classes that draw onto the map without the need to access data. Examples are the scale bar or legend where what is drawn is completely dictated by current Map and ViewportModel.
References:
Finding and Using a Map Decorator
All the implementations of MapGraphic are gathered into a single IService; with a IGeoResource representing each implementation.
As such you can look them up using catalog; we have placed the identifier as a static constant - however it is best to use a string as that way you do not need to depend on the specific implementation used.
To use GridMapGraphic we can look up its definition:
<mapGraphic
class="net.refractions.udig.mapgraphic.grid.GridMapGraphic"
icon="icons/obj16/grid_obj.gif"
id="grid"
name="%mapgraphic.grid.name"/>
So we can create the correct ID to look that up:
ID grid_id = new ID( MapGraphicService.SERVICE_ID, "grid" );
Or if you don't want to add the dependency:
IRepository local = CatalogPlugin.getDefault().getLocal();
final ID GRID_ID = new ID( "mapgraphic:, null );
IGeoResource gridResource = local.getById(IGeoResource.class, GRID_ID, new NullProgressMonitor() );
Implementing Map Graphic
The interface for MapGraphic is straight forward:
public interface MapGraphic {
/** extension point id **/
public static final String XPID = "net.refractions.udig.mapgraphic.mapgraphic"; /**
* Draws the graphic. Check the clip area of the {@link ViewportGraphics} object to determine what
* area needs to be refreshed.
*
* @param context The drawing context.
*/
void draw(MapGraphicContext context);
}
As you can see you are responsible for implementing a single draw method; the MapGraphicsContext provides access to the screen, access to the Layer (holding any style settings you require) and the Map and MapViewport.
Here is a simple example from the 1 Coordinate MapGraphic tutorial using screen coordinates:
public void draw( MapGraphicContext context ) {
ViewportGraphics g = context.getGraphics();
g.setColor(Color.RED);
g.setStroke(ViewportGraphics.LINE_SOLID, 2);
IMap map = context.getLayer().getMap();
IBlackboard blackboard = context.getLayer().getMap().getBlackboard();
List<Coordinate> coordinates = (List<Coordinate>) blackboard.get("locations");
if (coordinates == null) {
return; }
for (Coordinate coordinate : coordinates) {
Ellipse2D e = new Ellipse2D.Double(
coordinate.x-4,
coordinate.y-4,
10,10);
g.draw(e);
}
If you are working in real world locations (such as WGS84) you will need to convert those locations to screen coordinates:
public void draw(MapGraphicContext context) {
ViewportGraphics g = context.getGraphics();
g.setColor(Color.RED);
g.setStroke(ViewportGraphics.LINE_SOLID, 2);
IMap map = context.getLayer().getMap();
IBlackboard blackboard = context.getLayer().getMap().getBlackboard();
List<Coordinate> coordinates = (List<Coordinate>) blackboard.get("locations");
if (coordinates == null) {
return; }
try {
MathTransform dataToWorldTransform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, context.getCRS() );
for (Coordinate location : coordinates) {
Coordinate world = JTS.transform(location, null, dataToWorldTransform);
Point pixel = context.worldToPixel(world);
Ellipse2D e = new Ellipse2D.Double(pixel.x - 4, pixel.y - 4, 10, 10);
g.draw(e);
}
}
catch (FactoryException unableToTransform){
context.getLayer().setStatusMessage(unableToTransform.getMessage());
} catch (TransformException outOfBounds) {
context.getLayer().setStatusMessage(outOfBounds.getMessage());
}
}