spacer2 1_1 1_2
 The MP2K Update!
Front Cover
What's New
Sample Data
MapPoint 2013
Press Releases
MapPoint Forums
Link to MP2Kmag
Wish List
MapPoint Trial
 Earlier Content
Past News Items
Past What's New Announcements

MapPoint 2013

Programming MapPoint in .NET

MapPoint Book

  Spatial Community
SVG Tutorials

Map Visitors


Functional Programming with MapPoint and F#: Part 2

In this, the second of a two-part article on functional programming with MapPoint, Richard Marsden uses F# in a practical example classifying data points as wetlands based on hydrology, vegetation, and soil measurements.

In the first part of this article, I introduced F# and demonstrated how it can be used to call MapPoint using both early and late binding. Here I present a more practical example that classifies pushpins according to their data fields. Functional languages are defined in terms of functions, and it seemed that a classification application with non-trivial logic would be a good way of doing this. In fact some functional languages such as Prolog are designed for this kind of logic-based classification.

The specific application uses wetland data produced by ecology students of the University of Dallas (see for a Virtual Earth / PHP implementation). The underlying database consists of many data points with field measurements. This data has been imported into MapPoint using the Data Import Wizard. The application will determine if each pushpin represents a wetland based on the field measurements (stored as pushpin data fields), and change the pushpin symbol accordingly. Note that some data might be incomplete, but this is marked in the database using flags.

The determination is based on the hydrology, vegetation, and soil. The data point is a wetland if two or more of these indicate a wetland. Eg. The presence of standing water does not necessarily make it a wetland - it might be a temporary flood.

The Code

This example uses early binding. This allows us to take advantage of F# type checking and Visual Studio’s Intellisense. It is also simpler to code. It is assumed that you have created the MapPoint COM Interop as per the first part of this article. First we add references to the MapPoint COM Interop and to the .NET namespaces that we require:

Next we define a record type called DataRecord. Due to the way the data fields are stored in MapPoint, we have to look over them all, extracting the values. By putting them in a record, we can then access them in an arbitrary manner as/when we want them. All of the data fields are boolean flags (typically marking the presence of a characteristic) or integers (typically soil percentages or soil color measurements). The flags havehydro, haveveg, and havesoil all mark if the data has been collected for these respective groups of measurements. Here is the record definition:

Next we create a function called extract_fields which takes a MapPoint Recordset that is positioned at a pushpin, and creates a DataRecord from it:

This is actually a two stage process. The function loops over the fields in the Recordset. These are then inserted into a .NET Dictionary object. This stores the values for the data fields in an easy to access manner. However, all the data values have to use the same type. Also, a native F# record is much better suited to F#’s pattern matching and processing. Therefore we convert the completed dictionary into the DataRecord object which is returned. This is probably more complicated than it needs to be, but it does demonstrate the way F# can easily use the standard .NET libraries. Note that we are assume all the data types are correct and that missing fields will be interpreted as 0 or false. This would handled better in a production system. This is simply an example that hard-coded to a particular dataset.

Next we define a function to determine if we have sufficient information to say whether a data point is a wetland or not. Our final classifications are: wetland, not a wetland, and “not enough information”. Here is the function:

This function takes a DataRecord record and matches three fields. It returns true (we have sufficient information) if two (or more) of these three fields are true. Ie. If two of vegetation, hydrology, and soil have field measurements. match is a very powerful statement in F# and we will use it a few times. The ‘_’ character indicates a wildcard.

Next we define three similar functions. These determine if vegetation, hydrology, and soil indicate a wetland:

Note that we continue to use match, although conventional logic is used for wetland_veg. In the two match statements above, we also have a logic clause (a series of || or clauses) in the match parameters.

The above three functions can now be combined, to determine if a data point is a wetland:

At least two of the determinations have to be true, for the point to be a wetland. Note that this function will return a possible false negtive if there’s insufficient data. This is handled separately.

First we must define one more function. This chooses a symbol index according to whether there’s sufficient information for a determination, and whether the it is determined to be a wetland or not:

That is the last function. Now we can start on the global code. First, start MapPoint, load the map file, and create a Recordset for the first dataset:

Again, we are assuming that the first dataset is the one that is required - you would not do this in a production environment. Now we (finally) come to the ‘guts’. Here we loop over each pushpin, extract the fields, determine if we have enough information and whether it is a wetland, and choose a symbol accordingly:

And that is the end of the code! We deliberately leave MapPoint open at the end for viewing and/or saving by the user. Here is the resulting map after the pushpins have been classified:

Notice how the whole process has been broken down into small functions. Although we have mixed imperative and functional programming, virtually all of the program consists of many small functional components. The only except to our functional ideal is the large extract_fields() function.

Although it has not been used here, functional programming could be used to pass custom determination functions. The user/programmer could then call the classifier by simply passing the name of the map file and a function to do the classifying.

Discuss this story in the forum.

Author: Richard Marsden
Email: enquiries(AT)
Richard Marsden is the proprietor of Winwaed Software Technology, LLC which provides software consulting and development services, specializing in both MapPoint and online mapping applications. He operates the Website for MapPoint Tools and Utilities, and recently launched the GeoWeb Guru a community website for developers of the geospatial web. In 2008, Richard was awarded Virtual Earth MVP status by Microsoft.

Prior to Winwaed, Richard worked as a software developer working on seismic processing algorithms for the oil exploration industry. He holds geology and geophysics degrees from the University of Cambridge (Churchill College), and the University of Durham; and an interdisciplinary MBA from the University of Dallas.

MP2Kmag Internet

 Recent Discussion
Browse GIS books and periodicals
Find a MapPoint Partner or Consultant
Real Estate Columbia, MO Real Estate

Want Your Site To Appear Here?

   © 1999-2012 MP2K. Questions and comments to:
  Microsoft and MapPoint 2002/2004/2006/2009/2010/2011/2013 are either trademarks or registered trademarks of Microsoft.