Select to view content in your preferred language

Load an ESRI Shape File

2426
15
05-13-2011 10:48 AM
MichaelAquilina
Emerging Contributor
Hey guys, i was wondering if the ArcGIS library for WPF contains a method or class for loading and saving Shape file information.

I am aware that the format for a shape file is documented, so i could implement it myself if needed; but if the method is readily available there would be no need for this.
0 Kudos
15 Replies
IgressT
Emerging Contributor
If you can... please send me a copy at

harry.wills@gmail.com
0 Kudos
ErikEngstrom
Frequent Contributor
Nevermind... I was able to get the api sample to work correctly.
I needed to repair the assemblies and download the Reactive package from Microsoft. I seemed to get it working this way. I then added the SLContrib project to my site and added the code from the Contrib website. Worked perfectly... I just need to tweak it a bit to account for the differences in projections between the shapefiles we manage and the web mercator projection our web applications use.
0 Kudos
weiliang
Deactivated User
Could you send your code to me, Michael? I'd like to see how you implement it. My email is lwconquer@gmail.com .

Many thanks,

Wei
0 Kudos
MargoBlosser
Deactivated User
Michael,

Rectifying assemblies- yuck! I sure would appreciate getting a copy of your code snippet for loading a shape file.

Best Regards,

Margo
mblosser@gorgegis.com
0 Kudos
MichaelAquilina
Emerging Contributor
Wow, didnt realise there was such a demand for the code!

Here it is guys, enjoy!

public enum ShapeType
    {
        NullShape,
        Point, PolyLine, Polygon, MultiPoint,
        PointZ, PolyLineZ, PolygonZ, MultiPointZ,
        PointM, PolyLineM, PolygonM, MultiPointM,
        MultiPatch,
        Unknown
    };

    public class ShapeFile
    {
        public static ShapeType[] SupportedShapes = new ShapeType[] { ShapeType.PolyLine, ShapeType.Point };

        public ShapeType ShapeType;
        public int FileLength;
        public int Version;
        public int FileCode;

        public BoundingBox Boundary;

        public List<VectorShape> Data = new List<VectorShape>();

        public void Read(String ShapeFile )
        {
            FileStream Stream = new FileStream(ShapeFile, FileMode.Open);
            BinaryReader Reader = new BinaryReader(Stream);

            FileCode = (int) ReverseBytes((UInt32)Reader.ReadInt32());

            if (FileCode != 9994)
                throw new IOException("The Input file specified is not a valid Shape File (Invalid FileCode)");

            //read empty bytes found in the file
            Reader.ReadBytes(20);

            FileLength = (int) ReverseBytes((UInt32)Reader.ReadInt32());
            Version = Reader.ReadInt32();
            ShapeType =  GetShapeType(Reader.ReadInt32());

            if (ShapeType == ShapeType.Unknown)
                throw new IOException("The Input file has an unknown Shape Type Specified");

            if (!SupportedShapes.Contains(ShapeType))
                throw new IOException("The Input file has a shape type that is not suppored (" + ShapeType + ")\n" +
                                      "The Following types are supported:\n" +
                                      SupportedShapes);

            Boundary = new BoundingBox();
            Boundary.XMin = Reader.ReadDouble();
            Boundary.YMin = Reader.ReadDouble();
            Boundary.XMax = Reader.ReadDouble();
            Boundary.YMax = Reader.ReadDouble();
            Boundary.ZMin = Reader.ReadDouble();
            Boundary.ZMax = Reader.ReadDouble();
            Boundary.MMin = Reader.ReadDouble();
            Boundary.MMax = Reader.ReadDouble();

            while (Stream.Position < FileLength)
            {
                int RecordNumber = (int)ReverseBytes((UInt32)Reader.ReadInt32());
                int ContentLength = (int)ReverseBytes((UInt32)Reader.ReadInt32());
                ShapeType RecordShapeType = GetShapeType( Reader.ReadInt32() );

                switch( RecordShapeType )
                {
                    case ShapeType.Point: Data.Add(ReadPoint(Reader)); break;
                    case ShapeType.PolyLine: Data.Add(ReadPolyLine(Reader)); break;
                }
            }

            Stream.Close();
        }

        public void Write(String ShapeFile)
        {
            FileStream Stream = new FileStream(ShapeFile, FileMode.Create);
            BinaryWriter Writer = new BinaryWriter(Stream);

            Writer.Write( ReverseBytes(9994) );     //filecode
            Writer.Seek(28, 0);                     //file length
            Writer.Write( (int) 1000);              //Version
            Writer.Write(GetShapeCode(ShapeType));
            Writer.Write(Boundary.XMin);
            Writer.Write(Boundary.YMin);
            Writer.Write(Boundary.XMax);
            Writer.Write(Boundary.YMax);
            Writer.Write(Boundary.ZMin);
            Writer.Write(Boundary.ZMax);
            Writer.Write(Boundary.MMin);
            Writer.Write(Boundary.MMax);

            for (int i = 0; i < Data.Count; i++)
            {
                Writer.Write((int)ReverseBytes((UInt32)i));
                Writer.Write((int)ReverseBytes((UInt32)Data.SizeOf()));       //content length

                if (Data is PolyLine)
                {
                    Writer.Write(GetShapeCode(ShapeType.PolyLine));
                    WritePolyline(Writer, (PolyLine) Data );
                }

                if (Data is Point )
                {
                    Writer.Write(GetShapeCode(ShapeType.Point));
                    WritePoint(Writer, (Point) Data );
                }
            }

            int FileLength = (int) Stream.Position;
            Writer.Seek(24,0);
            Writer.Write((int)ReverseBytes((UInt32)FileLength));

            Stream.Close();
        }

        private void WritePoint(BinaryWriter Writer, Point Point)
        {
            Writer.Write(Point.X);
            Writer.Write(Point.Y);
        }

        private Point ReadPoint(BinaryReader Reader)
        {
            Point Point = new Point();
            Point.X = Reader.ReadDouble();
            Point.Y = Reader.ReadDouble();

            return Point;
        }

        private void WritePolyline(BinaryWriter Writer, PolyLine PolyLine)
        {
            Writer.Write(PolyLine.XMin);
            Writer.Write(PolyLine.YMin);
            Writer.Write(PolyLine.XMax);
            Writer.Write(PolyLine.YMax);

            Writer.Write(PolyLine.NumParts);
            Writer.Write(PolyLine.NumPoints);
            for (int i = 0; i < PolyLine.NumParts; i++ )
                Writer.Write( PolyLine.Parts );

            for (int i = 0; i < PolyLine.NumPoints; i++)
                WritePoint(Writer, PolyLine.Points);
        }

        private PolyLine ReadPolyLine(BinaryReader Reader)
        {
            PolyLine Output = new PolyLine();
            Output.XMin = Reader.ReadDouble();
            Output.YMin = Reader.ReadDouble();
            Output.XMax = Reader.ReadDouble();
            Output.YMax = Reader.ReadDouble();

            Output.NumParts = Reader.ReadInt32();
            Output.NumPoints = Reader.ReadInt32();
            Output.Parts = new int[Output.NumParts];
            Output.Points = new Point[Output.NumPoints];

            for (int i = 0; i < Output.Parts.Length; i++)
                Output.Parts = Reader.ReadInt32();

            for (int i = 0; i < Output.Points.Length; i++)
                Output.Points = ReadPoint(Reader);

            return Output;
        }

        public static UInt32 ReverseBytes(UInt32 value)
        {
            return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 |
                   (value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24;
        }

        public static int GetShapeCode(ShapeType Type)
        {
            switch (Type)
            {
                case ShapeType.NullShape : return 0;
                case ShapeType.Point: return 1;
                case ShapeType.PolyLine : return 3;
                case ShapeType.Polygon: return 5;
                case ShapeType.MultiPoint: return 8;
                case ShapeType.PointZ: return 11;
                case ShapeType.PolyLineZ: return 13;
                case ShapeType.PolygonZ: return 15;
                case ShapeType.MultiPointZ: return 18;
                case ShapeType.PointM: return 21;
                case ShapeType.PolyLineM : return 23;
                case ShapeType.PolygonM : return 25;
                case ShapeType.MultiPointM: return 28;
                case ShapeType.MultiPatch: return 31;
                default :return -1;
            }
        }

        public static ShapeType GetShapeType(int Code)
        {
            switch (Code)
            {
                case 0: return ShapeType.NullShape;
                case 1: return ShapeType.Point;
                case 3: return ShapeType.PolyLine;
                case 5: return ShapeType.Polygon;
                case 8: return ShapeType.MultiPoint;
                case 11: return ShapeType.PointZ;
                case 13: return ShapeType.PolyLineZ;
                case 15: return ShapeType.PolygonZ;
                case 18: return ShapeType.MultiPointZ;
                case 21: return ShapeType.PointM;
                case 23: return ShapeType.PolyLineM;
                case 25: return ShapeType.PolygonM;
                case 28: return ShapeType.MultiPointM;
                case 31: return ShapeType.MultiPatch;
                default: return ShapeType.Unknown;
            }
        }
0 Kudos
AzharIbrahim
Occasional Contributor
I took too much time trying to find the assembly so i decided to implement a method for reading and writing shape files myself.....was surprisingly easy! If anyone wishes some simple code snippets for help just ask 🙂

Thanks for the help!


Could you please send me some code snippets?
0 Kudos