Append to an existing shapefile

Topics: Algorithms, Data Access, General Topics, SharpMap Project
Feb 8, 2011 at 8:13 PM

HI All,

I am attempting to add new features to an existing shapefile and have come up with the "solution" below.

I'm not entirely happy with it because it involves copying all of the geometry and attributes from the original

shapefile into a feature collection, then adding to that collection and writing everything out again.  I realize

this isn't necessarily an ideal approach and am hoping someone has some ideas on how to just append

a new feature to an existing shapefile.

Thanks!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.IO;
using GisSharpBlog.NetTopologySuite.IO;
using GisSharpBlog.NetTopologySuite.Geometries;
using GisSharpBlog.NetTopologySuite.Features;
using GeoAPI.Geometries;

namespace AddToShapefile
{
    class Program
    {
        static void Main(string[] args)
        {
            ArrayList featureCollection = new ArrayList();
            string filename = @"D:\NSDFA_Temperature\NSDFAPoints_T";
            if (!File.Exists(filename + ".dbf"))
                throw new FileNotFoundException(filename + " not found at " + Environment.CurrentDirectory);
            ShapefileDataReader dataReader = new ShapefileDataReader(filename, new GeometryFactory());
            while (dataReader.Read())
            {
                Feature feature = new Feature();
                feature.Geometry = dataReader.Geometry;
                int length = dataReader.DbaseHeader.NumFields;
                string[] keys = new string[length];
                for (int i = 0; i < length; i++)
                    keys[i] = dataReader.DbaseHeader.Fields[i].Name;

                feature.Attributes = new AttributesTable();
                for (int i = 0; i < length; i++)
                {
                    object val = dataReader.GetValue(i);
                    feature.Attributes.AddAttribute(keys[i], val);
                }

                featureCollection.Add(feature);
            }

            IGeometryFactory Factory = new GeometryFactory();
            IPoint pntNew = Factory.CreatePoint(new Coordinate(100, 50));

            AttributesTable attributes = new AttributesTable();
            attributes.AddAttribute("SerialNo", args[1].Replace(",", ""));
            attributes.AddAttribute("TableName", args[2].Replace(",", ""));
            attributes.AddAttribute("Instrument", args[3].Replace(",", ""));
            Feature fNew = new Feature(pntNew, attributes);

            dataReader.Close();
            dataReader.Dispose();
            dataReader = null;

            // Write shapefile with stub header           
            string file = @"D:\NSDFA_Temperature\NSDFAPoints_T";
            ShapefileDataWriter dataWriter = new ShapefileDataWriter(file);
            dataWriter.Header = ShapefileDataWriter.GetHeader(featureCollection[0] as Feature, featureCollection.Count);
            dataWriter.Write(featureCollection);
            Console.WriteLine("Shapefile has been updated!");
        }
    }
}

Feb 10, 2011 at 5:44 PM

Below is another approach that I've tried.  The code below runs fine, adds a row to the DataTable,

but does not write out the new row to the shapefile.  I've also tried the two lines that I have commented

out.  Is there a way to write out the datatable, or "reapply" it to the orginal shapefile? 

 

Does anyone have any suggestions?  Hope someone can help

 

Thank You

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.IO;
using SharpMap.Layers;
using SharpMap.Data.Providers;
using SharpMap.Data;
using SharpMap.Geometries;

namespace AddToShapefile
{
    class Program
    {
        static void Main(string[] args)
        {
            SharpMap.Data.Providers.ShapeFile shp = new SharpMap.Data.Providers.ShapeFile("D:\\NSDFA_Temperature\\TestPnts.shp", true);
            shp.Open();
            FeatureDataSet fDS = new FeatureDataSet();
            shp.ExecuteIntersectionQuery(shp.GetExtents(), fDS);
            FeatureDataTable fDt = fDS.Tables[0];
            FeatureDataRow fDr = fDt.NewRow();
            fDr.Geometry = new SharpMap.Geometries.Point(100, 50);
            fDt.AddRow(fDr);
            fDt.AcceptChanges();
            //fDS.RemoveAt(0);
            //fDS.Add(fDt);
            fDS.AcceptChanges();
            shp.Close();
        }
    }
}

Coordinator
Feb 11, 2011 at 7:32 AM

The shapefile provider for sharpmap v0.9 is read-only.

If you need a writeable shapefile provider, you need to use sharpmap v2. It is hosted at http://code.google.com/p/sharpmapv2

Hth FObermaier

Feb 11, 2011 at 3:49 PM

That does help - thank you.  I'm afraid I could use a little bit of direction though on SharpMap v2 .

I can see where  under the source tab at http://code.google.com/p/sharpmapv2  there is mention of non-members.

and that a read-only version can be retrieved.  I have done this, but am wondering where to go next.

These may be silly questions, but do I need to compile the source to generate a new "SharpMap.dll" or is there

one already available that can be downloaded by members.   How does one become a member or is

it referring to being a member of google?  Is it possible to compile the application with C# Express or is a full

license of Visual Studio required?

 

Thanks for your patience!

Carl

Coordinator
Feb 14, 2011 at 7:44 AM

Carl, you need to compile the source yourself.

Unfortunately, the project is setup in a way, that requires more than the express versions of visual studio.

To get the shapefile provider going, you can setup your own solution file: I think all you need are:

GeoAPI, NetTopologySuite, NPack, SharpMap and SharpMap.Data.Providers.ShapeFile

Hth FObermaier