How to write an OpenMap Layer: Part 1

 

Introduction

From the OpenMap website [openmap.org]:

BBN Technologies' OpenMap™ package is an Open Source JavaBeans™ based programmer's toolkit. Using OpenMap, you can quickly build applications and applets that access data from legacy databases and applications. OpenMap provides the means to allow users to see and manipulate geospatial information.

This tutorial is about how to extend OpenMap through the development of a layer. Layers are the main visualization components of OpenMap and can be thought of as layers of a cake. Each layer is drawn in the order that it is stacked thus creating the composite image that the user sees.

 

The Code

When you want to create a layer there are many ways to start off, however, the easiest is to extend the AbstractPlugIn class. This creates a PlugIn that is wrapped in a PlugInLayer object that allows the developer to focus one implementing only one method (with the hopes that this one method will be implemented well).

AbstractPlugIn.java
package com.bbn.openmap.plugin; ... public abstract class AbstractPlugIn implements PlugIn, PropertyConsumer, MapMouseListener { ... /** * The getRectangle call is the main call into the PlugIn module. * The module is expected to fill a graphics list with objects * that are within the screen parameters passed. It's assumed that * the PlugIn will call generate(projection) on the OMGraphics * returned! If you don't call generate on the OMGraphics, they * will not be displayed on the map. * * @param p projection of the screen, holding scale, center * coords, height, width. May be null if the parent * component hasn't been given a projection. */ public abstract OMGraphicList getRectangle(Projection p); ... }

This method is relatively simple to implement. The Projection object contains everything you'll need to determine if something is shown or not. Some of the more commonly used properties it contains are the current scale, the size of the canvas (in pixels) and upper-left and lower-right locations (lat/lon). Using this information you should be able to determine what graphics to display and where to display them. The result is an OMGraphicList which is simply a specialized java.util.List for holding OMGraphic objects. So taking a look at the inputs and outputs we can generalize the method as something that takes in a canvas with some locational data and returns a list of objects that describe what to draw on this canvas.

The following code demonstrates a simple AbstractPlugIn implementation. This class draws a black circle directly in the center of the canvas, regardless of the projection type, size and scale of the projection.

CenteredDotPlugIn.java
package net.hazelnutcafe.openmap.plugins; import com.bbn.openmap.omGraphics.OMGraphicList; import com.bbn.openmap.omGraphics.OMCircle; import com.bbn.openmap.plugin.AbstractPlugIn; import com.bbn.openmap.proj.Projection; public class CenteredDotPlugIn extends AbstractPlugIn { public OMGraphicList getRectangle(Projection p) { // Create a new OMGraphicList with room allocated for 1 OMGraphic OMGraphicList result = new OMGraphicList(1); int x = p.getWidth() / 2; int y = p.getHeight() / 2; int height = 50; int width = 50; // Create a new OMGraphic designating an x/y position on the canvas with OMCircle graphic = new OMCircle(x, y, width, height); graphic.setFillPaint(java.awt.Color.BLACK); // Add the OMGraphic to the resultant array and regenerate the shapes to draw result.add(graphic); result.regenerate(p); // Send back the generated OMGraphicList return result; } }
 

What It Looks Like

When this layer is added to an OpenMap properties file it will render the following image.

 

The Configuration

Of course, this layer doesn't magically appear. It needs to be referenced in an OpenMap properties file. This is a simple file that contains name/value key pairs in the form of key = value. The following is an excerpt that will create a layer of type CenteredDotPlugIn. Also, this layer needs to be referenced in the openmap.layers propertie and if you want it to be displayed on startup the openmap.startUpLayers propertie.

openmap.properties
... ### End Component Properties ### ### OpenMap Layers ### openmap.layers = centeredDot graticule shapePolitical openmap.startUpLayers = centeredDot graticule shapePolitical ### -centeredDot- layer properties centeredDot.class = net.hazelnutcafe.openmap.plugins.CenteredDotPlugIn centeredDot.prettyName = Centered Dot ### -graticule- layer properties ...
 

Conclusion

Just a couple of notes here. First, these tutorials use plugin and layer interchangeably because they are used almost interchangeably within the OpenMap framework. In fact, the preferred way of developing a layer is to develop a plugin. In the properties file the plugin class was directly used for the layer class property and while correct is a form of shorthand. The more correct solution sets the plugin layer wrapper as the layer's class property and specified the plugin class as a plugin property. Confused? Just see the following modified properties snippet.

openmap.properties
... ### End Component Properties ### ### OpenMap Layers ### openmap.layers = centeredDot graticule shapePolitical openmap.startUpLayers = centeredDot graticule shapePolitical ### -centeredDot- layer properties centeredDot.class = com.bbn.openmap.plugin.PlugInLayer centeredDot.plugin = net.hazelnutcafe.openmap.plugins.CenteredDotPlugIn centeredDot.prettyName = Centered Dot ### -graticule- layer properties ...

Stay tuned for the next tutorial where the first half of property serialization (ingest) will be discussed.