Top Banner
- 1 - DRAFT Getting Started With the MapWinGIS ActiveX Control By Daniel P. Ames, PhD, PE
43

Using Map WinGIS

Apr 13, 2015

Download

Documents

MAPWINGIS
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Using Map WinGIS

- 1 - DRAFT

Getting Started With the MapWinGIS ActiveX Control

By Daniel P. Ames, PhD, PE

Page 2: Using Map WinGIS

- 2 - DRAFT

Copyright 2006 Daniel P. Ames All Rights Reserved. Printed in the United States of America The names of companies and products herein are trademarks or registered trademarks of their respective trademark owners. Revision 0.1

Page 3: Using Map WinGIS

- 3 - DRAFT

To Mrs. Brassey

Page 4: Using Map WinGIS

- 4 - DRAFT

Contents

PREFACE................................................................................................................5 ACKNOWLEDGMENTS.......................................................................................7 1 GIS SOFTWARE DEVELOPMENT PARADIGMS........................................8 2 GETTING STARTED WITH MAPWINGIS..................................................12

GETTING THE LATEST VERSION OF MAPWINGIS................................................12 REGISTERING THE MAPWINGIS ACTIVEX ON YOUR SYSTEM ............................14 CREATING A REFERENCE TO MAPWINGIS IN VISUAL BASIC 2005 EXPRESS EDITION...............................................................................................................16 ADDING A MAP COMPONENT TO YOUR VISUAL BASIC FORM..............................18 ADDING A SHAPEFILE DATA LAYER TO YOUR MAP............................................19 CREATING ZOOM AND PAN BUTTONS .................................................................22

3 SHAPEFILE DISPLAY, COLORING SCHEMES, AND LABELS ............25 ADJUSTING SHAPEFILE DISPLAY PROPERTIES .....................................................25 SETTING A COLORING SCHEME ...........................................................................31 USING A POINT IMAGE LIST ................................................................................34 LABELING FEATURES ..........................................................................................37

Page 5: Using Map WinGIS

- 5 - DRAFT

Preface In 1998 I discovered the magical world of object oriented programming and component architecture software. This was a wonderful discovery for a guy who began programming with the BASIC language (TRS-80 Model 1) at age 12 and later was formally trained in the FORTRAN language while at college. As many have done before me, I immediately recognized the value of reusing code and objects and began developing simple ActiveX components in Visual Basic 5.0 (some of which are still available for download from my legacy web-site, http://www.StonehavenSoftware.com.)

At about the same time, I began work on a fascinating and challenging doctoral research project that had a large GIS software development aspect. My fellow students and I originally began to write the needed code using the ESRI® MapObjects® product. While this product was robust and effective for most of our needs, it had a few functional deficiencies for our particular project and, perhaps more significantly, it had an associated license that would make our product cost-prohibitive to redistribute.

The world of free and open source GIS was still in its infancy at that time, and there were no free or open source GIS mapping components

Page 6: Using Map WinGIS

- 6 - DRAFT

available specifically for use in rapid application development environments such as Visual Basic. As a result, our research group began developing our own mapping components. The first version of the MapWindow MapWinGIS ActiveX control was released in 2002 and was made available to users of our products free of charge. In early 2004, the Idaho National Laboratory, a major federal funding source for our research, released much of the MapWindow project source code to the public domain.

In August 2004, I took a position at Idaho State University and brought the public domain source code with me for continued development and use. At that time, I was encouraged by colleagues at AQUA TERRA Consultants (http://www.aquaterra.com) to release MapWinGIS and its associated graphical user interface, MapWindow GIS, as open source software. In January 2005 a new web site, MapWindow.org, was created as a repository, information site, and distribution mechanism for all of the source code to the MapWindow GIS application and its underlying components (including the MapWinGIS ActiveX control).

With the help of some directed advertising using Google AdWords, the MapWindow GIS project quickly began to gain a large user community of people who had a similar need for a fast, efficient, and free GIS mapping component. As of this writing downloads from the MapWindow.org web site average about 2500 per month and are steadily increasing.

Two major resources for understanding the MapWinGIS ActiveX control are available on the MapWindow.org web site. These include 1) an active discussion forum where users post questions and answers on a variety of ongoing topics; and 2) a live WIKI site that includes documentation and sample code for most of the functions and objects in the MapWinGIS Active control. This book is not intended to replace either of these resources, but rather is meant to serve as a formal step-by-step introduction to using the component, suitable for use as part of a semester long course on GIS software development.

Page 7: Using Map WinGIS

- 7 - DRAFT

Acknowledgments

Thanks to Chris Michaelis, Lailin (Forest) Chen, Allen Anselmo, Ted Dunsford, Jey Veluppillai, and all others who have contributed time and talent to the MapWinGIS project..

Page 8: Using Map WinGIS

- 8 - DRAFT

1 GIS Software Development Paradigms

The multibillion dollar geographic information systems (GIS) industry has largely been built upon a relatively small collection of very successful commercial GIS software products. In recent years, the commercial GIS software industry has been supplemented by a thriving free and open source GIS developer community. From the perspective of GIS tool software development these products generally fall in one of three categories that correspond to three unique GIS software development paradigms. These paradigms are: 1) development of plug-ins and extensions which add additional functionality to existing desktop GIS systems; 2) development of web-based mapping and data visualization tools; and 3) development of custom standalone applications using GIS programming components.

Perhaps the most successful company in all three categories is Environmental Systems Research Institute (ESRI) of Redlands, California. The ESRI flagship desktop GIS product, ArcGIS, is known worldwide for its data analysis capabilities. ArcGIS is used as a teaching and research platform in most major university geography programs, and the software is found in government agencies and large engineering and environmental consulting firms throughout the world. While ArcGIS is primarily a

Page 9: Using Map WinGIS

- 9 - DRAFT

desktop data analysis package, it also is extensible through the development of extensions, scripts, and tools that can be written in several different languages. This extensibility has made ArcGIS a popular platform for distributing analytical tools, models, and other custom functionality to third-party end users.

In some cases, an individual or company may find that redistributing custom tools developed in a commercial software application is not particularly desirable. The high cost of commercial GIS software platforms may create a problem, especially when the custom tool is intended for use by individuals and entities who may not have the financial resources necessary to adopt expensive commercial software.

Take, for example, a small engineering company that has produced a software tool for tracking merchant shipping vessels in the Pacific Ocean—having based the tool on a commercial software package. If the company wants to sell their ship tracking tool to a third party, they must ensure that the purchaser already has a copy of the commercial GIS platform. In such a scenario, it is possible that the ship tracking software tool would be sold for much less than the cost of the GIS platform. This being the case, does it make sense to require the end users to pay the additional overhead for the commercial GIS package?

Another challenge that can arise is related to the level expertise required to operate large complex commercial GIS software products. Indeed, it is very probable that many of the readers of this book have taken semester long courses dedicated to learning all of the functionality of particular desktop GIS packages. Certainly a high degree of functionality is not a negative thing when one is a trained professional GIS analyst. However, what about the individual who has not taken formal GIS training courses? Such people can be considered “GIS consumers” rather than “GIS analysts.” Does it make sense to provide the typical GIS consumer with all of the functionality of a fully loaded commercial GIS desktop application when that user may only need access to a small subset of the available functionality?

Considering the ship tracking application again, it is likely that the end users of this product will be trained in management, business, and possibly even ship piloting, but probably not formal GIS analysis. This being the case, presenting those users with all of the functionality, and required

Page 10: Using Map WinGIS

- 10 - DRAFT

training and learning curve associated with commercial desktop GIS applications may be unnecessary extra burden.

In spite of the noted downfalls, the “extension” or “plug-in” GIS software development paradigm does meet the need of many projects—in particular the development of tools that are targeted at other GIS analysts. For example, a new spatial interpolation method that is likely to be used only by trained GIS analysts, is a good candidate tool to be built as a plug-in or extension to an existing GIS software package.

Many software development and location based service provider companies have addressed this problem of needing to keep their map based applications simple by moving them to the Internet. Indeed, map-enabled web sites such as MapQuest (http://www.mapquest.com) and Google Maps (http://maps.google.com) have rapidly grown in popularity in recent years. Such sites provide general location information, driving directions and even satellite imagery when available. Also a variety of government agencies at all levels have also begun to distribute geospatial data on web-based maps. Such applications can be used to provide citizens with information as varied as census data, severe weather warnings, election results, and much more.

Coincident with the current proliferation of map-based web sites, has come a proliferation of web-based GIS tools. ESRI produces the internet map server, ArcIMS, AutoDesk, Inc distributes a tool called MapGuide, and the University of Minnesota has led the open source movement in web-based GIS with its MapServer product. All of these tools follow a common development approach based largely on display of and relatively minimal interaction with static images generated by server based mapping engines. Many applications are suited to this software development paradigm. Certainly the best fitting GIS applications are those that require only minimal map interaction, and are focused primarily on the dissemination of data to a wide audience.

The third GIS software development paradigm noted above—development of custom standalone applications using GIS components—is the primary focus of this book. The governing premise of this paradigm is the need to place highly customized GIS enabled software tools on the desktop computers of end users. Many types of applications are well suited to this approach such as those that require significant user interaction and/or mobility and hence are less suited to development as web-based tools.

Page 11: Using Map WinGIS

- 11 - DRAFT

Also, when the intention is the development of a highly customized GIS application with a unique or branded “look and feel”, then the standalone development approach is generally better than the plug-in or extension approach.

The ship tracking example application mentioned previously could be considered as a good candidate for the standalone software development paradigm. Imagine a graphical user interface for the software that requires a single form with three separate maps, five buttons and six menu items. Ignoring for the moment exactly what the buttons and menu items will do and what will be displayed on the maps, it should be apparent that such a simple form does not necessarily require all of the overhead of a full GIS desktop application, and hence the standalone approach is more suitable than the plug-in or extension approach. Likewise, by simply adding the need for deployment of the software on ships that do not have live internet access, the standalone approach becomes clearly much more suitable than the web-based mapping paradigm.

In summary, this is an exciting time to be a GIS software developer due to the many available developer tools, and interesting projects with different requirements and needs. While no particular GIS software development paradigm will fit every project and every need, the standalone approach is well suited to a variety of applications and is the focus of this book. The remaining chapters are divided into two sections. The first section provides an introduction to programming standalone GIS software using the MapWinGIS ActiveX control. This section can be used as part of a course on custom GIS software development. The second section is a listing of the objects, functions, properties, and methods that are part of the MapWinGIS ActiveX control. This section is intended to be used as a reference guide to the component.

All code examples and screenshots in this book are based on Microsoft Visual Basic .NET 2005 Express Edition.

Page 12: Using Map WinGIS

- 12 - DRAFT

2 Getting Started with MapWinGIS

The purpose of this chapter is to quickly get you up and running with your first MapWinGIS ActiveX control based application. You will learn how to download and install the latest version of the MapWinGIS ActiveX control; how to add a reference to the MapWinGIS ActiveX control within Microsoft Visual Basic 2005 Express Edition; how to add a map component to a form; how to add a shapefile layer to your map; and how to perform basic zooming and panning functions on the map. Let’s get started!

Getting the Latest Version of MapWinGIS As an active open source development effort, the MapWindow GIS project and its MapWinGIS ActiveX control are regularly updated an improved. Because of this, you should always consider acquiring the latest version of the component before beginning any new development project. There are five ways you can get a copy of the MapWinGIS ActiveX control:

Page 13: Using Map WinGIS

- 13 - DRAFT

1) The CD included with this book contains a simple installer for the MapWinGIS ActiveX component. You can find the installer by inserting the CD into your hard drive and following the link on the auto start index page that should automatically load. This will be the latest version of the component at the time of preparing this book. If you want to ensure that the examples you see in this book are identical to the version of the component that you are using, then you should use the version that came on the CD with this book.

2) Alternatively, you can download the same installer directly from the

MapWindow GIS project home page: http://www.MapWindow.org/. Follow the download link and select the “MapWinGIS ActiveX Control” installer option.

3) The MapWinGIS component is also included in the installation

package for the MapWindow GIS desktop application as it is used heavily by that product. The latest installer for the MapWindow GIS desktop application can be found on the MapWindow project web site, and a version of that installer is also included on the CD with this book.

4) Another option is to download the current pre-release build of the

MapWinGIS ActiveX control directly from the MapWindow GIS project web site. If you take this approach, you will be on the bleeding edge, using a version of the component that has not been released for public consumption, but has any and all of the very latest features and bug fixes (and maybe new bugs!). The code repository where this version resides can be browsed at http://svn.mapwindow.org/svnroot/MapWindow4Dev/Bin/. You are looking for the file called “MapWinGIS.ocx” in this folder (or equivalent folder with later version number).

5) Finally, if you are skilled with C++, you can download the current

source code to the MapWinGIS ActiveX control directly from the Subversion code repository on the MapWindow GIS project web site. Instructions for doing this are given at

Page 14: Using Map WinGIS

- 14 - DRAFT

http://www.MapWindow.org/svn.php. Downloading the source code and recompiling the component are topics beyond the scope of this book, but you are welcome to take this approach if it fits your needs. If you are comfortable working with the C++ source code to the component, then you might want to consider joining the MapWindow GIS team http://www.MapWindow.org/team.php and contributing your own enhancements, improvements, and other great ideas to the project!

Registering the MapWinGIS ActiveX on Your System As an ActiveX control, MapWinGIS can be used within many different programming languages and environments. MapWinGIS users have built successful applications using most of the Microsoft development environments including Visual Basic 6.0, Visual Basic .NET 2003, Visual Basic 2005, C# .NET 2003, C# .NET 2005 and Visual C++. The component has also been used in Microsoft Access, Excel, and PowerPoint using the VBA programming language. Others have used the component in Borland Delphi. Essentially any software development environment that supports the ActiveX protocol can be used with MapWinGIS. I even know one person who uses MapWinGIS on forms developed within ESRI’s ArcGIS VBA programming environment!

In this chapter and the remainder of this book, Microsoft Visual Basic .NET 2005 Express Edition will be used for all examples. Some code samples for the other programming languages can be found on the MapWindow project web site. Especially useful are the ongoing discussions on the MapWindow forum (http://www.MapWindow.org/phorum) and the documentation on the MapWindow WIKI page (http://www.MapWindow.org/wiki). The WIKI includes a number of Visual Basic 6.0 sample code snippets that can be useful for VB 6.0 programmers and VBA programmers.

Once you have installed the MapWinGIS ActiveX control on your development computer, the most important step is to register the component with the system registry. This is a “feature” of Microsoft’s COM/ActiveX

Page 15: Using Map WinGIS

- 15 - DRAFT

paradigm which can be a source of frustration (if you have not registered your components) or a means of easing your programming effort (by allowing you to use one actual file (in this case, MapWinGIS.ocx) in several different software applications.)

If you use any of the MapWindow GIS installers (either for the full desktop application or for the MapWinGIS ActiveX component itself) then the installer will register the component on your system for you. However, if you have simply copied or downloaded the MapWinGIS.ocx file from another location, then you will need to register the file manually on your system. The easiest way to do this is to open your “Run” window from the “Start” menu. Within the “Run” menu dialog enter the following command and press “OK”. regsvr32.exe "C:\Program Files\MapWindow\MapWinGIS.ocx"

This will invoke the Windows Registry Server tool in your System32

folder to register the component with the registry. Successful registration of the component will return the following confirmation:

If the registry server fails to register MapWinGIS on your system then you are likely missing a required dependency file. MapWinGIS has a limited list of required dependencies which are required for the component to work. All of the dependencies are Microsoft runtime libraries and most will likely already be on your computer—especially if you have already installed one of the Microsoft development tools. For more information on the MapWinGIS dependencies, refer to Chapter 12 – Deploying My Application.

Page 16: Using Map WinGIS

- 16 - DRAFT

Creating a Reference to MapWinGIS in Visual Basic 2005 Express Edition The first step to using MapWinGIS in your application is to create a reference to the MapWinGIS ActiveX component in your integrated development environment. Here are the steps in Microsoft Visual Basic 2005 Express Edition:

1) Start a new Visual Basic 2005 project. In the example that follows, we will be using the “Windows Application” project template and will be creating a new project called, “MyFirstMapApp.”

Page 17: Using Map WinGIS

- 17 - DRAFT

2) Next you need to add the MapWinGIS ActiveX control to your Visual Basic 2005 toolbox. To do this, right click in the toolbox area and select the menu item, “Choose Items…” to display the “Choose Toolbox Items” dialog box. MapWinGIS is a COM object so you need to click the “COM Components” tab. Note that this can take a few minutes to load depending on the number of COM objects on your computer. When the list of COM objects loads, scroll down the list to the “Map Control” component. Note that ESRI® also has a component called “Map Control” that may also appear in your list of components. Make sure you select the MapWinGIS component.

The MapWinGIS ActiveX control will appear in your Visual Basic 2005 tool box with the name, “Map Control.”

Page 18: Using Map WinGIS

- 18 - DRAFT

Auto Sizing Your Map… If you want your map to be resized when the user resizes the form, you can set the “Anchor” property of the map component in the Visual Basic Properties window. Another nice effect is to use the “Dock” property to fill the form space with your map.

Adding a Map Component to your Visual Basic Form Adding a MapWinGIS Map component to your Visual Basic form is as simple as selecting the “Map Control” tool from the toolbox and dropping it on the form. In the example we have a form called “Form1” and an instance of MapWinGIS called “AxMap1”on the form.

Page 19: Using Map WinGIS

- 19 - DRAFT

Adding a Shapefile Data Layer to Your Map You should now have the MapWinGIS component file loaded on your computer, registered in the system registry, referenced in Visual Basic 2005, and added to a new blank form. You are now ready to start viewing data!

We will start with viewing vector shapefile data. The code to load a single shapefile into your map is very simple. Before we get started, let’s clean up our project a bit and make sure it is saved. Using the component names presented here will help ensure that your screen looks the same as the screen images shown here.

1) Rename the form from “Form1” to “frmMain” 2) Rename the map control from “AxMap1” to “mapMain” 3) Give frmMain the title, “My First Map Application” 4) Save your project as “MyFirstMapApp”

For our first example, you will create a subroutine called “LoadData” to

display a single shapefile. Open the code view for frmMain and view the code stub for the frmMain_Load function (the easy way to get there is by double-clicking on an empty area of the form somewhere.) Enter the following code into the frmMain_Load stub and create the LoadData function as follows:

Private Sub frmMain_Load(…) Handles MyBase.Load LoadData() End Sub Private Sub LoadData() Dim sfWorld As New MapWinGIS.Shapefile sfWorld.Open("C:\...\world_adm0.shp") mapMain.AddLayer(sfWorld, True) End Sub

Note that in the frmMain_Load function we have used “…” to indicate the frmMain_Load default parameters. In your code, you should see these parameters, not, “…”. Also in the LoadData function we are using “\...\”

Page 20: Using Map WinGIS

- 20 - DRAFT

to indicate the path to your data file. If you are using the sample data in the MapWindow application folder, then your full path might be:

“C:\Program Files\MapWindow\Sample Projects\World\Shapefiles\world_adm0.shp”

Now, start your program by hitting the F5 key, or by using the menu Debug|Start Debugging. There it is! Your first MapWinGIS application!

For this and other code samples in this book, we will take the approach of 1) showing the full code snippet; 2) showing the expected results or output; and 3) walking through the key parts of the code for which further explanation is useful.

The current example only has three lines of code that need explanation:

Dim sfWorld As New MapWinGIS.Shapefile

MapWinGIS has many useful objects—one of the most important is the MapWinGIS.Shapefile object. Here we are simply creating an instance of an empty shapefile object with the name, sf1.

sfWorld.Open("C:\... \world_adm0.shp")

Page 21: Using Map WinGIS

- 21 - DRAFT

A full list of all shapefile objects and functions is given in Part 2 of this book. Here we are using the “Open” function to open the specified shapefile. Remember that a shapefile is actually defined by 3 files, *.shp, *.shx and *.dbf. When opening a shapefile using the shapefile object, reference the full path of the *.shp file.

mapMain.AddLayer(sfWorld, True)

The AddLayer function on the map control takes two parameters, a

generic Object, and a Boolean parameter, “visible,” indicating whether or not to display the layer when it is added to the map.

The first parameter can be a MapWinGIS.Shapefile or a MapWinGIS.Image object. The second parameter is used to add the layer invisibly so that you can change its display properties before “turning it on”. For example, you may want to change the outline color of the countries layer before displaying it in the map. In that case, you would add the layer with the “visible” flag set to false. Then you would change the outline color on the layer, and finally, change the visible flag to true. We will learn how to do this in a later chapter.

Now that your first map application is running, you can try using the zoom functions on the map. When your application starts, the map will default to the “zoom in” cursor mode. In this mode, you can zoom to any part of the map with a single click on the map, or by drawing a “zoom box” on the area you want to zoom in to. To zoom out, simply right click on the map.

Page 22: Using Map WinGIS

- 22 - DRAFT

Creating Zoom and Pan Buttons One of the distinguishing characteristics of a GIS application, versus an application that shows static, unchanging maps, is the ability to navigate the map using zoom and pan buttons. In this section you will add a tool strip with four buttons to expose the following functions: zoom in, zoom out, pan, and zoom to full extents. You will attach these buttons to the appropriate functions in MapWinGIS and have fully functioning map navigation.

First place a ToolStrip component on your form. We will use the ToolStrip for the navigation buttons. Add four text buttons (or graphic buttons if you are adventurous) to the ToolStrip. Name your buttons, “btnZoomIn,” “btnZoomOut,” “btnPan,” and “btnFullExtents” and provide them with appropriate text, tool tips, and graphics as you see fit.

Instead of the ToolStrip control, you could also do this example using four simple command buttons. We will use the ToolStrip control in the remainder of this example.

Add code to the subroutine stubs for each of the Click event for each of your buttons. Your code should look like this:

Private Sub btnZoomIn_Click(ByVal sender As

… System.Object, ByVal e As … System.EventArgs) Handles btnZoomIn.Click

mapMain.CursorMode = MapWinGIS.tkCursorMode.cmZoomIn End Sub Private Sub btnZoomOut_Click(ByVal sender As

… System.Object, ByVal e As … System.EventArgs) Handles btnZoomOut.Click

mapMain.CursorMode = MapWinGIS.tkCursorMode.cmZoomOut End Sub

Page 23: Using Map WinGIS

- 23 - DRAFT

Private Sub btnPan_Click(ByVal sender As System.Object, … ByVal e As System.EventArgs) Handles … btnPan.Click

mapMain.CursorMode = MapWinGIS.tkCursorMode.cmPan End Sub Private Sub btnFullExtents_Click(ByVal sender As

… System.Object, ByVal e As … System.EventArgs) Handles … btnFullExtents.Click

mapMain.ZoomToMaxExtents() End Sub

In this code, you are making extensive use of the “Map.CursorMode”

property. The two remaining other enumerations of Map.CursorMode are cmSelection and cmNone. The enumeration cmSelection is used to convert the MapWinGIS cursor into a “pointing finger” that can be used for making selections on the map. The enumeration cmNone is a special case that is used when you are developing your own map interaction behavior and you don’t want one of the other cursor modes to interfere with your custom actions.

Run your program and see how it works. You should be able to change to the zoom in, zoom out, or pan mode and you should also be able to zoom to the full map extents. Here is a screenshot of the application as it should look so far (zoomed to Italy).

Now might be a good time to save your project as you get ready to move on to Chapter 3.

Page 24: Using Map WinGIS

- 24 - DRAFT

Zooming… MapWinGIS uses several optimization techniques for fast drawing. As you zoom around your map note that the drawing is slightly faster when you are zoomed to a small area and slightly slower at the full extents. This is due to an optimization that only draws those shapes that fall within your current extent on each zoom or pan function call.

Page 25: Using Map WinGIS

- 25 - DRAFT

3 Shapefile Display, Coloring Schemes,

and Labels In most circumstances, GIS software developers need the ability to create rich and informative maps by presenting data in visually stimulating ways. Typically, we use such techniques as coloring schemes, markers, labels, and other types of symbology to improve the visual value of a digital map. Symbology can be used to convey information about your data, such as the population of a country, or simply to draw attention to part of your map by highlighting a certain feature. In this chapter, you will learn how to adjust the global display properties for a layer, how to apply a coloring scheme to your data, how to add labels to your data.

Adjusting Shapefile Display Properties Before we start working with symbology, let’s add another layer to the project we started in the last chapter. Modify the frmMain_Load event to include the following code. NOTE: in this code, “…” should be replaced with the direct path to your shapefiles.

Page 26: Using Map WinGIS

- 26 - DRAFT

Private Sub LoadData() Dim sfWorld As New MapWinGIS.Shapefile Dim sfCities As New MapWinGIS.Shapefile Dim hndWorld As Integer Dim hndCities As Integer sfWorld.Open("C:\...\world_adm0.shp") sfCities.Open("C:\...\cities_capital_pt.shp") hndWorld = mapMain.AddLayer(sfWorld, True) hndCities = mapMain.AddLayer(sfCities, True) End Sub

Run your application and make sure you see both the country outlines and the city points. When you add layers to MapWinGIS, the data are displayed in the opposite order from which you added them to the map. In other words, if you add the cities layer first and then the countries, you would not see the cities because the countries data would be on top of them.

Note an important change to the code on the following lines:

hndWorld = mapMain.AddLayer(sfWorld, True) hndCities = mapMain.AddLayer(sfCities, True)

Previously we added the data layer to the map without catching the

value returned from the AddLayer function. This is convenient for quickly dropping a file into a map. However, usually we want to keep track of the layer that we just added, so we do that with a layer handle returned from the AddLayer function. In the previous lines, the variables hndWorld and hndCities will hold an integer value that is a handle to that layer within the map. We need that handle for applying visualization changes.

Now we will explore global display properties for point and polygon shapefile layers. Add the following lines of code after your AddLayer function calls. (Note that when a line of code is too wide for this book, we are indicating wrapped text using “…”.) Dim FillColor As UInt32 Dim LineColor As UInt32 Dim LineWidth As Single Dim PointColor As UInt32 Dim PointSize As Single

Page 27: Using Map WinGIS

- 27 - DRAFT

'Global display settings for the countries polygons mapMain.set_ShapeLayerDrawFill(hndWorld, True) FillColor = Convert.ToUInt32(RGB(Color.SpringGreen.R,

… Color.SpringGreen.G, Color.SpringGreen.B)) LineColor = Convert.ToUInt32(RGB(0, 0, 255)) LineWidth = 2.0 mapMain.set_ShapeLayerFillColor(hndWorld, FillColor) mapMain.set_ShapeLayerLineColor(hndWorld, LineColor) mapMain.set_ShapeLayerLineWidth(hndWorld, LineWidth) 'Global display settings for the cities points PointColor = Convert.ToUInt32(RGB(255, 255, 0)) PointSize = 8 mapMain.set_ShapeLayerPointColor(hndCities,

… PointColor) mapMain.set_ShapeLayerPointSize(hndCities, PointSize) mapMain.set_ShapeLayerPointType(hndCities,

… MapWinGIS.tkPointType.ptCircle)

When you run your application it should look like this:

This sample code demonstrates several global display parameters for

shapefile layers. The first question you might ask is, “why are we using UInt32 data types for the colors?” This is actually a really good question. MapWinGIS ActiveX was written to support both .NET and non-.NET

Page 28: Using Map WinGIS

- 28 - DRAFT

application development environments (e.g. Visual Basic 6.0) that do not support the .NET color enumerations. Instead these non-.NET languages expect to pass the control the equivalent of a Visual Basic 6.0 Long Integer. Hence, when working in .NET we need to cast the .NET color into a UInt32 data type before using it in the function calls. The following lines illustrates the conversion from a .NET color object and from an RGB defined color:

FillColor = … Convert.ToUInt32(RGB(Color.SpringGreen.R, … Color.SpringGreen.G, Color.SpringGreen.B))

LineColor = Convert.ToUInt32(RGB(0, 0, 255))

This code also demonstrates use of the “set_ShapeLayerLineWidth” function, and the “set_ShapeLayerPointSize” function, both of which should be relatively self explanatory, requiring only a Single value. The function, “set_ShapeLayerPointType” provides an enumeration of point types including square, circle, diamond, and triangles facing up, down, left or right. The “ptUserDefined” and “ptImageList” enumerations are used when you want to specify an icon or bitmap to display on each point.

It should now be clear why we needed to capture the return value from

the AddLayer function. The handles, hndWorld and hndCities are used to indicate which layer we are working on when we set properties in the map.

We will now modify the code to use a bitmap to represent the cities point shapefile. To do this, we need to first find an appropriate bitmap. You may want to make your own bitmaps or find suitable bitmaps on the Internet. For this example, we will use a cute camera I made: .

VB 6.0 Function Calls … In Visual Basic 6.0 and VBA development environments, many of the function calls described here will appear different, not having the “set_” prefix. Instead the shape line color, for example, would be specified as: mapMain.ShapeLayerLineColor(hndWorld) = vbRed.

Page 29: Using Map WinGIS

- 29 - DRAFT

To use this custom bitmap as the marker for a point shapefile, simply change the point type parameter to be ptUserDefined. Here is how the block of code for your cities global display settings should look now: 'Global display settings for the cities points PointColor = Convert.ToUInt32(RGB(255, 255, 0)) PointSize = 1 mapMain.set_ShapeLayerPointColor(hndCities, PointColor) mapMain.set_ShapeLayerPointSize(hndCities, PointSize) mapMain.set_ShapeLayerPointType(hndCities,

… MapWinGIS.tkPointType.ptUserDefined) Dim imgCities As New MapWinGIS.Image imgCities.Open("C:\...\camera16.bmp") mapMain.set_UDPointType(hndCities, imgCities)

If you use the camera bitmap provided with this book, your results should look something like this:

Page 30: Using Map WinGIS

- 30 - DRAFT

We have made three main changes to the code to be able to render

images for our point shapefile. 1) Change the point size property back to “1”. When using custom bitmaps, the size is multiplied by the value specified by set_ShapeLayerPointSize. 2) Use set_ShapeLayerPointType to specify a ptUserDefined point type. 3) Apply your bitmap to the shape layer. The third step requires the following lines of code:

Dim imgCities As New MapWinGIS.Image

Here we are creating a new MapWinGIS.Image object called imgCities.

Custom bitmaps in MapWinGIS must be defined as a MapWinGIS.Image. In the next line, we open the selected bitmap file into the MapWinGIS.Image object:

imgCities.Open("C:\...\camera16.bmp")

Finally, we tell the map to use the imgCities object as the user defined point type for the cities data layer:

mapMain.set_UDPointType(hndCities, imgCities)

Note that MapWinGIS also allows you to set a unique icon for each point shape in your map using the ptImageList point type. This function will be covered later in this chapter.

Transparency in Custom Bitmap Images… MapWinGIS looks at the pixel in the upper left hand corner of your bitmap and treats it as the transparency color. So if you want to have transparency somewhere in your bitmap, just choose the color that will be rendered transparent and place one pixel of that color in the upper left hand corner of your bitmap.

Page 31: Using Map WinGIS

- 31 - DRAFT

Setting a Coloring Scheme In MapWinGIS we se the term “coloring scheme” to mean color symbology that differentiates features on your map using colors based on a value in the shapefile attribute table. In this section we will build upon the code from the last section to color the countries data based on an attribute in the data called “region.”

Enter the following code in your LoadData function after the global display settings sections:

'Set up a coloring scheme for the countries polygons Dim ShapeNum As Integer Dim Region As String Dim FieldNum As Integer FieldNum = 2 For ShapeNum = 0 To sfWorld.NumShapes - 1 Region = sfWorld.CellValue(FieldNum, ShapeNum) Select Case Region Case "Antarctica" mapMain.set_ShapeFillColor(hndWorld, ShapeNum,

… Convert.ToUInt32(RGB(100, 50, 0))) Case "Asia" mapMain.set_ShapeFillColor(hndWorld, ShapeNum,

… Convert.ToUInt32(RGB(120, 70, 20))) Case "Australia" mapMain.set_ShapeFillColor(hndWorld, ShapeNum,

… Convert.ToUInt32(RGB(140, 90, 40))) Case "Caribbean" mapMain.set_ShapeFillColor(hndWorld, ShapeNum,

… Convert.ToUInt32(RGB(160, 110, 60))) Case "Europe" mapMain.set_ShapeFillColor(hndWorld, ShapeNum,

… Convert.ToUInt32(RGB(180, 130, 80))) Case "Latin America" mapMain.set_ShapeFillColor(hndWorld, ShapeNum,

… Convert.ToUInt32(RGB(200, 150, 100))) Case "North America" mapMain.set_ShapeFillColor(hndWorld, ShapeNum,

… Convert.ToUInt32(RGB(220, 170, 120))) Case "NorthAfrica"

Page 32: Using Map WinGIS

- 32 - DRAFT

mapMain.set_ShapeFillColor(hndWorld, ShapeNum, … Convert.ToUInt32(RGB(240, 190, 140)))

Case "Pacific" mapMain.set_ShapeFillColor(hndWorld, ShapeNum,

… Convert.ToUInt32(RGB(250, 210, 160))) Case "Sub Saharan Africa" mapMain.set_ShapeFillColor(hndWorld, ShapeNum,

… Convert.ToUInt32(RGB(255, 230, 180))) End Select Next mapMain.set_LayerVisible(hndCities, False)

When you run your application now, you should see that all of the

major regions of the world have been assigned a unique color. It should look something like this:

The code that we used to generate this map can be broken down into

three main steps. 1) Identify the field in the attribute table containing the data that will be used for the divisions or breaks in the coloring scheme. 2) Cycle through all of the shapes in the shapefile. 3) Identify shapes that have

Page 33: Using Map WinGIS

- 33 - DRAFT

a particular attribute value. 4) Assign a specific color to the individual shapes that meet the specified criteria.

In our sample code note that we had to know a priori which field contained the “region” data:

Dim FieldNum As Integer FieldNum = 2

In this case, we know that region is contained in field index 2. Fields

are indexed starting at zero, and don’t include the “ShapeNum” field that you might see if you look at the data in a desktop GIS application such as MapWindow GIS.

Once you know the field that you need to look in, then you simply cycle through all of the shapes in your shapefile looking for specific values in that field. In the following code, we are searching through all of the shapes based on their indices which range from 0 through n-1 (where n is the total number of shapes in the shapefile).

For ShapeNum = 0 To sfWorld.NumShapes - 1

In the next line, we extract the data contained in the shapefile attribute table at field index 2 and shape number, ShapeNum:

Region = sfWorld.CellValue(FieldNum, ShapeNum) If you add a debugger “Watch” flag to this variable, Region, then you

will see that as it passes this line, it contains strings such as, “Asia”. Finally we do a Select Case on the Region variable to take a specific

action depending on the value. In the following line, we set a fill color for every shape that has the value “Antarctica” set as its region:

Case "Antarctica" mapMain.set_ShapeFillColor(hndWorld, ShapeNum, … Convert.ToUInt32(RGB(100, 50, 0)))

Notice that we are using the conversion from RGB to UInt32 for all of

these color assignments. Also, notice the distinction between the function

Page 34: Using Map WinGIS

- 34 - DRAFT

call we used for global coloring, set_ShapeLayerFillColor, versus the function call used to color an individual shape, set_ShapeFillColor. A final note on this example: the last line of the example demonstrates how to turn on or turn off a specific layer in code:

mapMain.set_LayerVisible(hndCities, False)

Here we have turned the cities layer off so that we can have a better view of the results of our coloring scheme activity.

Using the technique shown here, you should be able to create any kind of coloring scheme symbology. For example, you can color points or lines based on a numeric value in the attribute table. You can also size your points based on a value such as population. Simply follow the same approach to get the attribute data from the attribute table (using “CellValue”) and then compare that to an expected value and size your point accordingly.

Using a Point Image List In our last symbology example, we will use an image list to specify two unique bitmaps to represent our cities. One will be used to indicate capital cities, and the other to indicate regular cities.

Start by identifying or making two bitmaps. You can open Microsoft Paint, for example, and draw your bitmaps and save them separately. For our example, I’ve drawn a red star to mark capitol cities and a yellow circle to represent regular cities.

Now insert the following code at the end of your LoadData function. Remember to specify the full path to your bitmaps: 'Set up a an image list for a point layer Dim imgCapitol As New MapWinGIS.Image Dim imgRegular As New MapWinGIS.Image Dim intCapitolIndex As Integer Dim intRegularIndex As Integer Dim isCapitol As Integer mapMain.set_ShapeLayerPointType(hndCities,

… MapWinGIS.tkPointType.ptImageList)

Page 35: Using Map WinGIS

- 35 - DRAFT

imgCapitol.Open("C:\...\capitolcity.bmp") imgRegular.Open("C:\...\city.bmp") intCapitolIndex = mapMain.set_UDPointImageListAdd

… (hndCities, imgCapitol) intRegularIndex = mapMain.set_UDPointImageListAdd

… (hndCities, imgRegular) FieldNum = 8 For ShapeNum = 0 To sfCities.NumShapes - 1 isCapitol = sfCities.CellValue(FieldNum, ShapeNum) If isCapitol = 1 Then mapMain.set_ShapePointImageListID(hndCities,

… ShapeNum, intCapitolIndex) Else mapMain.set_ShapePointImageListID(hndCities,

… ShapeNum, intRegularIndex) End If Next mapMain.set_LayerVisible(hndCities, True)

When you run your application, you should see a map of the world with all of the cities flagged as either capitol or regular cities. Here is what it might look like (with your images of course):

Page 36: Using Map WinGIS

- 36 - DRAFT

This example is similar to the coloring scheme example in the way that we search all shapes for attributes that match a specific value. However it is also different since the map component needs to store all of the images that you will be referencing for your points. Note the following lines:

Dim imgCapitol As New MapWinGIS.Image Dim imgRegular As New MapWinGIS.Image …

imgCapitol.Open("C:\...\capitolcity.bmp") imgRegular.Open("C:\...\city.bmp") …

intCapitolIndex = mapMain.set_UDPointImageListAdd … (hndCities, imgCapitol)

intRegularIndex = mapMain.set_UDPointImageListAdd … (hndCities, imgRegular)

Here we create two MapWinGIS.Image objects, imgCapitol and

imgRegular. These are then used to open two bitmaps from the disk. Of course \...\ indicates the full path to your image files on your own computer. Finally, we add both of these images to a global image list stored inside the map component using set_UDPointImageListAdd. This makes the images available to you later when you want to specify a particular image for a specific point. To reference the images that we added to the image list, you are given an index as the return value from the function. In the example, we are storing these indices as intCapitolIndex and intRegularIndex.

Now look at the loop through the shapes. For each shape we are going to test the value of the contents of field number 8:

isCapitol = sfCities.CellValue(FieldNum, ShapeNum)

I happen to know that field number 8 contains a flag value of 1 or 0 indicating whether or not the city is a capitol city. For those cities that have the flag set to 1, we then specify that they should use the image from the image list with index intCapitolIndex as follows:

mapMain.set_ShapePointImageListID(hndCities, … ShapeNum, intCapitolIndex)

Page 37: Using Map WinGIS

- 37 - DRAFT

If the city is not a capitol city (i.e. the value in field 8 is 0) then we specify to use the image from the image list with the index intRegularIndex:

mapMain.set_ShapePointImageListID(hndCities, … ShapeNum, intRegularIndex)

Image lists for point shapefile bitmaps can be very useful. For example,

you could specify a series of images that indicate type of weather station, road, building, environmental monitoring station, etc.

Labeling Features Labeling of features on a map is an art that is very difficult to automate. There are issues of label sizing, fonts, scaling, rotation, following lines, centering in polygons, placement by points, collision with other labels, and on and on. Indeed, even the most functional GIS tools often expect the user to perform final labeling for map production in external, add-on, or third party applications.

MapWinGIS as primarily a dynamic GIS software development tool (as opposed to a tool for generating paper map printouts) has a robust and flexible set of labeling functions, but leaves much of the responsibility for labeling with the programmer (you!). In this section we’ll learn how to use the AddLabel and AddLabelEx functions to automatically label a map. We will use the same two data sets that were used in the previous sections.

To start, we need to decide what features you want to label, and what text you want to apply. Next you need to obtain positioning information. Finally you need to determine the look of the labels you are going to apply as you place them on the map.

For the sake of continuity, use the same code from the previous section and add the following lines to the end of your LoadData function: 'Add labels to cities Dim LabelText As String Dim LabelColor As UInt32 = Convert.ToUInt32(RGB(0,0,0)) Dim X As Double

Page 38: Using Map WinGIS

- 38 - DRAFT

Dim Y As Double FieldNum = 2 For ShapeNum = 0 To sfCities.NumShapes - 1 LabelText = sfCities.CellValue(FieldNum, ShapeNum) X = sfCities.Shape(ShapeNum).Point(0).x Y = sfCities.Shape(ShapeNum).Point(0).y mapMain.AddLabel(hndCities, LabelText, LabelColor, X,

… Y, MapWinGIS.tkHJustification.hjCenter) Next

When you run this code, you should see a map of the world with all of the major cities labeled by with their names. In the following screenshot, we have zoomed to Germany and can see several major cities in and around Germany:

The code for generating these labels is quite simple. We specified a

label color and a field in the shapefile attribute table from which to pull the label text. Next we cycled through all of the shapes in the shapefile and extracted the label text as well as the X and Y coordinates of the points. Finally we used the AddLabel function to apply the labels to the map.

All of the code used here should be fairly straightforward given our previous examples, however the following lines are worth pointing out:

X = sfCities.Shape(ShapeNum).Point(0).x

Page 39: Using Map WinGIS

- 39 - DRAFT

Y = sfCities.Shape(ShapeNum).Point(0).y In these two lines of code, we are extracting the X and Y coordinates of

the current point in our For…Next loop. Notice, however, that to get to the X and Y values, we actually look at the Shape object at index, ShapeNum, and then for that Shape, we look at its Point object at position 0. The logic behind this approach might make more sense if you consider a polyline shapefile.

Assume that you have a polyline shapefile with 20 polylines. In MapWinGIS, each of these polylines would be considered a single “Shape” object. Each of these Shape objects are, in turn, comprised of a series of “Point” objects. Each Point object contains information such as X, Y, and Z location.

In the case of a point shapefile, each unique Shape object only has one associated Point object. And that point object is at index 0. The same object structure is used for both point, line, and polygon shapefiles for the sake of consistency. Just keep in mind that a shapefile is comprised of shapes and there is a one-to-one relationship between each shape and a single record in the shapefile attribute table. Each of these shapes is comprised of points. And for point shapefiles, there is only one point per shape.

Looking back at our sample code, once we have obtained the X and Y coordinates for the city in question, we can use that information to place a label using this line:

mapMain.AddLabel(hndCities, LabelText, LabelColor, … X, Y, MapWinGIS.tkHJustification.hjCenter)

Here we specify the handle index of the layer to which the label

belongs, the text of the label, the color of the label, the position (X and Y) of the label, and finally the justification of the label. Justification options include left, right, and centered. You can try the other justification options and see how they adjust the positioning of the labels.

From this example, it should be clear to you that labels, though connected to a particular layer, are effectively independent of the data in the layer. You could just as easily have generated random text and random X and Y locations and used those as labels on your layer. Of course this isn’t

Page 40: Using Map WinGIS

- 40 - DRAFT

always useful, but it is meant to give you a high level of flexibility in applying labels.

You can further customize your map labels by using the function LayerFont to specify a particular font and font size:

mapMain.LayerFont(hndCities, "Times New Roman", 9) Label scaling is useful if you want to let have your labels grow and shring with the map when your users zoom in and out:

mapMain.set_LayerLabelsScale(hndCities, False) A global label offset can be set for a specific layer so that all labels are adjusted vertically by a constant number of pixels. This is useful if you want to avoid collision between your label and a custom point bitmap:

LaymapMain.set_LayerLabelsOffset(hndCities, 8) Label shadows can help your readability by providing a background around the label:

mapMain.set_LayerLabelsShadow(hndCities, True) mapMain.set_LayerLabelsShadowColor(hndCities, ShadowColor)

And finally, once you have applied labels to a layer, you can turn them on and off using the set_LayerLabelsVisible function:

mapMain.set_LayerLabelsVisible(hndCities, True) We will now take a look at another function for adding labels to your

map. As its name implies, AddLabelEx is an extended labeling function with an useful addition – rotation of labels. To see this function work, replace the AddLabel function call in your code with the following line:

mapMain.AddLabelEx(hndCities, LabelText, … LabelColor, X, Y, MapWinGIS.tkHJustification. … hjCenter, 45)

Page 41: Using Map WinGIS

- 41 - DRAFT

When you run your application, you should see all of the labels rotated at a 45 degree angle (counterclockwise from horizontal) as shown in the following screenshot:

The final labeling function we will explore is automatic label collision

avoidance. Too many labels on a map can make it illegible, especially when they overlap each other. The purpose of automatic label collision avoidance is to avoid this situation, and make sure that all of the labels on your map are separated enough to be legible.

To activate automatic label collision avoidance, use the following function:

mapMain.set_UseLabelCollision(hndCities, True)

Notice that you must specify the layer for which you want this function

activated. In our case we specify the handle to the Cities shapefile layer. The second parameter is a Boolean indicating whether you want the capability activated or not.

The following screenshot, though not particular visually appealing, indicates the value of the label collision avoidance function. In the map of India on the left, you can see that only the city of Dehli is labeled (in the

Page 42: Using Map WinGIS

- 42 - DRAFT

North part of the map). However, when the user zooms in to the area around Dehli, all of the other major cities become labeled—as shown in the figure on the right.

Label collision avoidance is particularly useful when you are using fixed size labels. In this case, as you zoom out, the labels remain a constant size and would begin to block and overlap each other. This is not always as much of a problem when you use scalable labels that grow and shrink with your map.

As you become familiar with these labeling functions as well as the other symbology techniques illustrated in this chapter you should be able to create dynamic and informative, well-labeled maps for you users.

Performance Issues… We have shown you lots of interesting and powerful labeling and symbology capabilities in this chapter. As you use these functions, be aware that each one carries an additional overhead for speed and performance of your application. You may want to consider trying a variety of symbology and labeling techniques with data sets that are typical for your particular mapping application and make sure that speed and performance to not begin to suffer.

Page 43: Using Map WinGIS

- 43 - DRAFT

(This is a work in progress with several more chapters to go. Check for an updated and extended version of this document at: http://www.MapWindow.org/doc/UsingMapWinGIS.pdf Thanks! Dan)