Using PointSymbolizer on a DrawingLayer

Introduction

DotSpatial is an open-source project that contains controls which can be used to manipulate and display geographic information. This article explains how to create a DotSpatial extension by using the online template. If you are not familiar with creating a simple DotSpatial-based extension, please consider the introductory article. The extension we are creating will show a star georeferenced to each point where the user right clicks.

Getting Started

Create a new project using the DotSpatial Plugin Template. You may delete the Readme.txt and modify the name of the MyPlugin1 class (to reflect the functionality provided by the extension). I named mine PointSymbolizerPlugin. It is also reasonable to rename the template SimpleActionItem from “My Button Caption” to “Create Stars On Right-Click”

Creating a MapPointLayer

We’ll use the ButtonClick event to start tracking the mouse so that we can capture coordinates and draw points on the map surface. The MapPointLayer will hold the collection of points and a PointSymbolizer will be responsible for drawing them.

public void ButtonClick(object sender, EventArgs e)
{
    map = App.Map as Map;

    // Enable left click panning and mouse wheel zooming
    map.FunctionMode = FunctionMode.Pan;

    // Handle mouse up event on the map
    map.MouseUp += map_MouseUp;

    // The FeatureSet starts with no data; be sure to set it to the point featuretype
    _markers = new FeatureSet(FeatureType.Point);

    // The MapPointLayer controls the drawing of the marker features
    _markerLayer = new MapPointLayer(_markers);

    // The Symbolizer controls what the points look like
    _markerLayer.Symbolizer = new PointSymbolizer(Color.Blue, Symbology.PointShape.Star, 15);

    // A drawing layer draws on top of data layers, but is still georeferenced.
    map.MapFrame.DrawingLayers.Add(_markerLayer);
}

You will notice that we use a few class level variables (fields). Add them to class by placing this code inside the class and outside of any methods, preferably at the top of the class.

    private Map map;
    private FeatureSet _markers;
    private MapPointLayer _markerLayer;

To keep the code succinct, add these statements beneath the other using statements, which are near the top of the file.

    using System.Drawing;
    using System.Windows.Forms;
    using DotSpatial.Data;
    using DotSpatial.Symbology;
    using DotSpatial.Topology;

References should be added (Project, Add Reference) to System.Windows.Forms and System.Drawing. These assemblies contain code related to MouseUp event and to the Color Blue, respectively.

Adding Features to a FeatureSet

We will use the Mouse up event to intercept right clicks and add features (points) to the feature set and layer we created earlier. These points will be symbolized (drawn) by the PointSymbolizer when the MapFrame is invalidated. This happens when the window is resized or when we programatically invoke the Invalidate() method.

void map_MouseUp(object sender, MouseEventArgs e)
{
    // Intercept only the right click for adding markers
    if (e.Button != MouseButtons.Right) return;

    // Get the geographic location that was clicked
    Coordinate c = map.PixelToProj(e.Location);

    // Add the new coordinate as a "point" to the point featureset
    _markers.AddFeature(new DotSpatial.Topology.Point(c));

    // Drawing will take place from a bitmap buffer, so if data is updated,
    // we need to tell the map to refresh the buffer 
    map.MapFrame.Invalidate();
}

It is important that we convert the mouse location to the proper map coordinate based on the current map projection, by calling PixelToProj() with the mouse coordinates.

Cleaning Up on Deactivate()

Though the template doesn’t include an extension manager that would let us deactivate or activate the extension, let’s consider how we should deal with the case where the extension was uninstalled while running or where it was deactivated by the user.

The Deactivate method already has a call to HeaderControl.RemoveAll(). This means the menu item will be removed. We need to also remove our layer and redraw the map. Add this code to the Deactivate method under the RemoveAll() method call.

if (map != null && map.MapFrame.DrawingLayers.Contains(_markerLayer))
{
    // Remove our drawing layer from the map.
    map.MapFrame.DrawingLayers.Remove(_markerLayer);

    // Request a redraw
    map.MapFrame.Invalidate();
}

Conclusion

Build and run your project. Add a layer (e.g., bgd file) to the map for reference by dragging and dropping the file onto the map control. Click your extension menu item and add a few points to the map. When you zoom in or out using the mouse wheel, any stars will redrawn so that their size remains constant.

image

Points Of Interest

You can drop the DotSpatial.Plugins.ExtensionManager.dll and NuGet.Core in your output Plugins folder if you would like test deactivating your extension. I noticed that the current DemoMap implementation will not add the menu item back in if you reactivate the extension. You’ll have to run the project again.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s