Create Polyline shapefile, adding attributes issue

Hi, I am reading from a CSV file, using Lat, Long to create a line shapefile (This is done successfully), at the same time, creating fields and adding values from the CSV to the shapefile. The weird thing is that If I hard code the field index and row (or shape) index, I get that value in the shapefile attributes table. But as I pass fieldIndex, r (row index), nothing inserted. The main part of the code is here. Would anybody give me some clue? Or someone can share your code of creating a polyline shapefile and add attributes to it?

I added a test righter after I insert the value, the value is there in debugging, but the resulted attribute table didn’t have it.
object testStatic = sf.CellValue[2, 2];

I am using VS 2015 on Windows 10. MapWinGIS 5.0, doing windows form app.

Thanks a lot in advance!!

Lang

            for (int r = 1; r < lines.Length-1; r++)  //r =0 is the first line which is headers 
            {               
                string[] dataValue = lines[r].Split(',');
                string[] dataValue1 = { };

                sf.Table.EditInsertRow(ref r);
                //MessageBox.Show(dataValue[5]);
                if (r + 1 < lines.Length-1) {
                    dataValue1 = lines[r + 1].Split(',');
                }
                //char[] charsToTrim = { '*', '"', '\'' };

                for (int i = 1; i < columnCount; i++)
                {
                    //MessageBox.Show(headerLabels[i]);
                    headerLabels[i] = headerLabels[i].Replace("\"","");
                    int fieldIndex = sf.Table.get_FieldIndexByName(headerLabels[i]);

                    if (fieldIndex == -1)
                    {
                        //make IRI field a double to get ready for color-coding
                        if (headerLabels[i].Contains("IRI"))
                        {
                            fieldIndex = sf.EditAddField(headerLabels[i], FieldType.DOUBLE_FIELD, 6, 9);
                        }
                        else
                        {
                            fieldIndex = sf.EditAddField(headerLabels[i], FieldType.STRING_FIELD, 0, 30);
                        }
                    }

                    //MessageBox.Show(fieldIndex.ToString()+","+r.ToString() + ","+dataValue[i]);
                    
                    bool b = sf.EditCellValue(fieldIndex, r, dataValue[i]);
                    object test = sf.CellValue[fieldIndex, r];
                    
                    //sf.Table.EditCellValue(fieldIndex, r, dataValue[i].ToString())  
                    bool b1 = sf.EditCellValue(2, 2, dataValue[i]);
                    object testStatic = sf.CellValue[2, 2];
                   
                    sf.EditCellValue(3, 9, dataValue[i]);
                    sf.EditCellValue(4, 5, dataValue[i]);
                    Console.WriteLine($"{b} {fieldIndex} {r} {dataValue[i]} {i}");
                }
               
                Shape shp = new Shape();
                shp.Create(ShpfileType.SHP_POLYLINE);

                if (dataValue1.Length >= 4)
                {
                    x = Convert.ToDouble(dataValue[selectedIndexX]);
                    y = Convert.ToDouble(dataValue[selectedIndexY]);
                    x1 = Convert.ToDouble(dataValue1[selectedIndexX]);
                    y1 = Convert.ToDouble(dataValue1[selectedIndexY]);

                    
                    if (x.ToString() == null || y.ToString() == null)
                    {
                        MessageBox.Show("X or Y value cannot be null!");
                        return;
                    }
                    MapWinGIS.Point pnt = new MapWinGIS.Point();
                    pnt.x = x;
                    pnt.y = y;
                    int index = shp.numPoints;
                    shp.InsertPoint(pnt, ref index);

                    pnt = new MapWinGIS.Point();
                    pnt.x = x1;
                    pnt.y = y1;
                    index = shp.numPoints;
                    shp.InsertPoint(pnt, ref index);

                    index = sf.NumShapes;
                    sf.EditInsertShape(shp, ref index);
                }
            }

I can’t see anything obviously wrong in your code.
I normally start with adding the shape and then the attributes.

You ask for the cell value of the third column of the third shape (sf.CellValue[2, 2]). Are you sure you already added those shapes at that moment? You could check the NumShapes and NumFields before using CellValue.

Hi pmeems

Thank you for your kind response! I’ll take your suggestion to adding the shape first and see how it goes. when I test the value of sf.CellValue[2,2], I can see it’s there in debug. But you mean though I can see it, but since the shape many not be created yet, thus it only exits in memory during the debugging and is gone after the session, so that I don’t have it in the resulted shapefile?

This is how I would do it.
Because I don’t have your CSV-file I’m using another shpaefile to get some valid coordinates:

This is the code:

// First read some coordinates, in this case I read them from another polyline shapefile:
var sfInput = Helper.OpenShapefile(@"sf\SHP_POLYLINE.shp");
var lines = new List<List<Point>>(); // lines is a list of line and each line is a list of point
for (var i = 0; i < sfInput.NumShapes; i++)
{
    var shp = sfInput.Shape[i];
    var line = new List<Point>();
    for (var j = 0; j < shp.numPoints; j++)
    {
        line.Add(shp.Point[j]);
    }
    lines.Add(line);
}

// Create a new shapefile
var sf = new Shapefile();
Assert.IsNotNull(sf, "sf is null");
Assert.IsTrue(sf.CreateNewWithShapeID("", ShpfileType.SHP_POLYLINE), "Cannot create shapefile");

// Create fields:
var keyFieldIndex = sf.EditAddField("key", FieldType.INTEGER_FIELD, 0, 5);
var evenFieldIndex = sf.EditAddField("even", FieldType.BOOLEAN_FIELD, 0, 1);
var dateFieldIndex = sf.EditAddField("date", FieldType.DATE_FIELD, 0, 12);

// Create new lines:
foreach (var line in lines)
{
    var shp = new Shape();
    Assert.IsTrue(shp.Create(sf.ShapefileType));
    foreach (var point in line)
    {
        // Add point to shape:
        shp.AddPoint(point.x, point.y);
    }

    // Add the new shape to the shapefile:
    var shpIndex = sf.EditAddShape(shp);
    // Add some attributes:
    Assert.IsTrue(sf.EditCellValue(keyFieldIndex, shpIndex, shpIndex), "Cannot add key attribute");
    Assert.IsTrue(sf.EditCellValue(evenFieldIndex, shpIndex, shpIndex % 2 == 0), "Cannot add even attribute");
    Assert.IsTrue(sf.EditCellValue(dateFieldIndex, shpIndex, DateTime.Now), "Cannot add date attribute");
}

// Optional: Add projection:
sf.GeoProjection = sfInput.GeoProjection.Clone();

// Now the new shapefile is created, check it and save it:
Assert.IsFalse(sf.HasInvalidShapes(), "sf has invalid shapes");
var fileLocation = Path.Combine(Path.GetTempPath(), "NewShapefile.shp");
Helper.SaveAsShapefile(sf, fileLocation);

And this is the result:


The green+red dotted lines are from the new shapefile. The table editor shows the attributes of the 4 lines.

If you attach your CSV-file I can update the code to fit your needs.

These are the basic steps needed:

  1. Create a shapefile
  2. Add some fields
  3. Add 1 or more shapes in a loop
  4. Fill the attributes of that shape within that loop
  5. Save the shapefile

Dear pmeems,

Really appreciate it! You showed me a new way to do it. I’ll definitely give it a try and let you know the result.

You used Assert in your code. Will you share that function?

I tried to upload the csv, but being told that new users cannot upload attachment!! Why? So I have to copy it below for you. Or email me, so I can send it to you:
denglang36@yahoo.com. Thanks!

From (ft.) To (ft.) Distance (ft.) GPS Latitude GPS Longitude IRI Average (in/mi)
0+00.0 1+00.0 100 42.0904452 -87.71785224 303.62
1+00.0 2+00.0 100 42.09066704 -87.71763038 131.2
2+00.0 3+00.0 100 42.09086039 -87.71736568 267.52
3+00.0 4+00.0 100 42.09106414 -87.71712586 463.8
4+00.0 5+00.0 100 42.09129138 -87.7169103 234.07
5+00.0 6+00.0 100 42.09150166 -87.71666953 306.37
6+00.0 7+00.0 100 42.09171606 -87.71644683 211.32
7+00.0 8+00.0 100 42.0919315 -87.71621995 326.62
8+00.0 9+00.0 100 42.0921311 -87.71596777 395.28
9+00.0 10+00.0 100 42.09233814 -87.71572284 424.08
10+00.0 11+00.0 100 42.09256371 -87.71550879 386.68
11+00.0 12+00.0 100 42.09278509 -87.71528592 250.14
12+00.0 13+00.0 100 42.09297916 -87.7150244 342.5
13+00.0 14+00.0 100 42.09285975 -87.71470643 344.36
14+00.0 15+00.0 100 42.09270548 -87.71439969 181.8
15+00.0 16+00.0 100 42.09249977 -87.71414631 174.16
16+00.0 17+00.0 100 42.0923244 -87.71385283 350.38
17+00.0 18+00.0 100 42.09216728 -87.71355021 213.26
18+00.0 18+46.3 46.3 42.09197615 -87.71328179 280.86

Lang

Hi pmeems,

Problem solved! You are exactly correct: when I write the attributes, the shapes are not created yet! So I just create the shapes before editing attributes and everything works now. Thank you so much!
Also, I see you opened a table for editing shapefile? Will you share code for that?
Plus, how do you do identify? I am using editing table in lieu of identify now.

Lang

Assert is just a default C# method to use in unit tests.

The screenshots I made using MapWindow5 (MW5).
This is the desktop GIS that uses MapWinGIS as the mapping engine.

If you need a full working GIS it might be easier to create a plug-in for MW5 and just build your specific code and reuse everything else from MW5.
We have a template plug-in written in C# to help you get started.

Hi Pmeems,

Would you please try to use the csv I gave you to create a polyline shapefile? I just figured that the attributes are added correctly but I don’t see any shape. will you try to see if you can create a polyline shapefile? Thanks a lot in advance!

Lang

I’ve sent you an e-mail requesting for the CSV-file because the one in the post is unclear to me.
Is every line a point of the polyline and do you expect just 1 polyline?

When you zip your csv you should be able to attach it to your post.