(Click to go to part one of this tutorial)
Introduction
The objective of this series is to present a simple and easy to use approach to develop a desktop GIS application. My tool pack includes only MapWinGIS.ocx from MapWindow GIS Project which is one of the most successful open source GIS projects for Windows platform. MapWinGIS.ocx provides the full set of tools to maintain and display GIS data and it is free of charge under MPL license.
In the previous lesson, we discussed the basics required to display GIS data on the MapWinGIS.ocx Map Control. We also discussed how to customize the symbology of the displayed GIS data. In this lesson, I am going to teach you how to advance your symbology skills and use labeling functionality on your map.
As mentioned in the previous lesson, I am using .NET Framework 3.5 and Visual Studio 2008 professional edition in the code attached here, but you can use Visual Studio express edition to get the same results. You have to download MapWinGIS.ocx and install it on your machine too. You can download it from the official site of MapWindow Project.
Attributes and Symbology
One of the most amazing features of GIS is combining the description of the geographic entity with its geometry. Indeed, every geographic entity may describe using different attributes. For example, the attributes of land parcel may include area, perimeter, owner name, land use, etc. which these attributes may use to create different maps using different symbology approaches. In the previous lesson, we had used a simple symbology approach where all features in the GIS layer presented use a single symbol. In this lesson, we will know how we can create a quantitative map using attribute data.
According to ESRI Shapefile specification that was published by ESRI in July 1998, “Shapefile
” technically means three files have the same name and different extensions:
- *.shp is the main file that includes the geometric presentation of the geographic entities
- *.shx is the index file, and
- *.dbf is the attribute file
ESRI Shapefile
uses Dbase IV DBF file format to store the attributes of the GIS layer. The data attached to this lesson is a single ESRI Shapefile that presents Arab League Countries. The attributes of this shapefile are organized in two fields CNTRY_NAME
and POP_CNTRY
. CNTRY_NAME
is a text field which includes the name of the country. POP_CNTRY
is an unsigned long integer field that includes the population of the country.
Create Your GUI
The GUI of our application is composed of a single Windows Form. This form has a tool strip named toolStrip1
which has five buttons, toolCursor
, toolZoomExtent
, toolZoomIn
, toolZoomOut
and toolPan
. The code of these buttons is discussed in the previous lesson. The form has a split container named splitContainer1
which is split vertically into two panels splitContainer1.panel1
to left and splitContainer1.panel2
to right. The left panel includes three buttons, btnReset
, btnQuant
and btnLablel
. The right panel includes the MapWinGIS.ocx Map Control component named axMap1
. You have also added a reference for MapWinGIS.ocx to your project. The previous lesson includes details for reference adding procedure.
The following figure shows the GUI of the application attached to this lesson:
Set Your Public Variables
I am using two public
variables in this application. The first is an integer that denotes the layer handler and the second is MapWinGIS.Shapefile
. These variables will be declared directly after the first clause of the class declaration as shown in the following:
public int intHandler;
public MapWinGIS.Shapefile myShapefile = new MapWinGIS.Shapefile();
These items should be public
because many methods will use these items.
Create a SetBasicSymbology Method
This objective of this method is to set the symbology of the layer to a specific predefined symbology every time it is called. It does not return any value. The following code shows this method:
public void SetBasicSymbology()
{
axMap1.set_ShapeLayerFillColor(intHandler,
(UInt32)(System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Honeydew)));
axMap1 .set_ShapeLayerLineColor(intHandler,
(UInt32)(System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Goldenrod)));
}
Load Your Data
Now, we will load our data to our form, the following code should add to Form1_Load
event:
private void Form1_Load(object sender, EventArgs e)
{
myShapefile.Open(@"D:\GISSampleData2\arabcntry.shp", null);
intHandler = axMap1.AddLayer(myShapefile, true);
SetBasicSymbology();
}
This code loads the shapefile (D:\GISSampleData2\arabcntry.shp) into MapWinGIS.Shapefile
instance (myShapefile
), then adds it to the map control (axMap1
) and stores its handler in intHandler
. Finally, we will call SetBasicSymbology()
to set the layer symbology to the basic symbology.
btnReset Code
The objective of btnReset
is to reset the symbology of the layer to the basic symbology every time a user clicks it. The code of btnReset
is the following:
private void btnReset_Click(object sender, EventArgs e)
{
SetBasicSymbology();
}
btnQuant Code
The code of btnQUnat
is the main target of this lesson. This code customizes the layer symbology to show the population of each country using a spectrum of two colors. The first color is aqua color which illustrates the less populated country; another color is Dark Blue which illustrates the most populated country. Any country that has population among the less and most population will be colored with a color among aqua and dark blue.
To do that, you have to know which field in the shapefile
table includes the population and calculate the minimum and maximum population.
The code will be added to the btnQuant_Click
event to let the user click this button and make his/her quantitative map that shows the population in the Arab League Countries.
The code is the following:
private void btnQuant_Click(object sender, EventArgs e)
{
MapWinGIS.Table myTable = new MapWinGIS.Table();
myTable.Open(@"D:\GISSampleData2\arabcntry.dbf", null);
int myFieldIndex = 1;
int numberOfRows = myTable.NumRows;
double[] myCellsValues = new double[numberOfRows];
for (int i = 0; i < numberOfRows - 1; i++)
{
myCellsValues[i] =
System.Convert.ToDouble(myTable.get_CellValue(1, i));
}
double minValue = myCellsValues.Min();
double maxValue = myCellsValues.Max();
MapWinGIS.ShapefileColorScheme myScheme =
new MapWinGIS.ShapefileColorScheme();
myScheme.LayerHandle = intHandler;
myScheme.FieldIndex = myFieldIndex;
MapWinGIS.ShapefileColorBreak myBreak =
new MapWinGIS.ShapefileColorBreak();
myBreak.StartValue = minValue;
myBreak.StartColor =
(UInt32)(System.Drawing.ColorTranslator.ToOle
(System.Drawing.Color.Aqua));
myBreak.EndValue = maxValue;
myBreak.EndColor =
(UInt32)(System.Drawing.ColorTranslator.ToOle
(System.Drawing.Color.DarkBlue));
myScheme.Add(myBreak);
axMap1.ApplyLegendColors(myScheme);
}
In the first line, we declare and initiate a new instance of MapWinGIS.Table
class and name it myTable
. This class is designed to present the table of ESRI Shapefile
. The instance of this class includes a collection of instance for Field
class. Each Field
instance is used to present a field in the table of shapefile
. The instances have zero-based index. Each Field
instance has a collection of instances for CellValue
class. CellValue
instance presents the values of the cells organized in a Field
instance.
In the second line, we load our dbf
table in MapWinGIS.Table
instance (myTable
) using Open
method.
In the third line, we declare an integer (myFieldIndex
) and assign one to him. This integer is used to identify the field we will use in symbology as the second field (POP_ CNTRY
).
The fourth line is used to get the number of rows in the table using NumRows
method of MapWinGIS.Table
instance (myTable
).
In the fifth line, we declare and create an array (myCellsValues
) composed of a number of double
elements equal to the number of rows in the table.
Now, we will use For
loop to populate our new array (myCellsValues
) by the values of CellValue
instance in myTable
. Then we will get the minimum and maximum values in the array using Min
and Max
methods for array.
The minimum and maximum values are assigned to two variables minValue
and maxValue
of double
type.
Now, we will declare and create a new instance for MapWinGIS.ShapefileColorScheme
class and name it myScheme
. This class is designed to describe the complex color scheme for the layer based on the values stored in the shapefile
table field. The scheme is joined to a specific layer by the handler of this layer, and to the field by the field index. The instance of this class has a collection of MapWinGIS.ShapefileColorBreak
instances.
MapWinGIS.ShapefileColorBreak
class is used to describe a color theme used to color the geographic entities in the layer based on a region of values. This region of values is limited by two properties for each MapWinGIS.ShapefileColorBreak
instance: StartValue
and EndValue
. The color of theme is identified by two another properties for the instance: StartColor
and EndColor
.
In this application, I had used one MapWinGIS.ShapefileColorBreak
instance named myBreak
, and I had assigned the minValue
and maxValue
to StartValue
and EndValue
properties respectively. Also, I had assigned aqua and dark blue colors to StartColor
and EndColor
properties respectively.
After assigning the properties of the MapWinGIS.ShapefileColorBreak
instance (myBreak
), I had used Add
method to add it to MapWinGIS.ShapefileColorBreak
instances collection of myScheme
.
The final step is to use ApplyLegendColors
method of Map Control (axMap1
) to use this scheme to symbolize the layer.
Now, strike F5 to run the application and click btnQuant button to get your new map.
Add Labels to Your Map
Labels are very important to make your map meaningful. Most of the GIS users and developers use values stored in the table to label their features, and that is what I am going to do. Add the following code to btnLabel_Click
event:
private void btnLabel_Click(object sender, EventArgs e)
{
string myLabel;
double x, y;
for (int i = 0; i < myShapefile.NumShapes -1; i++)
{
myLabel = System.Convert.ToString(
myShapefile.get_CellValue(0, i));
x = myShapefile.get_Shape(i).Extents.xMin +
(myShapefile.get_Shape(i).Extents.xMax -
myShapefile.get_Shape(i).Extents.xMin) / 2;
y = myShapefile.get_Shape(i).Extents.yMin +
(myShapefile.get_Shape(i).Extents.yMax -
myShapefile.get_Shape(i).Extents.yMin) / 2;
axMap1.AddLabel(
intHandler,
myLabel,
(UInt32)(System.Drawing.ColorTranslator.ToOle
(System.Drawing.Color.Black)),
x, y,
MapWinGIS.tkHJustification.hjCenter
);
}
}
To add labels for your map, you have to know which field includes the values of labels and where you will set the labels on the map.
In the previous code, I was creating a string
variable named myLabel
and two double
variables x
and y
to use to locate the label on the map. Then, I was using the for
loop to read the cell values from the first field for all shapes in the shapefile
, and each loop I was assigning this value to (myLabel
) string
variable and getting the position of the label as the center of the shape.
Finally, I was using AddLabel
method of Map Control (axMap1
) to add this label (myLabel
) using Black color as a font color in a position identified by x
and y
.
Now, strike F5 to run the application and click btnLabel to show the label on your map.
Now, we have many useful ideas to use MapWinGIS.ocx to build a GIS application. In the next lesson, together we are going to explore how useful arial photographs and satellite images can be for our applications.
History
- Version 1: Thursday, July 16, 2009