spacer1
spacer2 1_1 1_2
2_1
 Subscribe
 The MP2K Update!
 
 
 
 Magazine
Front Cover
What's New
Articles
News
Sample Data
Gallery
Advertise
About
 Features
MapPoint 2009
Press Releases
MapPoint Forums
Companies
Link to MP2Kmag
Wish List
MapPoint Trial
Authors
 Earlier Content
Past News Items
Past What's New Announcements
 Sponsors
 Order

MapPoint 2009

Programming MapPoint in .NET

MapPoint Book

  Spatial Community
ViaVirtualEarth
SVG Tutorials
MapPoint

Map Visitors

 Direct Media

Travel Insurance Compare over 450 travel insurance policies (inc. annual multi-trip, single trip & winter sports)

  ARTICLES  


Plotting Earthquake Hazard Data in MapPoint

This two-part article by Richard Marsden shows how to use MapPoint to produce maps of earthquake hazards and to overlay recent earthquakes using data from the USGS. The technique of depicting data using grids can be used in a wide range of environmental and commercial applications.

California earthquakes for the week up to Wed Sep 15 8:22:13 PDT 2004

Recent earthquakes are plotted as solid circles and the color background displays earthquake hazard as calculated by the US Geological Survey (USGS). The hazard data has been plotted using some custom programming, while the recent earthquake data was prepared with Excel and plotted using MapPoint’s Data Import Wizard. We will look at the earthquake hazard data first.

The Earthquake Hazard Data

This was prepared using a custom C++ program, but the code could also be adapted to work in any language that can call MapPoint (e.g. VB6). Alternatively, a third party data import tool such as Grid Imp could be used.

If programming MapPoint in C++ without MFC is new to you, then you should look at the article Calling MapPoint From C++ Without the MFC Safety Net first. I will assume that you have a working project with the required mpinterface.h, etc. files in place.

The earthquake hazard data was calculated by the USGS and is available from http://eqhazmaps.usgs.gov/. Go to the 2003 conterminous gridded data at http://eqhazmaps.usgs.gov/html/data2002.html and download the “PGA 10% PE in 50 years” file ( ftp://ghtftp.cr.usgs.gov/pub/hazmaps/data2003/ascii/USpga500v6.asc ).

This file estimates the peak ground accelerations expected at the 10% probability level in the next fifty years. Peak ground acceleration (PGA) is related to the force applied to a building by an earthquake, so this is a better measure of earthquake hazard than the “Earthquake Index” provided with MapPoint 2004 North America. This is a large file (20MB) but covers the entire conterminous US at a resolution of 0.5 degrees.

Open the file in a text editor. The data consists of three columns, one each for longitude, latitude, and PGA. The first line contains titles for each column. Delete this first line.

To read the file, I created a new C++ class called FileDataReader. The header is as follows:

// FileDataReader.h header file #include using namespace std; class FileDataReader { public: FileDataReader(char* fname); virtual ~FileDataReader(); bool EndOfFile(); void Close(); bool ReadTriplet(double& lng, double& lat, double& z); // Private Members private: ifstream myStream; };

This is a pretty simple class, but is capable of parsing an individual line as well as simple file management (open/close, end of file). The implementation is as follows:

// FileDataReader.cpp: implementation of the FileDataReader class. #include "stdafx.h" #include "FileDataReader.h" FileDataReader::FileDataReader(char* fname) { myStream.open(fname, ofstream::in); } FileDataReader::~FileDataReader() { } bool FileDataReader::EndOfFile() { return myStream.eof(); } void FileDataReader::Close() { myStream.close(); } bool FileDataReader::ReadTriplet(double& lng, double& lat, double& z) { // Simple read of a triplet file. Values separated by whitespace. // Return true if EOF or other error occurs // If the EOF occurs at the very end, then report as Good (false). myStream >> lng; if (!myStream.good()) return true; myStream >> lat; if (!myStream.good()) return true; myStream >> z; return myStream.fail() || myStream.bad(); }

The data is read one line at a time, and plotted if required. Plotting and MapPoint control is managed by a second class called MapPointController. The include file is as follows:

// MapPointController.h: interface for the MapPointController class. #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "FileDataReader.h" // Number of colors in the colormap #define NUM_COLS 11 class MapPointController { public: MapPointController(); virtual ~MapPointController(); void CreateGridSquares( FileDataReader& myReader, const double minLong, const double maxLong, const double minLat, const double maxLat, const double gridSize, const double min_val, const double max_val ); // Auxiliary Methods private: double CalcLongitude( const double lng ) const; // Private member: Colormap to use long colormap[NUM_COLS]; };

The implementation for MapPointController is a little more involved, and is described here in sections. First we have the required includes, and we also tell C++ that we are using the MapPoint namespace.

// MapPointController.cpp: implementation of the MapPointController class. ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "MapPointController.h" #include "mpinterfaces.h" #include "FileDataReader.h" using namespace MapPoint;

Next we have the constructor and destructor for the MapPointController object. The only initialization required is for the colormap array, which stores the required colormap. Each color is stored as a long value with one byte for each of the RGB components. The colormap here contains 11 colors making a rainbow scheme. You may adapt this as required, but remember to update the NUM_COLS definition in MapPointController.h if required. Also note that MapPoint limits the colors to a palette of about 36. These are listed in a bitmap provided with MapPoint and in the Appendix of http://www.mapping-tools.com/gridimp/wxm_formatspec.doc.

////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// MapPointController::MapPointController() { // NUM_COLS = 11 // RED GREEN BLUE colormap[ 0] = 0x80 + 0x00 * 256 + 0x00 * 65536; colormap[ 1] = 0xFF + 0x00 * 256 + 0x00 * 65536; colormap[ 2] = 0xFF + 0x99 * 256 + 0x00 * 65536; colormap[ 3] = 0xFF + 0xCC * 256 + 0x00 * 65536; colormap[ 4] = 0xFF + 0xFF * 256 + 0x00 * 65536; colormap[ 5] = 0x99 + 0xCC * 256 + 0x00 * 65536; colormap[ 6] = 0x00 + 0x80 * 256 + 0x00 * 65536; colormap[ 7] = 0x00 + 0x80 * 256 + 0x80 * 65536; colormap[ 8] = 0x33 + 0x66 * 256 + 0xFF * 65536; colormap[ 9] = 0xFF + 0x00 * 256 + 0xFF * 65536; colormap[10] = 0x80 + 0x00 * 256 + 0x80 * 65536; } MapPointController::~MapPointController() { }

Next we define an auxiliary method to check that the longitude coordinate is within range. MapPoint longitude values must be in the range of –180 to +180. This is necessary if you use a different dataset, for example the file for Alaska crosses the International Date Line.

double MapPointController::CalcLongitude( const double lng ) const { double l(lng); while (l> 180.0) l-=360.0; while (l<-180.0) l+=360.0; return l; }

Next we come to the main controller method that calls MapPoint to create grid squares from the input data. It is called with an opened FileDataReader object to read the data from. The extents of the output grid are also provided as minimum/maximum longitude and latitude values. The grid size is also provided (0.5 degrees for this data file). A range of data values to plot are also provided. This can be used so that areas of minimal hazard are not plotted.

void MapPointController::CreateGridSquares( FileDataReader& myReader, const double minLong, const double maxLong, const double minLat, const double maxLat, const double gridSize, const double min_val, const double max_val )

Next we start MapPoint and initialize our range variables.

{ // Start MapPoint _ApplicationPtr myMapPointPtr; HRESULT hr = myMapPointPtr.CreateInstance("MapPoint.Application.NA"); if (hr != 0) { MessageBox(NULL, "Could not open Microsoft MapPoint!", "demo: CreateGridSquares", MB_SETFOREGROUND); return; } _Application* myMapPoint = (_Application*)myMapPointPtr; ATLASSERT( myMapPoint != NULL ); // Set MapPoint to be visible, and to stay open after this program closes myMapPoint->Visible = true; myMapPoint->UserControl = true; // Get a pointer to the _Map object _MapPtr myMapPtr = myMapPoint->ActiveMap; _Map* myMap = (_Map*)myMapPtr; ATLASSERT( myMap!=NULL ); double halfGridSize = gridSize * 0.5; double minLatR = minLat - halfGridSize; double maxLatR = maxLat + halfGridSize; double minLonR = minLong - halfGridSize; double maxLonR = maxLong + halfGridSize;

Next we start a loop, reading each data point in turn and plotting it if it is within the required longitude, latitude, and z (hazard) values.

// Loop over each data point, reading it in while ( !myReader.EndOfFile() ) { // Read data point double lng,lat,z; if ( myReader.ReadTriplet( lng,lat, z) ) break; // Is it in the output range? if ( lng > minLonR && lng < maxLonR && lat > minLatR && lat < maxLatR ) if ( z>min_val && z

At this point in the program , we have found a data point which meets the requirements so we will plot it. The data point is plotted as a grid square centered on the point location. The grid square is created by creating a closed solid polyline, described using a VARIANT array of Location objects. The z (hazard) value is used to find the required color from the colormap. The finished polygon has a solid fill but no edge line and is positioned behind the roads.

// Draw square VARIANT vcoords; VariantInit( &vcoords ); V_VT(&vcoords) = VT_DISPATCH + VT_ARRAY; SAFEARRAYBOUND saBound[ 1 ] ; saBound[ 0 ].cElements = 5 ; saBound[ 0 ].lLbound = 0 ; SAFEARRAY FAR* coords = SafeArrayCreate( VT_DISPATCH, 1, saBound ) ; V_ARRAY(&vcoords) = coords; long idx[ 1 ] ; LocationPtr locPtr1 = myMap->GetLocation( lat-halfGridSize, CalcLongitude(lng-halfGridSize), 100.0 ); Location* myLoc1 = (Location*)locPtr1; ATLASSERT(myLoc1!=NULL); idx[ 0 ] = 0; HRESULT hr = SafeArrayPutElement( coords , idx , locPtr1) ; ATLASSERT(hr==0); LocationPtr locPtr2 = myMap->GetLocation( lat+halfGridSize, CalcLongitude(lng-halfGridSize), 100.0 ); Location* myLoc2 = (Location*)locPtr2; ATLASSERT(myLoc2!=NULL); idx[ 0 ] = 1; hr = SafeArrayPutElement( coords , idx , locPtr2) ; ATLASSERT(hr==0); LocationPtr locPtr3 = myMap->GetLocation( lat+halfGridSize, CalcLongitude(lng+halfGridSize), 100.0 ); Location* myLoc3 = (Location*)locPtr3; ATLASSERT(myLoc3!=NULL); idx[ 0 ] = 2; hr = SafeArrayPutElement( coords , idx , locPtr3) ; ATLASSERT(hr==0); LocationPtr locPtr4 = myMap->GetLocation( lat-halfGridSize, CalcLongitude(lng+halfGridSize), 100.0 ); Location* myLoc4 = (Location*)locPtr4; ATLASSERT(myLoc4!=NULL); idx[ 0 ] = 3; hr = SafeArrayPutElement( coords , idx , locPtr4) ; ATLASSERT(hr==0); idx[ 0 ] = 4; hr = SafeArrayPutElement( coords , idx , locPtr1) ; ATLASSERT(hr==0); ShapePtr myShapePtr = myMap->Shapes->AddPolyline( vcoords ); Shape* myShape = (Shape*)myShapePtr; long color = colormap[ (int)( (z-min_val+1.0)*NUM_COLS / (max_val-min_val) ) ]; myShape->Fill->Visible = true; myShape->Fill->ForeColor = color; myShape->Line->Visible = false; myShape->ZOrder(geoSendBehindRoads); // Tidy this shape up myShapePtr.Release(); locPtr1.Release(); locPtr2.Release(); locPtr3.Release(); locPtr4.Release(); } // Loop around to the next line of data }

The data has been read in and plotted, now close the file and release the remaining MapPoint pointers.

// Close the input file, release the COM objects and finish myReader.Close(); myMapPtr.Release(); myMapPointPtr.Release(); }

That is it for the MapPointController class. For my sample program, I used a simple dialog box, and wired the OK button to perform the drawing. The implementation for the drawing was as follows:

// Create a FileDataReader object using the earthquake file // Change the path to point to the location of the file on your computer FileDataReader myInput("C:\\Projects\\maps\\eq\\demo\\Debug\\USpga500v6.asc"); // If the file was opened successfully, create the grid squares if (!myInput.EndOfFile()) { MapPointController myController; // Plot areas of California & Nevada with PGA > 20.0 myController.CreateGridSquares( myInput, -124.50, -114.01, 32.55, 42.01, 0.05, 20.0, 140.0 ); // Here are some other example areas that work for the same dataset // myController.CreateGridSquares( myInput, -123.30,-120.86, 36.70,38.56, 0.05, 140.0 ); // SF Bay Area // myController.CreateGridSquares( myInput, -94.45,-85.64, 33.0,41.86, 0.05, 20.0, 140.0 ); // New Madrid Fault Zone } // Close the input file myInput.Close();

When you build this and run it, you will find that it is quite slow due to the large amount of data being read and processed. A number of optimizations can be applied, but the above code has been kept simple to show the basic concept. The Grid Imp product by from Mapping-Tools.com uses the same concept but runs much faster due to optimizations. It is also much more flexible, being capable of reading a variety of file types, as well as supporting different grid spacings and data holes. The final map should like this:

Next month MP2K Magazine will be featuring the second part of this part which will show how to display recent earthquakes, also using publicly available, free information from the USGS.

Discuss this story in the forum.

Author: Richard Marsden
Email: enquiries(AT)winwaed.com
URL: http://www.winwaed.com
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 Mapping-Tools.com 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.



Google
 
MP2Kmag Internet


 Recent Discussion
-bingmaps: Join the UK #BingMaps team for the finance and insurance sector webcast tomorrow http://bit.ly/chMYcb
-Bing Maps at MIX10!
-Bing Maps at MIX10!
-bingmaps: Want live Twitter and Maps on your website, use the new widget from Bing Maps: http://bit.ly/9KkFSa
-linked files
-Criteria for extracting postcodes in Mappoint Euro Ver
-Spatial Data Import COM Add-in / Shapes (SHP file)
-BingMapsDev: @jont87 For Silverlight I would start here: http://is.gd/a4BAq and then look at the Bing Maps iSDK: http://is.gd/a4C4y
-bingmaps: Channel 5's Gadget Show are impressed by #BingMaps Birds Eye (forward to 24 mins) http://bit.ly/9Cn6sY
-bingmaps: #BingMaps SXSW Panel Announced http://bit.ly/9GWSeT
-bingmaps: Bing Maps retail and supply chain webcast starts in 10 minutes. Register here: http://bit.ly/dsNNJD
-Bing Maps SXSW Panel Announced
-Check if Mappoint exists on the PC
-bingmaps: @markti Great glad you like it!
-bingmaps: RT @ChrisPendleton: Bing Maps adds 6.7 MILLION sq. km. of new imagery: http://bit.ly/bCcyCw. @BingMaps #Russia #Sweden #Mexico #Australia
-bingmaps: #BingMaps UK team present Mapping Technology for the Communications sector http://cot.ag/979oFy
-bingmaps: Johannes Kebeck blogs on Daimler AG and the Smart Web Portal in the Cloud http://bit.ly/a8uvsR #BingMaps
-BingMapsDev: Have you joined the Bing Maps UK user group yet? http://bingmapsuk.ning.com/
-WiMax Clear Service in Chicago
-Registry Error Installing 2006 Version in Windows 7 Professional
-MapPoint Geocoding Project
-Water Feature toggle
-objGPS.Tracking = True give access denied
-Smart Web Portal in the Cloud
-The latest Bing Maps Imagery Update…
 Resources
Browse GIS books and periodicals
Best Car Contract Hire Lease Save
Find a MapPoint Partner or Consultant
Real Estate Columbia, MO


Want Your Site To Appear Here?

   © 1999-2009 MP2K. Questions and comments to: website@mp2kmag.com
  Microsoft and MapPoint 2002/2004/2006/2009 are either trademarks or registered trademarks of Microsoft.

• Replacement Cordless Phone Batteries from DSMiller
Improve your career with a computer degree LocalEDU.com
• Tim Cohn's Marketing Strategy Consultancy
• Buy Toner Cartridges at Marquee Office Solutions
• Looking for Dry Erase Boards? See Dry Erase Boards • The Search Starts Here Used Cars
• 5339 - We Know Bikes: Road Bikes / Triathlon Bikes / Mountain Bikes / BMX Bikes
• Buy Your Car Used Cars UK, Car Lease and Contract Hire