Click here to Skip to main content
Click here to Skip to main content

Build a Desktop GIS Application Using MapWinGIS and C# - Part 2

By , 16 Jul 2009
 

(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:

  1. *.shp is the main file that includes the geometric presentation of the geographic entities
  2. *.shx is the index file, and 
  3. *.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:

01.JPG

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:

//Create a layer handler
public int intHandler;
//Create a new instance for MapWinGIS.Shapefile
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()
{
    //Set Filling color of the polygon shapefile
    axMap1.set_ShapeLayerFillColor(intHandler, 
	(UInt32)(System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Honeydew)));
    //Set the outline color of the polygon features
    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)
{           
   //Define the data source of Shapefile instance
   myShapefile.Open(@"D:\GISSampleData2\arabcntry.shp", null);
   //Display the layer on the map control
   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)
        {
            //Create a new instance for MapWinGIS.Table
            MapWinGIS.Table myTable = new MapWinGIS.Table();
            //Define the data source of Table instance
            myTable.Open(@"D:\GISSampleData2\arabcntry.dbf", null);
            //Define the index of the field will used in symbology
            int myFieldIndex = 1;
            //Get the number of rows in the table
            int numberOfRows = myTable.NumRows;
            //Create an array to store the cell values of the field
            double[] myCellsValues = new double[numberOfRows];
            //Populate the array with cell values restored from the Table instance
            for (int i = 0; i < numberOfRows - 1; i++)
            {
                myCellsValues[i] =
                    System.Convert.ToDouble(myTable.get_CellValue(1, i));
            }
            //Get the minimum and maximum values
            double minValue = myCellsValues.Min();
            double maxValue = myCellsValues.Max();

            //Create a new instance for MapWinGIS.ShapefileColorScheme
            MapWinGIS.ShapefileColorScheme myScheme = 
				new MapWinGIS.ShapefileColorScheme();
            //Set the layer handler to the MapWinGIS.ShapefileColorScheme instance
            myScheme.LayerHandle = intHandler;
            //Set the field index to use in symbology
            myScheme.FieldIndex = myFieldIndex;
            //Create a new instance for MapWinGIS.ShapefileColorBreak 
            MapWinGIS.ShapefileColorBreak myBreak = 
			new MapWinGIS.ShapefileColorBreak();
            //Set the minimum value in the field as a start value
            myBreak.StartValue = minValue;
            //Set the start color of the scheme
            myBreak.StartColor =
                (UInt32)(System.Drawing.ColorTranslator.ToOle
		(System.Drawing.Color.Aqua));
            //Set the maximum value in the field as an end value
            myBreak.EndValue = maxValue;
            //Set the end color of the scheme
            myBreak.EndColor =
                (UInt32)(System.Drawing.ColorTranslator.ToOle
				(System.Drawing.Color.DarkBlue));
            //Add the break to the color scheme
            myScheme.Add(myBreak);
            //Upgrade display using the scheme
            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. 

02.JPG

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)
        {
            //Define a string to store the label of the feature
            string myLabel;
            //define two double variables to use as a coordinates for label position
            double x, y;
            //Use a loop to read the cell value that is used as a label and 
	   //set the label on the map
            for (int i = 0; i < myShapefile.NumShapes -1; i++) 
            {
                //assign the value of the cells of the field number zero to the label
                myLabel = System.Convert.ToString(
                    myShapefile.get_CellValue(0, i)); 
                //Calculate the x position for the label
                x = myShapefile.get_Shape(i).Extents.xMin +
                    (myShapefile.get_Shape(i).Extents.xMax - 
			myShapefile.get_Shape(i).Extents.xMin) / 2;
                //Calculate the y position for the label
                y = myShapefile.get_Shape(i).Extents.yMin +
                    (myShapefile.get_Shape(i).Extents.yMax - 
			myShapefile.get_Shape(i).Extents.yMin) / 2;
                //add the label on the map
                axMap1.AddLabel(
                    intHandler, //Layer handler
                    myLabel, //Label string
                    (UInt32)(System.Drawing.ColorTranslator.ToOle
                        (System.Drawing.Color.Black)), //Color of the label
                        x, y, //Position of the label
                        MapWinGIS.tkHJustification.hjCenter //Justification of the label
                        );
            }
        } 

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.

03.JPG

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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Wisam E. Mohammed
Dammam University, Kingdom of Saudi Arabia
Egypt Egypt
Member
Wisam Mohammed was graduated with B.Sc in Math then got M.Sc and Ph.D in Geographic Information Systems. He is working now as Assistant Professor for GIScience in Dammam University, Kingdom of Saudi Arabia where he is living. He had worked for different international and governmental firms.
He is also a Technical Writer. He published many books in Arabic and many scientific papers in the scientific journals. He is the official editor for the Arabic Manual of MapWindow GIS. His book "Basics of Geographic information Systems" was best seller technical book for 2008 in many Arabian Countries. He was honored by many scientific and academic institutions in Arabic countries as a pioneer of the Open Source paradigm in the Arabian World.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 4memberkishore doni28 Aug '12 - 21:56 
fine
QuestionHow to show Arabic charictars in labels?memberyazen91223 Jun '12 - 6:58 
I want to thank you for this tutorial which helped me alot in understanding the main concepts of mapgis.
I would be glad if you help me to solve the problem i faced which is :
 
when I want to add label containg Arabic charictars it shows it as question marks
 
I want a way to let mapgis recognize Arabic charictars
GeneralMy vote of 5memberahmed_am554 May '12 - 17:04 
ما شاء الله
QuestionNeed some helpmemberGISShamanth13 Apr '12 - 21:24 
Hello everyone....
 
I am new to MapWinGis. I am doing my academic project. I have three shape files (soil, wasteland, altitude) . I want to propose the tree species from access database when I select one feature on my wasteland shapefile. I need to write spatial query that will clip remaining two shapes and from the attribute data I should show the resulting species from my access table.
 
Any help on reading material or coding is welcome.
 
Thank you in adv.
QuestionUnworking btnQuant buttonmemberPierre Thouvenin9 Jan '12 - 7:33 
Dear Wisam
 
A big thanks for your series of tutorials. Smile | :)
It was a great introduction to developpment with MapWinGIS and helped me a lot in my current work.
 
I have followed your article but have a problem with the btnQuant button : there is no change in the map colors when it is clicked. Confused | :confused:
 
With debugging I can see that :
- all values of population are read correctly
- all "ShapefileColorBreak" properties are set
- the "ApplyLegendColors" method return true when called
 
I had to edit the loop so that it does one more step, otherwise yemen was ommitted.
At first the other buttons didn't work too, I fixed it by adding a call to "ApplyLegendColors" on an empty scheme at the end of the code of the buttons (though it still needs the correct LayerHandle).
 
If it can be of any help, here is my configuration :
- Windows Vista Pro SP2 32bits
- Visual C# 2010 Express (SP1)
- .NET Framework version 4 (SP1).
- MapWindow 4.8.6
 
Do you have any idea of what could go wrong?
Thanks
AnswerRe: Unworking btnQuant buttonmemberstarWolf14 Feb '12 - 7:47 
There are a few issues with the code as presented. You found out the loop counter was off by one already.
 
I don't know if categorization is something which has been added since this code was written, but I got the code to work using it and the code is much simpler.
 
private void btnCategorization_Click(object sender, EventArgs e)
{
    //Define the index of the field will used in symbology
    int myFieldIndex = 1;
 
    //Generate Categories
    shapeFile.Categories.Generate(myFieldIndex, MapWinGIS.tkClassificationType.ctNaturalBreaks, 25);
    shapeFile.Categories.ApplyExpressions();
 
    //Create a new instance for MapWinGIS.ShapefileColorScheme
    MapWinGIS.ColorScheme myScheme = new MapWinGIS.ColorScheme();
    myScheme.SetColors2(MapWinGIS.tkMapColor.Aqua, MapWinGIS.tkMapColor.DarkBlue);
    shapeFile.Categories.ApplyColorScheme(MapWinGIS.tkColorSchemeType.ctSchemeGraduated, myScheme);
 
    axMap1.Redraw(); // Not in his code, but it forces an immediate redraw of the control so you can see your colors
}

GeneralRe: Unworking btnQuant buttonmemberPierre Thouvenin29 Feb '12 - 3:45 
Thank you for your answer.
Your code works fine for me too. Smile | :)
GeneralRe: Unworking btnQuant buttonmemberdprc24 Apr '12 - 23:16 
Dear,
your code is wonderful!
But you did not select *.dbf, how did you get the color of each country?
I am not very clear about this...
thanks in advance
GeneralRe: Unworking btnQuant buttonmemberstarWolf30 Apr '12 - 9:24 
I am not sure if you are asking me this or not. But the two lines of code:
myScheme.SetColors2(MapWinGIS.tkMapColor.Aqua, MapWinGIS.tkMapColor.DarkBlue);
shapeFile.Categories.ApplyColorScheme(MapWinGIS.tkColorSchemeType.ctSchemeGraduated, myScheme);
Define the colors for each country. Each country has an index, and these two lines build a graduated color scheme, with the colors ranging between Aqua and Dark Blue. Where the country falls in this graduated scheme depends on what it's index is. For example, the country with the lowest color index is going to be Aqua, and the one with the highest index is going to be Dark Blue.
GeneralRe: Unworking btnQuant buttonmemberRavinder Raturi12 Jun '12 - 1:38 
Sorry starWolf, Consider me dumb but i an still not able to figure it out. As dprc mentioned you are not using any database file. Then at what basics are you changing the color. And What is the differenc between your code and the Wisam Code. Why is Wisam code not working(Only btnQuant). Please help.
GeneralRe: Unworking btnQuant buttonmemberstarWolf12 Jun '12 - 2:14 
The Wisam code didn't work because newer versions of MapWinGIS don't work the same. The preferred method of coloring individual shapes in newer versions is to use color schemes. He may have changed it by now, I don't know.
 
As for the database, it is already loaded with the shapes. When you specify the shapes file MapWinGIS will look for a file of the same name with the extension dbf and load that underneath the covers, as it were. You don't have to explicitly load it. when you do the
 
shapeFile.Open(sShapeFullFileName + ".shp", null);
it will also find the dbf file if it has the same name and path. So the myFieldIndex variable finds the column in the dbf to create the color scheme on.
 
The line
shapeFile.Categories.Generate(myFieldIndex, MapWinGIS.tkClassificationType.ctNaturalBreaks, 25);
tells the code to take the minimum and maximum values from column "myFieldIndex" and divide that range into 25 different cells, or buckets.
 
The line
myScheme.SetColors2(MapWinGIS.tkMapColor.Aqua, MapWinGIS.tkMapColor.DarkBlue);
tells the code to color each bucket in a gradient from Aqua to DarkBlue. The rest of the code is applying the gradient scheme to the shapes and redrawing.
GeneralRe: Unworking btnQuant buttonmemberAsp_Harry12 Jun '12 - 4:15 
Ok it's crystal now expect 25. Why 25, why   not any other number. Can you please share some more info about it. And it will be a great help if you can suggest me some tutorial(url) of MapWinGIS.   Sorry for the trouble i m giving you starWolf. I really appreciate your help.
 
Thanks
GeneralRe: Unworking btnQuant buttonmemberstarWolf12 Jun '12 - 4:34 
Why 25? Why not 25?
 
No seriously, the number of color gradient buckets is up to you. Yes, almost any other number would work up to the color resolution of your system. 128 would have worked fine. 17 would have worked. There is nothing magic about 25 except it seemed to be a good number of color buckets.
 
As for tutorials, Wisam's tutorials are pretty good. I would just work your way through those. There are a couple of small programming errors, mostly around loop counters but his basic explanations are pretty good. The only place where his code didn't work at all for me was doing the color gradients and I searched around until I found out why.
 
The way I like to use tutorials like this is to put in the code exactly as written, and then try to figure out how to change things. I would suggest using his code, seeing if you can find the one or type loop errors, fix the color gradients, and then start changing things to see what you can learn.
GeneralRe: Unworking btnQuant buttonmemberAsp_Harry12 Jun '12 - 4:42 
Ok i admit. That was a stupid question. But good answer bTw. Thank a ton. And yes you are right about these tutorials. Thanks once again man..
Cheers
GeneralRe: Unworking btnQuant buttonmemberstarWolf12 Jun '12 - 4:47 
When I used to teach at a University I would tell students the only stupid question was "If a tree falls in a forest and no one is around to hear it..." All other questions are valid.
 
So your question, if it helped you understand, was by all means not stupid. My answer, I admit, started a bit flippant although I meant it to be funny, not insulting and I hope it came across like that.
 
But I am glad you liked the answer and I hope this helps you make some cool apps. I am not a MapWinGIS expert bit I have had quite a bit of fun with it.
GeneralRe: Unworking btnQuant buttonmemberAsp_Harry13 Jun '12 - 23:43 
Sure it did Sir Thumbs Up | :thumbsup: And in future I am sure you will be there to answer more of my stupid questions. LOL
 
Have a Nice Day
Cheers
GeneralMy vote of 5memberKanasz Robert1 Dec '11 - 2:45 
This is really interesting project Wink | ;)
Questionhelp mememberyenchitan8929 Sep '11 - 22:26 
Hello,
In the btnQuant Code, I have followed your code and when I run the application and click btnQuant button, nothing happened. I don't know what's wrong. I've tried in the btnLabel button and that's ok. Can anybody help me? I'm a newcomer in C#.
Thanks.
QuestionHelp mememberlamiwe7 Sep '11 - 2:08 
Dear Wisam
the code does not work for me
I debug step by step, and startvalue and endvalue and startcolour and endcolour is OK
but on the screen , it does not change at all.
Thank you so much
AnswerRe: Help mememberdprc24 Apr '12 - 22:56 
I am facing the same problem...
GeneralMy vote of 5memberhfs200616 Jul '11 - 2:01 
im from algeria
GeneralRe: My vote of 5memberWisam E. Mohammed19 Nov '11 - 10:42 
thank you brother
Questionhow can I create contourmembertityfikir6 Apr '11 - 20:53 
Hello There I need to create contour from raster
could u help me?
QuestionNeed to color partially of selected shapememberTintinBD28 Mar '11 - 21:06 
Hi Wisam,
 
Thanks for your awesome project. I am developing a land based desktop application. Your project cover almost 90% of my need. I am stuck with one problem, i need to color the shapes in different colors for showing the status. Like 50% of a single shape will colored on green if that is crop land, 25% of that shape in red color as residential areas, 25% on blue as waterbody. I can retrieve the shape id from .dbf file, and change the whole shape color, how can i color it partially?
 
Thanks is advance.
 
Zobayer
General3d mapmemberalousahmad23 Mar '11 - 10:47 
hello sir
is there anyway to work with 3d maps other than mapwingis ocx

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 16 Jul 2009
Article Copyright 2009 by Wisam E. Mohammed
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid