Preface
This lesson is part 4 of a series of lessons aimed to show the capabilities of MapWinGIS.ocx to develop Windows-based desktop GIS standalone applications using C#. If you are reading about MapWinGIS.ocx the first time, I strongly recommend reading the previous three articles before. These articles are available here: Part 1, Part 2, and Part 3.
Introduction
Many GIS specialists believe that data creation is one of the most important GIS activities. GIS data may be created in different ways, it may draw directly or be imported from secondary sources. In this article, I am going to discuss how to manage data creation using MapWinGIS.ocx and C#. I am using .NET Framework 3.5 and Microsoft Visual Studio 2008 Professional Edition. Actually, you can use Visual Studio Express Edition without any problems. Also, you have to install MapWinGIS.ocx in your machine. Finally, the data used in this article is attached as a zipped file.
Objective
The objective of the following program is to create a point shape file using secondary data stored in comma separated values in *.csv text format. A CSV file is a specially formatted plain text file which stores table-style information in a very simple format, with one record on each line, and each field within that record separated by a comma. In this tutorial, a series of locations were stored in a CSV file named road.csv. Each location was described using three parameters. The first parameter is the ID which is the integer index. The second and third parameters are the location coordinates in a Universal Transverse Mercator metric coordinate format. The following figure shows the contents of the road.csv file shown in Notepad++ software.
I have to mention here that many data gathering devices such as GPS and echo sounders can export gathered data. For instance, NMEA 0183 files that download from GPS devices is some kind of CSV file format.
Methodology
Three main problems should be considered by the programmer when working on CSV to shape file conversion software. These problems are how to create a new shape file, how to read CSV file contents and parse it properly, and finally, how to create the shapes and add it to the shape file. The following figure shows a detailed methodology to convert a CSV file to a shape file.
The first step is to create a new shape file instance using the MapWinGIS API. The second step is to add a new index field for the new shape file table. It is recommended to add at least one field to the shape file in the creation phase. In this example, the index field will be the integer data type. These steps represent the first task to be considered by the developer, which is the shape file creation task. After finishing this task, we have an empty shape file. If we terminate the program at this point, we will lose the shape file, because it is empty. The shape file should include some shapes to be a real shape file, and has a location and size on the storage media. Before adding the shapes for the shape file, we have to create these shapes using data provided by the CSV file. So, the next task is to open the CSV file and read its contents. The third step is to open the CSV file. This is a very easy step because, this file is a text file. Reading the CSV file contents line by line and analyzing the line to extract the ID, x, and y data is the fourth step. Analyzing the CSV line is done using secondary subroutines. These subroutines introduce the fourth step. The fifth step is to create the shapes using the MapWinGIS API. After creating the shapes, the shapes should be added to the shape file, which is the sixth step. Steps from four to six will repeated while the CSV file still has rows to read. The final step is to save the shape file.
Time to write some code
I think we have a complete road map to develop a simple software to convert a CSV file to an ESRI shape file. So, let's write some funny code. In this tutorial, we will use a console application template. Start your Visual Studio and create a new Console Application project. We need to add a reference to MapWinGIS. You can get a detailed description of how to add this reference for your project in the first tutorial in this series. Before writing the core of our code - the CSV to shape file conversion code - we have to develop a simple code to parse the CSV file contents. The following code box shows three static methods: GetIndex
, GetX
, and GetY
, where each method receives a CSV raw and returns a specific component from this raw (Index, X, Y field values).
private static double GetY(string sentence)
{
string strY = sentence.Substring(sentence.LastIndexOf(";") + 1);
double result = Convert.ToDouble(strY);
return result;
}
private static double GetX(string sentence)
{
string strNewSentense = sentence.Substring(sentence.IndexOf(";")+1);
string strX = strNewSentense.Substring(0, strNewSentense.IndexOf(";"));
double result = Convert.ToDouble(strX);
return result;
}
private static Int16 GetIndex(string sentence)
{
string strId = sentence.Substring(0, sentence.IndexOf(";"));
Int16 result = Convert.ToInt16(strId);
return result;
}
Back to the main method for the console project, where we will write the core code. In the first line, add the code required to create a new instance (myShapefile
) for the Shapefile
class. In the second line, use the method CreateNew
to create a new physical shape file by assigning its full path and its geometry type. The geometry type for the shape file is defined by the ShapefileType
enumerator. This enumerator can define 14 geometry types. The most common geometry types provided by this enumerator are SHP_POINT
, SHP_POLYLINE
, and SHP_POLYGON
for the point, polyline, and polygon geometry types. It is strongly recommended to add a new field for your shape file table when you do new shape file creation, regardless of whether you add values for this field cells or not.
The third line shows how to create a new instance (myField
) for the MapWinGIS.Filed
class. The following three lines show how to set the field properties. There are many available field properties, but the common properties are those three. The first property is Name
, which is a string and is assigned as the name of a new field. You have to note that; the Shapefile format use the old format *.dbf to store attributes; you have to consider all the restrictions of file naming in your work. This means, the name string should be less than 12 letters, and not include special characters or spaces. The second property is Type
, which defines the data type that can be stores in this new field. MapWinGIS provides an enumerator (FieldType
) that includes all the available data types that may be accepted by the Field
class. This enumerator provides DOUBLE_FIELD
, INTEGER_FIELD
, and STRING_FIELD
for double precision, integer, and string data, respectively. The third property is the Width
. This property defines the width (how many letters or digits) for the field. Integer values only set to this property. Finally, we have to add this new field for the table. The method EditInsertField
of the instance myShapefile
is used to add the new field for the table. You have to note this: using this method requires you to set the value of the table object EditTable
property to be true
. Fortunately, when we use the CreateNew
method, both the EditTable
and EditShape
properties are automatically set to true
.
Shapefile myShapefile = new Shapefile();
myShapefile.CreateNew(@"D:\GISLesson04\road.shp", ShpfileType.SHP_POINT);
MapWinGIS.Field myField = new Field();
myField.Name = "ID";
myField.Type = FieldType.INTEGER_FIELD;
myField.Width = 10;
int intFieldIndex = 0;
myShapefile.EditInsertField(myField, ref intFieldIndex, null);
Now we have a new shape file with a single field table ready to use. If we finish the application in this situation, MapWinGIS will delete the shape file physically because there is no meaning for a shapeless shape file. You have to add at least one shape file to be accepted by MapWinGIS
to save this new shape file. However, we have a CSV file full of data needed for the drawing and that what we will do in the following section. To read the contents of the CSV file - remember, a CSV file is a text file - we use the StreamReader
instance (myFile
), and then we can use this as a stream reader instance to read the contents of the CSV file line by line using a while
loop. This loop will stop when it arrives at the end of the CSV file. Within the while
block, with each loop, we will create a new instance (myShape
) of the Shape
class. The Shape
class defines the shapes inside the shape file. Each Shape
includes one or more points. This new instance should be created using the method Create
for the instance myShape
. This method requires an argument that defines the geometry of the shape. This geometry is provided by the enumerator ShapefileType
which was mentioned before. After creating the Shape
instance myShape
, we have to draw it - or define it spatially - using the point data in the CSV file. To do that, we have to create a new instance for the Point
class called myPoint
. This instance has two properties (x, y) which define the location of the point. Now is the time when the parsing methods designed before will be useful. We will use the GetX
and GetY
methods to get the x and y value from the CSV line, and set these values to the myPoint
(x ,y) properties. After creating the point, we will add it to the Shape
instance (myShape
) using the method InsertPoint
. Then, we will add this shape to the shape file instance (myShapefile
) using the method EditInsertShape
.
System.IO.StreamReader myFile =
new System.IO.StreamReader(@"D:\GISLesson04\road.csv");
while ((myLine = myFile.ReadLine()) != null)
{
if (myCounter > 0)
{
MapWinGIS.Shape myShape = new Shape();
myShape.Create(ShpfileType.SHP_POINT);
MapWinGIS.Point myPoint = new Point();
myPoint.x = GetX(myLine);
myPoint.y = GetY(myLine);
int myPointIndex = 0;
myShape.InsertPoint(myPoint, ref myPointIndex);
myShapefile.EditInsertShape(myShape, ref myShapeIndex);
myShapeIndex++;
}
myCounter++;
}
When the while
loop reaches the end of the CSV file, every line in the CSV file will match a point in the shape file. The final step is to stop editing the shape file. To do that, we have to use the method StopEditingShapes
of the myShapefile
instance. Now, you can display your new shape file using any GIS software. You may display it using the MapWinGIS application as we did before in the early lessons. For me, I will display the shape file in MapWindows GIS, which is the Open Source desktop GIS application for Microsoft Windows built completely on MapWinGIS.