Creating an application using DotSpatial

Apr 13, 2012 at 9:15 PM

Hi,

I have implemented an AIS parser library. In order to check library's functionality, I thought it would be a nice idea to create an application using it.

The basic idea was to create a map and display AIS receiver data/ships on it. I used DotSpatial libraries, with Brutile layer ([discussion:285933]) in order to create the background map. I in order to display AIS receiver's data on the map, I used a FeatureSet.

This is the code used creating the layers:

            uxMap.BackColor = Color.FromArgb(181, 208, 208);
            uxMap.Layers.Add(BruTileLayer.CreateOsmLayer());

            featureTable = new AISDataSet.Message1DataTable();
            ships = new FeatureSet(FeatureType.Point);
            ships.Projection = uxMap.Layers[0].Projection; // OpenSteetMap projection;
            ships.DataTable = featureTable;

            shipsLayer = new MapPointLayer(ships);
            shipsLayer.Symbolizer = new PointSymbolizer(Color.Blue, DotSpatial.Symbology.PointShape.Ellipse, 10);
            shipsLayer.LegendText = "AIS Features";
            uxMap.MapFrame.DrawingLayers.Add(shipsLayer);

Message1DataTable is a strong-typed datatable I created, in order to use in the FeatureSet - it contains all the nessasery columns to store the data an AIS receiver offers.

The data the map has to display, is constantly changing; the datatable either has new rows added, or existing rows change. A second issue is, the AIS receiver offers ships' coordinates in WGS84, and the application has to tranform the projection in order to match OpenStreetMap projection, so the ships can display correctly on the map.

My question: the following code is used to add/update a feature on the featureset:

	Hashtable rs = aisparser.Parse(textline);
	
	double[] pointCoords = { (double)rs["Longitude"], (double)rs["Latitude"] };
	double[] z = { 0 };
	Reproject.ReprojectPoints(pointCoords, z, KnownCoordinateSystems.Geographic.World.WGS1984, shipsLayer.Projection, 0, 1);

	Coordinate coord = new Coordinate(pointCoords[0], pointCoords[1]);
	IFeature feature;

	List<int> results = ships.Find(string.Format("UserID={0}", rs["UserID"]));
	if (results != null && results.Count > 0)
	{
		feature = ships.GetFeature(results[0]);
		feature.Coordinates[0] = coord;
	}
	else
	{
		DotSpatial.Topology.Point point = new DotSpatial.Topology.Point(coord);
		feature = ships.AddFeature(point);
	}

	foreach (DictionaryEntry item in rs)
	{
		feature.DataRow[item.Key.ToString()] = item.Value;
	}
	uxMap.MapFrame.Invalidate();

Variable ships is the FeatureSet; variable rs holds the data received from the parser.

Is this code optimal? Is there anything better I could do? This code runs every time data is received; this means 1-2 seconds.

The application's code is part of project SharpAIS in codeplex, in case someone wants to check it...

 

Thanks,
George J.

Developer
Apr 13, 2012 at 11:29 PM

If feature often referenced the same feature, you could store that reference so you don't need to search for it each time. I'd almost recommend attaching a profiler so that you could see what is taking the longest if you have performance problems.

Sometimes, using results.Any() will be faster than

results.Count > 0

But, I don't think that you will find a difference for the List<int>
Apr 14, 2012 at 5:47 AM

Thank you for answer. I must say, this is the first time I use DotSpatial's libraries, and it could not be possible without your blog posts.

Back to my question: An AIS receiver generates data deriving from about 500 ships per hour; though, the featureset would have 500 features more or less. Every ship refreshes its position every 3 to 5 seconds. Having a reference for each feature seems difficult, as no one knows which ship will sail in a region at a given time.

Perhaps, I good idea would be to create keys on my dataset, to help make the search faster.

I can see on the DotSpatial.Controls.SpatialToolStrip control, that buttons like "Identifier" and "Attribute Table" are offered. When I use these buttons, I get an empty "Identify" window. What do I have to implement, in order to get a feature's attributes in that window displayed? - I assume these attributes come from a feature's columns in the dataset, filled during a feature's creation/update process.

 

George J.