Ejemplo n.º 1
0
        /// <summary>
        /// Opens a shapefile
        /// </summary>
        /// <param name="fileName">The string fileName of the point shapefile to load</param>
        /// <param name="progressHandler">Any valid implementation of the DotSpatial.Data.IProgressHandler</param>
        public void Open(string fileName, IProgressHandler progressHandler)
        {
            //JK - handle case when filename doesn't exist
            if (!File.Exists(fileName))
            {
                Attributes = new AttributeTable();
                Header = new ShapefileHeader { FileLength = 100, ShapeType = ShapeType.Point };
                FeatureType = FeatureType.Point;
                return;
            }

            IndexMode = true;
            Filename = fileName;

            Header = new ShapefileHeader(fileName);
            CoordinateType = CoordinateType.Regular;
            if (Header.ShapeType == ShapeType.PointM)
            {
                CoordinateType = CoordinateType.M;
            }
            if (Header.ShapeType == ShapeType.PointZ)
            {
                CoordinateType = CoordinateType.Z;
            }
            MyExtent = Header.ToExtent();
            Name = Path.GetFileNameWithoutExtension(fileName);
            Attributes.Open(fileName);
            FillPoints(fileName, progressHandler);
            ReadProjection();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Opens a shapefile
        /// </summary>
        /// <param name="fileName">The string fileName of the line shapefile to load</param>
        /// <param name="progressHandler">Any valid implementation of the DotSpatial.Data.IProgressHandler</param>
        public void Open(string fileName, IProgressHandler progressHandler)
        {
            if (!File.Exists(fileName)) return;

            Filename = fileName;
            IndexMode = true;
            Header = new ShapefileHeader(fileName);

            switch (Header.ShapeType)
            {
                case ShapeType.PolyLineM:
                    CoordinateType = CoordinateType.M;
                    break;
                case ShapeType.PolyLineZ:
                    CoordinateType = CoordinateType.Z;
                    break;
                default:
                    CoordinateType = CoordinateType.Regular;
                    break;
            }

            Extent = Header.ToExtent();
            Name = Path.GetFileNameWithoutExtension(fileName);
            Attributes.Open(fileName);

            FillLines(fileName, progressHandler, this, FeatureType.Line);
            ReadProjection();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Opens a shapefile
        /// </summary>
        /// <param name="fileName">The string fileName of the line shapefile to load</param>
        /// <param name="progressHandler">Any valid implementation of the DotSpatial.Data.IProgressHandler</param>
        public void Open(string fileName, IProgressHandler progressHandler)
        {
            if (!File.Exists(fileName))
            {
                Attributes = new AttributeTable();
                Header = new ShapefileHeader { FileLength = 100, ShapeType = ShapeType.PolyLine };
                FeatureType = FeatureType.Line;
                return;
            }

            Filename = fileName;
            FeatureType = FeatureType.Line;
            Header = new ShapefileHeader(fileName);
            CoordinateType = CoordinateType.Regular;
            IndexMode = true;
            if (Header.ShapeType == ShapeType.PolyLineM)
            {
                CoordinateType = CoordinateType.M;
            }
            if (Header.ShapeType == ShapeType.PolyLineZ)
            {
                CoordinateType = CoordinateType.Z;
            }
            MyExtent = Header.ToExtent();
            Name = Path.GetFileNameWithoutExtension(fileName);
            Attributes.Open(fileName);
            FillLines(fileName, progressHandler);
            ReadProjection();
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Creates a new instance of a shapefile based on a fileName
 /// </summary>
 /// <param name="fileName">File name</param>
 /// <param name="featureType">Feature type</param>
 protected Shapefile(string fileName, FeatureType featureType)
     : base(featureType)
 {
     Attributes = new AttributeTable();
     Header = new ShapefileHeader();
     
     Open(fileName, null);
 }
        /// <inheritdocs/>
        protected override void AppendBasicGeometry(ShapefileHeader header, IBasicGeometry feature, int numFeatures)
        {
            FileInfo fi = new FileInfo(Filename);
            int offset = Convert.ToInt32(fi.Length / 2);

            FileStream shpStream = new FileStream(Filename, FileMode.Append, FileAccess.Write, FileShare.None, 10000);
            FileStream shxStream = new FileStream(header.ShxFilename, FileMode.Append, FileAccess.Write, FileShare.None, 100);

            Coordinate point = feature.Coordinates[0];
            int contentLength = 6;
            if (header.ShapeType == ShapeType.PointM)
            {
                contentLength += 4; // one additional value (m)
            }
            if (header.ShapeType == ShapeType.PointZ)
            {
                contentLength += 8; // 2 additional values (m, z)
            }

            //                                              Index File
            //                                              ---------------------------------------------------------
            //                                              Position     Value               Type        Number      Byte Order
            //                                              ---------------------------------------------------------
            shxStream.WriteBe(offset);                      // Byte 0     Offset             Integer     1           Big
            shxStream.WriteBe(contentLength);               // Byte 4    Content Length      Integer     1           Big
            shxStream.Flush();
            shxStream.Close();
            //                                              X Y Points
            //                                              ---------------------------------------------------------
            //                                              Position     Value               Type        Number      Byte Order
            //                                              ---------------------------------------------------------
            shpStream.WriteBe(numFeatures);                 // Byte 0       Record Number       Integer     1           Big
            shpStream.WriteBe(contentLength);               // Byte 4       Content Length      Integer     1           Big
            shpStream.WriteLe((int)header.ShapeType);       // Byte 8       Shape Type 3        Integer     1           Little
            if (header.ShapeType == ShapeType.NullShape)
            {
                return;
            }

            shpStream.WriteLe(point.X);             // Byte 12      X                   Double      1           Little
            shpStream.WriteLe(point.Y);             // Byte 20      Y                   Double      1           Little

            if (header.ShapeType == ShapeType.PointM)
            {
                shpStream.WriteLe(point.M);                            // Byte 28      M                   Double      1           Little
            }
            else if (header.ShapeType == ShapeType.PointZ)
            {
                shpStream.WriteLe(point.Z);                            // Byte 28      Z                   Double      1           Little
                shpStream.WriteLe(point.M);                            // Byte 36      M                   Double      1           Little
            }
            shpStream.Flush();
            shpStream.Close();
            offset += contentLength;
            Shapefile.WriteFileLength(Filename, offset);
            Shapefile.WriteFileLength(header.ShxFilename, 50 + numFeatures * 4);
        }
        /// <inheritdocs/>
        protected override Shape GetShapeAtIndex(FileStream fs, ShapefileIndexFile shx, ShapefileHeader header, int shp, IEnvelope envelope)
        {
            // Read from the index file because some deleted records
            // might still exist in the .shp file.
            long offset = (shx.Shapes[shp].ByteOffset);
            fs.Seek(offset, SeekOrigin.Begin);
            Shape myShape = new Shape();
            // Position     Value               Type        Number      Byte Order
            ShapeRange shape = new ShapeRange(FeatureType.Point); //--------------------------------------------------------------------
            shape.RecordNumber = fs.ReadInt32(Endian.BigEndian);     // Byte 0       Record Number       Integer     1           Big
            shape.ContentLength = fs.ReadInt32(Endian.BigEndian);    // Byte 4       Content Length      Integer     1           Big
            ShapeType shapeType = (ShapeType)fs.ReadInt32(); // Byte 8       Shape Type          Integer     1           Little
            if (shapeType == ShapeType.NullShape)
            {
                return null;
            }
            double[] vertices = fs.ReadDouble(2);
            double x = vertices[0], y = vertices[1];
            // Don't add this shape to the result
            if (envelope != null)
            {
                if (!envelope.Contains(new Coordinate(x, y)))
                {
                    return null;
                }
            }

            shape.StartIndex = 0;
            shape.NumParts = 1;
            shape.NumPoints = 1;
            shape.ShapeType = shapeType;
            shape.Extent = new Extent(x, y, x, y);
            myShape.Range = shape;
            myShape.Vertices = vertices;

            if (header.ShapeType == ShapeType.PointM)
            {
                myShape.M = fs.ReadDouble(1);
                myShape.MinM = myShape.MaxM = myShape.M[0];
                shape.Extent = new ExtentM(shape.Extent, myShape.MinM, myShape.MaxM);
            }
            else if (header.ShapeType == ShapeType.PointZ)
            {
                // For Z shapefiles, the Z part is not optional.
                myShape.Z = fs.ReadDouble(1);
                myShape.MinZ = myShape.MaxZ = myShape.Z[0];
                myShape.M = fs.ReadDouble(1);
                myShape.MinM = myShape.MaxM = myShape.M[0];
                shape.Extent = new ExtentMZ(shape.Extent.MinX, shape.Extent.MinY, myShape.MinM, myShape.MinZ, shape.Extent.MaxX, shape.Extent.MaxY, myShape.MaxM, myShape.MaxZ);
            }

            PartRange partR = new PartRange(myShape.Vertices, 0, 0, FeatureType.Point) { NumVertices = 1 };
            shape.Parts.Add(partR);
            myShape.Range = shape;

            return myShape;
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Creates a new instance of a PolygonShapefile for in-ram handling only.
 /// </summary>
 public PolygonShapefile()
     : base(FeatureType.Polygon)
 {
     Attributes = new AttributeTable();
     Header = new ShapefileHeader();
     Header.FileLength = 100;
     Header.ShapeType = ShapeType.Polygon;
     FeatureType = FeatureType.Polygon;
 }
Ejemplo n.º 8
0
 /// <summary>
 /// Creates a new ShapefileReader tailored to read a particular file.
 /// </summary>
 /// <param name="filename"></param>
 /// <returns></returns>
 public ShapefileReader(string filename)
 {
     Filename = filename;
     _attributeTable = new AttributeTable(filename);
     ShapefileHeader header = new ShapefileHeader(filename);
     //if (header.ShapeType == ShapeType.Polygon ||
     //    header.ShapeType == ShapeType.PolygonM ||
     //    header.ShapeType == ShapeType.PolygonZ)
     //{
     //    _shapeSource = new PolygonShapefileShapeSource(filename);
     //}
     // To Do: Implement alternate shape sources here.
     _fieldCount = -1;
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Opens a shapefile
 /// </summary>
 /// <param name="fileName">The string fileName of the point shapefile to load</param>
 /// <param name="progressHandler">Any valid implementation of the DotSpatial.Data.IProgressHandler</param>
 public void Open(string fileName, IProgressHandler progressHandler)
 {
     IndexMode = true;
     Filename = fileName;
     FeatureType = FeatureType.MultiPoint;
     Header = new ShapefileHeader(fileName);
     CoordinateType = CoordinateType.Regular;
     if (Header.ShapeType == ShapeType.MultiPointM)
     {
         CoordinateType = CoordinateType.M;
     }
     if (Header.ShapeType == ShapeType.MultiPointZ)
     {
         CoordinateType = CoordinateType.Z;
     }
     Name = Path.GetFileNameWithoutExtension(fileName);
     Attributes.Open(fileName);
     FillPoints(fileName, progressHandler);
     ReadProjection();
 }
Ejemplo n.º 10
0
 /// <summary>
 /// This tests the specified file in order to determine what type of vector the file contains.
 /// This returns unspecified if the file format is not supported by this provider.
 /// </summary>
 /// <param name="fileName">The string fileName to test</param>
 /// <returns>A FeatureType clarifying what sort of features are stored on the data type.</returns>
 public virtual FeatureType GetFeatureType(string fileName)
 {
     ShapefileHeader sh = new ShapefileHeader(fileName);
     if (sh.ShapeType == ShapeType.Polygon || sh.ShapeType == ShapeType.PolygonM || sh.ShapeType == ShapeType.PolygonZ)
     {
         return FeatureType.Polygon;
     }
     if (sh.ShapeType == ShapeType.PolyLine || sh.ShapeType == ShapeType.PolyLineM || sh.ShapeType == ShapeType.PolyLineZ)
     {
         return FeatureType.Line;
     }
     if (sh.ShapeType == ShapeType.Point || sh.ShapeType == ShapeType.PointM || sh.ShapeType == ShapeType.PointZ)
     {
         return FeatureType.Point;
     }
     if (sh.ShapeType == ShapeType.MultiPoint || sh.ShapeType == ShapeType.MultiPointM || sh.ShapeType == ShapeType.MultiPointZ)
     {
         return FeatureType.MultiPoint;
     }
     return FeatureType.Unspecified;
 }
Ejemplo n.º 11
0
        /// <summary>
        /// Opens a shapefile
        /// </summary>
        /// <param name="fileName">The string fileName of the polygon shapefile to load</param>
        /// <param name="progressHandler">Any valid implementation of the DotSpatial.Data.IProgressHandler</param>
        public void Open(string fileName, IProgressHandler progressHandler)
        {
            //JK - handle case when filename doesn't exist
            if (!File.Exists(fileName)) return;

            IndexMode = true;
            Filename = fileName;
            Header = new ShapefileHeader(fileName);
            CoordinateType = CoordinateType.Regular;
            if (Header.ShapeType == ShapeType.PolygonM)
            {
                CoordinateType = CoordinateType.M;
            }
            if (Header.ShapeType == ShapeType.PolygonZ)
            {
                CoordinateType = CoordinateType.Z;
            }
            Name = Path.GetFileNameWithoutExtension(fileName);
            Attributes.Open(fileName);

            FillPolygons(fileName, progressHandler);
            ReadProjection();
        }
Ejemplo n.º 12
0
        /// <inheritdocs/>
        public void RemoveAt(int index)
        {
            // Get shape range so we can update header smartly
            int         startIndex = index;
            IFeatureSet ifs        = Select(null, null, ref startIndex, 1);

            if (ifs.NumRows() > 0)
            {
                var shx = new ShapefileIndexFile();
                shx.Open(Filename);
                shx.Shapes.RemoveAt(index);
                shx.Save();

                AttributeTable dbf = GetAttributeTable(Filename);
                dbf.RemoveRowAt(index);
                if (_trackDeletedRows)
                {
                    _deletedRows = dbf.DeletedRows;
                }

                // Update extent in header if feature being deleted is NOT completely contained
                var hdr = new ShapefileHeader(Filename);

                Envelope featureEnv = ifs.GetFeature(0).Geometry.EnvelopeInternal;
                if (featureEnv.MinX <= hdr.Xmin || featureEnv.MaxX >= hdr.Xmax || featureEnv.MaxY >= hdr.Ymax || featureEnv.MinY <= hdr.Ymin)
                {
                    UpdateExtents();
                }

                // Update the Quadtree
                if (null != Quadtree)
                {
                    Quadtree.Remove(featureEnv, index);
                }
            }
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Opens a shapefile.
        /// </summary>
        /// <param name="fileName">The string fileName of the polygon shapefile to load.</param>
        /// <param name="progressHandler">Any valid implementation of the DotSpatial.Data.IProgressHandler.</param>
        public void Open(string fileName, IProgressHandler progressHandler)
        {
            if (!File.Exists(fileName))
            {
                return;
            }

            Filename  = fileName;
            IndexMode = true;
            Header    = new ShapefileHeader(Filename);

            CoordinateType = Header.ShapeType switch
            {
                ShapeType.PolygonM => CoordinateType.M,
                ShapeType.PolygonZ => CoordinateType.Z,
                _ => CoordinateType.Regular,
            };
            Extent = Header.ToExtent();
            Name   = Path.GetFileNameWithoutExtension(fileName);
            Attributes.Open(Filename);

            LineShapefile.FillLines(Filename, progressHandler, this, FeatureType.Polygon);
            ReadProjection();
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Opens a shapefile
        /// </summary>
        /// <param name="fileName">The string fileName of the point shapefile to load</param>
        /// <param name="progressHandler">Any valid implementation of the DotSpatial.Data.IProgressHandler</param>
        private void Open(string fileName, IProgressHandler progressHandler)
        {
            if (!File.Exists(fileName)) return;
        
            Header = new ShapefileHeader(fileName);

            // Check to ensure that the fileName is the correct shape type
            switch (FeatureType)
            {
                case FeatureType.Line:
                    if (Header.ShapeType != ShapeType.PolyLine &&
                        Header.ShapeType != ShapeType.PolyLineM &&
                        Header.ShapeType != ShapeType.PolyLineZ)
                    {
                        throw new ArgumentException(DataStrings.FileNotLines_S.Replace("%S", fileName));
                    }
                    break;
                case FeatureType.Polygon:
                    if (Header.ShapeType != ShapeType.Polygon &&
                        Header.ShapeType != ShapeType.PolygonM &&
                        Header.ShapeType != ShapeType.PolygonZ)
                    {
                        throw new ArgumentException(DataStrings.FileNotPolygons_S.Replace("%S", fileName));
                    }
                    break;
                case FeatureType.Point:
                    if (Header.ShapeType != ShapeType.Point &&
                        Header.ShapeType != ShapeType.PointM &&
                        Header.ShapeType != ShapeType.PointZ)
                    {
                        throw new ArgumentException(DataStrings.FileNotPoints_S.Replace("%S", fileName));
                    }
                    break;
                case FeatureType.MultiPoint:
                    if (Header.ShapeType != ShapeType.MultiPoint &&
                        Header.ShapeType != ShapeType.MultiPointM &&
                        Header.ShapeType != ShapeType.MultiPointZ)
                    {
                        throw new ArgumentException(DataStrings.FileNotMultipoints_S.Replace("%S", fileName));
                    }
                    break;
            }

            switch (Header.ShapeType)
            {
                case ShapeType.Point:
                case ShapeType.MultiPoint:
                case ShapeType.PolyLine:
                case ShapeType.Polygon:
                    CoordinateType = CoordinateType.Regular;
                    break;
                case ShapeType.PointM:
                case ShapeType.MultiPointM:
                case ShapeType.PolyLineM:
                case ShapeType.PolygonM:
                    CoordinateType = CoordinateType.M;
                    break;
                case ShapeType.PointZ:
                case ShapeType.MultiPointZ:
                case ShapeType.PolyLineZ:
                case ShapeType.PolygonZ:
                    CoordinateType = CoordinateType.Z;
                    break;
                default:
                    throw new Exception("Unsupported ShapeType");
            }

            Filename = fileName;
            IndexMode = true;

            Extent = Header.ToExtent();
            Name = Path.GetFileNameWithoutExtension(fileName);
            Attributes.Open(fileName);

            FillIndexes(fileName, progressHandler);
            ReadProjection();
        }
Ejemplo n.º 15
0
 private void Configure()
 {
     Attributes = new AttributeTable();
     Header     = new ShapefileHeader();
     IndexMode  = true;
 }
Ejemplo n.º 16
0
        /// <summary>
        /// Obtains a typed list of ShapefilePoint structures with double values associated with the various coordinates.
        /// </summary>
        /// <param name="fileName">A string fileName</param>
        /// <param name="progressHandler">A progress indicator</param>
        private void FillPoints(string fileName, IProgressHandler progressHandler)
        {
            // Check to ensure the fileName is not null
            if (fileName == null)
            {
                throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", fileName));
            }

            if (File.Exists(fileName) == false)
            {
                throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName));
            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List <ShapeHeader> shapeHeaders = ReadIndexFile(fileName);

            // Get the basic header information.
            ShapefileHeader header = new ShapefileHeader(fileName);

            MyExtent = header.ToExtent();
            // Check to ensure that the fileName is the correct shape type
            if (header.ShapeType != ShapeType.Point && header.ShapeType != ShapeType.PointM &&
                header.ShapeType != ShapeType.PointZ)
            {
                throw new ApplicationException(DataStrings.FileNotPoints_S.Replace("%S", fileName));
            }

            // This will set up a reader so that we can read values in huge chunks, which is much
            // faster than one value at a time.
            BufferedBinaryReader bbReader = new BufferedBinaryReader(fileName, progressHandler);

            if (bbReader.FileLength == 100)
            {
                bbReader.Close();
                // the file is empty so we are done reading
                return;
            }

            // Skip the shapefile header by skipping the first 100 bytes in the shapefile
            bbReader.Seek(100, SeekOrigin.Begin);
            int numShapes = shapeHeaders.Count;

            byte[] bigEndian = new byte[numShapes * 8];
            byte[] allCoords = new byte[numShapes * 16];
            bool   isM       = false;
            bool   isZ       = false;

            if (header.ShapeType == ShapeType.PointM || header.ShapeType == ShapeType.PointZ)
            {
                isM = true;
            }
            if (header.ShapeType == ShapeType.PointZ)
            {
                isZ = true;
            }
            byte[] allM = new byte[8];
            if (isM)
            {
                allM = new byte[numShapes * 8];
            }
            byte[] allZ = new byte[8];
            if (isZ)
            {
                allZ = new byte[numShapes * 8];
            }
            for (int shp = 0; shp < numShapes; shp++)
            {
                // Read from the index file because some deleted records
                // might still exist in the .shp file.
                long offset = (shapeHeaders[shp].ByteOffset);
                bbReader.Seek(offset, SeekOrigin.Begin);
                bbReader.Read(bigEndian, shp * 8, 8);
                bbReader.ReadInt32(); // Skip ShapeType.  Null shapes may break this.
                //bbReader.Seek(4, SeekOrigin.Current);
                bbReader.Read(allCoords, shp * 16, 16);
                if (isZ)
                {
                    bbReader.Read(allZ, shp * 8, 8);
                }
                if (isM)
                {
                    bbReader.Read(allM, shp * 8, 8);
                }
                ShapeRange shape = new ShapeRange(FeatureType.Point)
                {
                    StartIndex    = shp,
                    ContentLength = 8,
                    NumPoints     = 1,
                    NumParts      = 1
                };
                ShapeIndices.Add(shape);
            }
            double[] vert = new double[2 * numShapes];
            Buffer.BlockCopy(allCoords, 0, vert, 0, numShapes * 16);
            Vertex = vert;
            if (isM)
            {
                double[] m = new double[numShapes];
                Buffer.BlockCopy(allM, 0, m, 0, numShapes * 8);
                M = m;
            }
            if (isZ)
            {
                double[] z = new double[numShapes];
                Buffer.BlockCopy(allZ, 0, z, 0, numShapes * 8);
                Z = z;
            }
            for (int shp = 0; shp < numShapes; shp++)
            {
                PartRange part = new PartRange(vert, shp, 0, FeatureType.Point);
                part.NumVertices = 1;
                ShapeRange shape = ShapeIndices[shp];
                shape.Parts.Add(part);
                shape.Extent = new Extent(new[] { vert[shp * 2], vert[shp * 2 + 1], vert[shp * 2], vert[shp * 2 + 1] });
            }

            bbReader.Dispose();
        }
Ejemplo n.º 17
0
 /// <summary>
 /// Creates a new instance of a LineShapefile for in-ram handling only.
 /// </summary>
 public LineShapefile()
     : base(FeatureType.Line)
 {
     Attributes = new AttributeTable();
     Header = new ShapefileHeader { FileLength = 100, ShapeType = ShapeType.PolyLine };
 }
Ejemplo n.º 18
0
        /// <summary>
        /// Writes the current content to the specified file.
        /// </summary>
        /// <param name="header">The header to write</param>
        /// <param name="fileName">Basically the same code can be used for the shp and shx files</param>
        /// <param name="numShapes">The integer number of shapes to write to the file</param>
        private static void WriteHeader(ShapefileHeader header, string fileName, int numShapes)
        {
            string dir = Path.GetDirectoryName(fileName);
            if (dir != null)
            {
                if (!Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                }
            }

            FileStream bbWriter = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None, 100);

            bbWriter.WriteBe(header.FileCode);                     //  Byte 0          File Code       9994        Integer     Big

            byte[] bt = new byte[20];
            bbWriter.Write(bt, 0, 20);                                   //  Bytes 4 - 20 are unused

            // This is overwritten later
            bbWriter.WriteBe(50 + 4 * numShapes);                //  Byte 24         File Length     File Length Integer     Big

            bbWriter.WriteLe(header.Version);                             //  Byte 28         Version         1000        Integer     Little

            bbWriter.WriteLe((int)header.ShapeType);                      //  Byte 32         Shape Type      Shape Type  Integer     Little

            bbWriter.WriteLe(header.Xmin);                                //  Byte 36         Bounding Box    Xmin        Double      Little

            bbWriter.WriteLe(header.Ymin);                                //  Byte 44         Bounding Box    Ymin        Double      Little

            bbWriter.WriteLe(header.Xmax);                                //  Byte 52         Bounding Box    Xmax        Double      Little

            bbWriter.WriteLe(header.Ymax);                                //  Byte 60         Bounding Box    Ymax        Double      Little

            bbWriter.WriteLe(header.Zmin);                                //  Byte 68         Bounding Box    Zmin        Double      Little

            bbWriter.WriteLe(header.Zmax);                                //  Byte 76         Bounding Box    Zmax        Double      Little

            bbWriter.WriteLe(header.Mmin);                                //  Byte 84         Bounding Box    Mmin        Double      Little

            bbWriter.WriteLe(header.Mmax);                                //  Byte 92         Bounding Box    Mmax        Double      Little

            // ------------ WRITE TO SHP FILE -------------------------

            bbWriter.Close();
        }
Ejemplo n.º 19
0
        // X Y Poly Lines: Total Length = 28 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 3        Integer     1           Little
        // Byte 12      Xmin                Double      1           Little
        // Byte 20      Ymin                Double      1           Little
        // Byte 28      Xmax                Double      1           Little
        // Byte 36      Ymax                Double      1           Little
        // Byte 44      NumParts            Integer     1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte 52      Parts               Integer     NumParts    Little
        // Byte X       Points              Point       NumPoints   Little

        // X Y M Poly Lines: Total Length = 34 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 23       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumParts            Integer     1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte 52      Parts               Integer     NumParts    Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y*      Mmin                Double      1           Little
        // Byte Y + 8*  Mmax                Double      1           Little
        // Byte Y + 16* Marray              Double      NumPoints   Little

        // X Y Z M Poly Lines: Total Length = 44 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number  Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 13       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumParts            Integer     1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte 52      Parts               Integer     NumParts    Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y       Zmin                Double      1           Little
        // Byte Y + 8   Zmax                Double      1           Little
        // Byte Y + 16  Zarray              Double      NumPoints   Little
        // Byte Z*      Mmin                Double      1           Little
        // Byte Z+8*    Mmax                Double      1           Little
        // Byte Z+16*   Marray              Double      NumPoints   Little

        private void FillPolygons(string fileName, IProgressHandler progressHandler)
        {
            // Check to ensure the fileName is not null
            if (fileName == null)
            {
                throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", fileName));
            }

            if (File.Exists(fileName) == false)
            {
                throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName));
            }

            // Get the basic header information.
            ShapefileHeader header = new ShapefileHeader(fileName);

            Extent = new Extent(new[] { header.Xmin, header.Ymin, header.Xmax, header.Ymax });

            // Check to ensure that the fileName is the correct shape type
            if (header.ShapeType != ShapeType.Polygon &&
                header.ShapeType != ShapeType.PolygonM &&
                header.ShapeType != ShapeType.PolygonZ)
            {
                throw new ArgumentException(DataStrings.FileNotLines_S.Replace("%S", fileName));
            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List <ShapeHeader> shapeHeaders = ReadIndexFile(fileName);

            // TO DO: replace with a normal reader.  We no longer need Buffered Binary reader as
            // the buffer can be set on the underlying file stream.
            BufferedBinaryReader bbReader = new BufferedBinaryReader(fileName, progressHandler);

            if (bbReader.FileLength == 100)
            {
                // The shapefile is empty so we can simply return here
                bbReader.Close();
                return;
            }

            // Skip the shapefile header by skipping the first 100 bytes in the shapefile
            bbReader.Seek(100, SeekOrigin.Begin);

            int numShapes = shapeHeaders.Count;

            int[] partOffsets = new int[numShapes];
            //byte[] allBounds = new byte[numShapes * 32];

            // probably all will be in one block, but use a byteBlock just in case.
            ByteBlock allParts  = new ByteBlock(BLOCKSIZE);
            ByteBlock allCoords = new ByteBlock(BLOCKSIZE);
            bool      isM       = (header.ShapeType == ShapeType.PolygonM || header.ShapeType == ShapeType.PolygonZ);
            bool      isZ       = (header.ShapeType == ShapeType.PolygonZ);
            ByteBlock allZ      = null;
            ByteBlock allM      = null;

            if (isZ)
            {
                allZ = new ByteBlock(BLOCKSIZE);
            }
            if (isM)
            {
                allM = new ByteBlock(BLOCKSIZE);
            }

            int pointOffset = 0;

            for (int shp = 0; shp < numShapes; shp++)
            {
                // Read from the index file because some deleted records
                // might still exist in the .shp file.
                long offset = (shapeHeaders[shp].ByteOffset);
                bbReader.Seek(offset, SeekOrigin.Begin);

                // Position  Value Type    Number  Byte Order
                ShapeRange shape = new ShapeRange(FeatureType.Polygon); //------------------------------------
                shape.RecordNumber  = bbReader.ReadInt32(false);        // Byte 0   Record Integer   1     Big
                shape.ContentLength = bbReader.ReadInt32(false);        // Byte 4   Length Integer   1     Big

                // Setting shape type also controls extent class type.
                shape.ShapeType  = (ShapeType)bbReader.ReadInt32();     // Byte 8   Type   Integer   1     Little
                shape.StartIndex = pointOffset;
                if (shape.ShapeType == ShapeType.NullShape)
                {
                    continue;
                }
                shape.Extent.MinX = bbReader.ReadDouble();
                shape.Extent.MinY = bbReader.ReadDouble();
                shape.Extent.MaxX = bbReader.ReadDouble();
                shape.Extent.MaxY = bbReader.ReadDouble();
                shape.NumParts    = bbReader.ReadInt32();               // Byte 44  #Parts  Integer  1    Little
                shape.NumPoints   = bbReader.ReadInt32();               // Byte 48  #Points Integer  1    Little
                partOffsets[shp]  = allParts.IntOffset();
                allParts.Read(shape.NumParts * 4, bbReader);
                allCoords.Read(shape.NumPoints * 16, bbReader);
                pointOffset += shape.NumPoints;

                if (header.ShapeType == ShapeType.PolygonM)
                {
                    // These are listed as "optional" but there isn't a good indicator of
                    // how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints)
                    {
                        IExtentM mExt = (IExtentM)shape.Extent;
                        mExt.MinM = bbReader.ReadDouble();
                        mExt.MaxM = bbReader.ReadDouble();

                        if (allM != null)
                        {
                            allM.Read(shape.NumPoints * 8, bbReader);
                        }
                    }
                }

                if (header.ShapeType == ShapeType.PolygonZ)
                {
                    bool     hasM = shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints;
                    IExtentZ zExt = (IExtentZ)shape.Extent;
                    zExt.MinZ = bbReader.ReadDouble();
                    zExt.MaxZ = bbReader.ReadDouble();

                    // For Z shapefiles, the Z part is not optional.
                    if (allZ != null)
                    {
                        allZ.Read(shape.NumPoints * 8, bbReader);
                    }
                    // These are listed as "optional" but there isn't a good indicator of
                    // how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (hasM)
                    {
                        IExtentM mExt = (IExtentM)shape.Extent;
                        mExt.MinM = bbReader.ReadDouble();
                        mExt.MaxM = bbReader.ReadDouble();
                        if (allM != null)
                        {
                            allM.Read(shape.NumPoints * 8, bbReader);
                        }
                    }
                }
                ShapeIndices.Add(shape);
            }

            double[] vert = allCoords.ToDoubleArray();
            Vertex = vert;
            if (isM)
            {
                M = allM.ToDoubleArray();
            }
            if (isZ)
            {
                Z = allZ.ToDoubleArray();
            }
            List <ShapeRange> shapes = ShapeIndices;

            //double[] bounds = new double[numShapes * 4];
            //Buffer.BlockCopy(allBounds, 0, bounds, 0, allBounds.Length);
            int[] parts = allParts.ToIntArray();
            ProgressMeter = new ProgressMeter(ProgressHandler, "Testing Parts and Holes", shapes.Count);
            for (int shp = 0; shp < shapes.Count; shp++)
            {
                ShapeRange shape = shapes[shp];
                //shape.Extent = new Extent(bounds, shp * 4);
                for (int part = 0; part < shape.NumParts; part++)
                {
                    int offset     = partOffsets[shp];
                    int endIndex   = shape.NumPoints + shape.StartIndex;
                    int startIndex = parts[offset + part] + shape.StartIndex;
                    if (part < shape.NumParts - 1)
                    {
                        endIndex = parts[offset + part + 1] + shape.StartIndex;
                    }
                    int       count = endIndex - startIndex;
                    PartRange partR = new PartRange(vert, shape.StartIndex, parts[offset + part], FeatureType.Polygon);
                    partR.NumVertices = count;
                    shape.Parts.Add(partR);
                }
                ProgressMeter.CurrentValue = shp;
            }
            ProgressMeter.Reset();
        }
Ejemplo n.º 20
0
 private void Configure()
 {
     Attributes = new AttributeTable();
     _header = new ShapefileHeader();
     IndexMode = true;
 }
Ejemplo n.º 21
0
 /// <summary>
 /// Update the header to include the feature extent
 /// </summary>
 /// <param name="header"></param>
 /// <param name="feature"></param>
 protected void UpdateHeader(ShapefileHeader header, IGeometry feature)
 {
     UpdateHeader(header, feature, true);
 }
Ejemplo n.º 22
0
        /// <inheritdoc/>
        protected override void AppendGeometry(ShapefileHeader header, Geometry feature, int numFeatures)
        {
            FileInfo fi     = new FileInfo(Filename);
            int      offset = Convert.ToInt32(fi.Length / 2);

            FileStream shpStream = new FileStream(Filename, FileMode.Append, FileAccess.Write, FileShare.None, 10000);
            FileStream shxStream = new FileStream(header.ShxFilename, FileMode.Append, FileAccess.Write, FileShare.None, 100);

            List <int> parts = new List <int>();

            List <Coordinate> points = new List <Coordinate>();
            int contentLength        = 22;

            for (int iPart = 0; iPart < feature.NumGeometries; iPart++)
            {
                parts.Add(points.Count);
                LineString pg = feature.GetGeometryN(iPart) as LineString;
                if (pg == null)
                {
                    continue;
                }
                points.AddRange(pg.Coordinates);
            }

            contentLength += 2 * parts.Count;
            if (header.ShapeType == ShapeType.PolyLine)
            {
                contentLength += points.Count * 8;
            }

            if (header.ShapeType == ShapeType.PolyLineM)
            {
                contentLength += 8;                 // mmin mmax
                contentLength += points.Count * 12; // x, y, m
            }

            if (header.ShapeType == ShapeType.PolyLineZ)
            {
                contentLength += 16;                // mmin, mmax, zmin, zmax
                contentLength += points.Count * 16; // x, y, m, z
            }

            ////                                              Index File
            //                                                -------------------------------------------------------------------
            //                                                Position     Value               Type        Number      Byte Order
            //                                                -------------------------------------------------------------------
            shxStream.WriteBe(offset);                        // Byte 0    Offset              Integer     1           Big
            shxStream.WriteBe(contentLength);                 // Byte 4    Content Length      Integer     1           Big
            shxStream.Flush();
            shxStream.Close();
            ////                                              X Y Poly Lines
            //                                                -------------------------------------------------------------------
            //                                                Position     Value               Type        Number      Byte Order
            //                                                -------------------------------------------------------------------
            shpStream.WriteBe(numFeatures);                   // Byte 0    Record Number       Integer     1           Big
            shpStream.WriteBe(contentLength);                 // Byte 4    Content Length      Integer     1           Big
            shpStream.WriteLe((int)header.ShapeType);         // Byte 8    Shape Type 3        Integer     1           Little
            if (header.ShapeType == ShapeType.NullShape)
            {
                return;
            }

            shpStream.WriteLe(feature.EnvelopeInternal.MinX); // Byte 12   Xmin                Double      1           Little
            shpStream.WriteLe(feature.EnvelopeInternal.MinY); // Byte 20   Ymin                Double      1           Little
            shpStream.WriteLe(feature.EnvelopeInternal.MaxX); // Byte 28   Xmax                Double      1           Little
            shpStream.WriteLe(feature.EnvelopeInternal.MaxY); // Byte 36   Ymax                Double      1           Little
            shpStream.WriteLe(parts.Count);                   // Byte 44   NumParts            Integer     1           Little
            shpStream.WriteLe(points.Count);                  // Byte 48   NumPoints           Integer     1           Little

            foreach (int iPart in parts)
            {
                shpStream.WriteLe(iPart);                     // Byte 52   Parts               Integer     NumParts    Little
            }

            double[] xyVals = new double[points.Count * 2];

            for (var i = 0; i < points.Count; i++)
            {
                xyVals[i * 2]       = points[i].X;
                xyVals[(i * 2) + 1] = points[i].Y;
            }

            shpStream.WriteLe(xyVals, 0, 2 * points.Count);

            if (header.ShapeType == ShapeType.PolyLineZ)
            {
                shpStream.WriteLe(feature.MinZ());
                shpStream.WriteLe(feature.MaxZ());
                double[] zVals = new double[points.Count];
                for (int ipoint = 0; ipoint < points.Count; ipoint++)
                {
                    zVals[ipoint] = points[ipoint].Z;
                }

                shpStream.WriteLe(zVals, 0, points.Count);
            }

            if (header.ShapeType == ShapeType.PolyLineM || header.ShapeType == ShapeType.PolyLineZ)
            {
                if (feature.Envelope == null)
                {
                    shpStream.WriteLe(0.0);
                    shpStream.WriteLe(0.0);
                }
                else
                {
                    shpStream.WriteLe(feature.MinM());
                    shpStream.WriteLe(feature.MaxM());
                }

                double[] mVals = new double[points.Count];
                for (int ipoint = 0; ipoint < points.Count; ipoint++)
                {
                    mVals[ipoint] = points[ipoint].M;
                }

                shpStream.WriteLe(mVals, 0, points.Count);
            }

            shpStream.Flush();
            shpStream.Close();
            offset += contentLength;
            Shapefile.WriteFileLength(Filename, offset + 4); // Add 4 for the record header
            Shapefile.WriteFileLength(header.ShxFilename, 50 + (numFeatures * 4));
        }
Ejemplo n.º 23
0
        protected override void InsertGeometry(ShapefileHeader header, int fid, IGeometry geometry)
        {
            var shapeHeaders = ReadIndexFile(header.ShxFilename);

            if (fid < shapeHeaders.Count)
            {
                var        tmpShpPath   = Path.GetTempFileName();
                var        tmpShxPath   = Path.GetTempFileName();
                FileStream tmpShpStream = new FileStream(tmpShpPath, FileMode.Create, FileAccess.ReadWrite);
                FileStream shpStream    = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 10000);
                FileStream tmpShxStream = new FileStream(tmpShxPath, FileMode.Create, FileAccess.ReadWrite);
                FileStream shxStream    = new FileStream(header.ShxFilename, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 100);

                long shpOffset          = shapeHeaders[fid].ByteOffset;
                long shpRemainderOffset = shpOffset;
                long shpRemainderCount  = shpStream.Length - shpRemainderOffset;
                if (shpRemainderCount > 0)
                {
                    CopyTo(shpStream, tmpShpStream, shpRemainderOffset, shpRemainderCount);
                }

                long shxOffset          = 100 + fid * 8;
                long shxRemainderOffset = shxOffset;
                long shxRemainderCount  = shxStream.Length - shxRemainderOffset;
                if (shxRemainderCount > 0)
                {
                    CopyTo(shxStream, tmpShxStream, shxRemainderOffset, shxRemainderCount);
                }

                shpStream.Seek(shpOffset, SeekOrigin.Begin);
                shxStream.Seek(shxOffset, SeekOrigin.Begin);
                int recordNumber = fid + 1;

                int contentLength = GetContentLength(header.ShapeType);

                ////                                            Index File
                //                                              ---------------------------------------------------------
                //                                              Position     Value               Type        Number      Byte Order
                //                                              ---------------------------------------------------------
                shxStream.WriteBe(shapeHeaders[fid].Offset);    // Byte 0     Offset             Integer     1           Big
                shxStream.WriteBe(contentLength);               // Byte 4    Content Length      Integer     1           Big

                ////                                            X Y Points
                //                                              ---------------------------------------------------------
                //                                              Position     Value               Type        Number      Byte Order
                //                                              ---------------------------------------------------------
                shpStream.WriteBe(recordNumber);             // Byte 0       Record Number       Integer     1           Big
                shpStream.WriteBe(contentLength);            // Byte 4       Content Length      Integer     1           Big
                shpStream.WriteLe((int)header.ShapeType);    // Byte 8       Shape Type 3        Integer     1           Little
                if (header.ShapeType != ShapeType.NullShape)
                {
                    WriteGeometryContent(shpStream, header.ShapeType, geometry);
                }

                if (shxRemainderCount > 0)
                {
                    CopyTo(tmpShxStream, shxStream, 0, shxRemainderCount);
                }
                int dOffset = (int)((shpStream.Position - shpOffset) / 2);
                if (dOffset != 0)
                {
                    long shpPosition = shpStream.Position;
                    for (int i = fid; i < shapeHeaders.Count; i++)
                    {
                        shxStream.Seek(100 + (i + 1) * 8, SeekOrigin.Begin);
                        shxStream.WriteBe(shapeHeaders[i].Offset + dOffset);

                        shpStream.Seek((shapeHeaders[i].Offset + dOffset) * 2, SeekOrigin.Begin);
                        shpStream.WriteBe(i + 2);
                    }
                    shpStream.Seek(shpPosition, SeekOrigin.Begin);
                }

                int shxLength = Convert.ToInt32(shxStream.Length / 2);
                shxStream.Flush();
                tmpShxStream.Dispose();
                shxStream.Dispose();
                File.Delete(tmpShxPath);

                if (shpRemainderCount > 0)
                {
                    CopyTo(tmpShpStream, shpStream, 0, shpRemainderCount);
                }
                if (shpStream.Length != shpStream.Position + shpRemainderCount)
                {
                    shpStream.SetLength(shpStream.Position + shpRemainderCount);
                }
                ;
                int shpLength = Convert.ToInt32(shpStream.Length / 2);
                shpStream.Flush();
                shpStream.Dispose();
                Shapefile.WriteFileLength(Filename, shpLength);
                Shapefile.WriteFileLength(header.ShxFilename, shxLength);
                tmpShpStream.Dispose();
                File.Delete(tmpShpPath);
            }
        }
Ejemplo n.º 24
0
 /// <summary>
 /// Append the geometry to the shapefile.
 /// </summary>
 /// <param name="header">ShapefileHeader of this file.</param>
 /// <param name="geometry">Geometry that gets appended.</param>
 /// <param name="numFeatures">Number of the features in the shapefile including the one getting appended.</param>
 protected abstract void AppendGeometry(ShapefileHeader header, Geometry geometry, int numFeatures);
Ejemplo n.º 25
0
        /// <summary>
        /// Updates the file with an additional feature.
        /// </summary>
        /// <param name="feature">Feature that gets added.</param>
        public void Add(IFeature feature)
        {
            if (feature.FeatureType != FeatureType)
            {
                throw new FeatureTypeMismatchException();
            }

            string dir = Path.GetDirectoryName(Filename);

            if (dir != null && !Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            // We must add the dbf entry before changing the shx because if we already have one deleted record, the AttributeTable thinks we have none
            AttributeTable dbf = GetAttributeTable(Filename);

            dbf.AddRow(feature.DataRow);

            int numFeatures = 0;
            var header      = new ShapefileHeader();

            if (File.Exists(Filename))
            {
                header.Open(Filename);
                UpdateHeader(header, feature.Geometry);
                numFeatures = (header.ShxLength - 50) / 4;
            }
            else
            {
                header.Xmin = feature.Geometry.EnvelopeInternal.MinX;
                header.Xmax = feature.Geometry.EnvelopeInternal.MaxX;
                header.Ymin = feature.Geometry.EnvelopeInternal.MinY;
                header.Ymax = feature.Geometry.EnvelopeInternal.MaxY;
                if (double.IsNaN(feature.Geometry.Coordinates[0].M))
                {
                    header.ShapeType = ShapeType;
                }
                else
                {
                    if (double.IsNaN(feature.Geometry.Coordinates[0].Z))
                    {
                        header.ShapeType = ShapeTypeM;
                    }
                    else
                    {
                        header.Zmin      = feature.Geometry.MinZ();
                        header.Zmax      = feature.Geometry.MaxZ();
                        header.ShapeType = ShapeTypeZ;
                    }

                    header.Mmin = feature.Geometry.MinM();
                    header.Mmax = feature.Geometry.MaxM();
                }

                header.ShxLength = 4 + 50;
                header.SaveAs(Filename);
            }

            AppendGeometry(header, feature.Geometry, numFeatures);

            Quadtree?.Insert(feature.Geometry.EnvelopeInternal, numFeatures - 1);
        }
Ejemplo n.º 26
0
 /// <summary>
 /// Append the geometry to the shapefile
 /// </summary>
 /// <param name="header"></param>
 /// <param name="feature"></param>
 /// <param name="numFeatures"></param>
 protected abstract void AppendBasicGeometry(ShapefileHeader header, IBasicGeometry feature, int numFeatures);
Ejemplo n.º 27
0
 /// <summary>
 /// Get the shape at the specified index.  Must be implemented by all shape sources derived from ShapefileShapeSource
 /// </summary>
 /// <param name="fs"></param>
 /// <param name="shx"></param>
 /// <param name="header"></param>
 /// <param name="shp"></param>
 /// <param name="envelope"></param>
 /// <returns></returns>
 protected abstract Shape GetShapeAtIndex(FileStream fs, ShapefileIndexFile shx, ShapefileHeader header, int shp,
                                          IEnvelope envelope);
Ejemplo n.º 28
0
 /// <summary>
 /// Get the shape at the specified index.  Must be implemented by all shape sources derived from ShapefileShapeSource
 /// </summary>
 /// <param name="fs"></param>
 /// <param name="shx"></param>
 /// <param name="header"></param>
 /// <param name="shp"></param>
 /// <param name="envelope"></param>
 /// <returns></returns>
 protected abstract Shape GetShapeAtIndex(FileStream fs, ShapefileIndexFile shx, ShapefileHeader header, int shp,
                                          IEnvelope envelope);
Ejemplo n.º 29
0
        // X Y MultiPoints: Total Length = 28 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 8        Integer     1           Little
        // Byte 12      Xmin                Double      1           Little
        // Byte 20      Ymin                Double      1           Little
        // Byte 28      Xmax                Double      1           Little
        // Byte 36      Ymax                Double      1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte X       Points              Point       NumPoints   Little

        // X Y M MultiPoints: Total Length = 34 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 28       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumPoints           Integer     1           Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y*      Mmin                Double      1           Little
        // Byte Y + 8*  Mmax                Double      1           Little
        // Byte Y + 16* Marray              Double      NumPoints   Little

        // X Y Z M MultiPoints: Total Length = 44 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number  Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 18       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumPoints           Integer     1           Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y       Zmin                Double      1           Little
        // Byte Y + 8   Zmax                Double      1           Little
        // Byte Y + 16  Zarray              Double      NumPoints   Little
        // Byte Z*      Mmin                Double      1           Little
        // Byte Z+8*    Mmax                Double      1           Little
        // Byte Z+16*   Marray              Double      NumPoints   Little

        private void FillPoints(string fileName, IProgressHandler progressHandler)
        {
            // Check to ensure the fileName is not null
            if (fileName == null)
            {
                throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", fileName));
            }

            if (File.Exists(fileName) == false)
            {
                throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName));
            }

            // Get the basic header information.
            ShapefileHeader header = new ShapefileHeader(fileName);
            Extent = new Extent(new[] { header.Xmin, header.Ymin, header.Xmax, header.Ymax });
            // Check to ensure that the fileName is the correct shape type
            if (header.ShapeType != ShapeType.MultiPoint &&
                 header.ShapeType != ShapeType.MultiPointM &&
                 header.ShapeType != ShapeType.MultiPointZ)
            {
                throw new ArgumentException(DataStrings.FileNotLines_S.Replace("%S", fileName));
            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List<ShapeHeader> shapeHeaders = ReadIndexFile(fileName);

            // This will set up a reader so that we can read values in huge chunks, which is much faster than one value at a time.
            BufferedBinaryReader bbReader = new BufferedBinaryReader(fileName, progressHandler);

            if (bbReader.FileLength == 100)
            {
                // The shapefile is empty so we can simply return here
                bbReader.Close();
                return;
            }

            // Skip the shapefile header by skipping the first 100 bytes in the shapefile
            bbReader.Seek(100, SeekOrigin.Begin);

            int numShapes = shapeHeaders.Count;

            byte[] bigEndians = new byte[numShapes * 8];
            byte[] allBounds = new byte[numShapes * 32];

            ByteBlock allCoords = new ByteBlock(BLOCKSIZE);
            bool isM = (header.ShapeType == ShapeType.MultiPointZ || header.ShapeType == ShapeType.MultiPointM);
            bool isZ = (header.ShapeType == ShapeType.PolyLineZ);
            ByteBlock allZ = null;
            ByteBlock allM = null;
            if (isZ)
            {
                allZ = new ByteBlock(BLOCKSIZE);
            }
            if (isM)
            {
                allM = new ByteBlock(BLOCKSIZE);
            }
            int pointOffset = 0;
            for (int shp = 0; shp < numShapes; shp++)
            {
                // Read from the index file because some deleted records
                // might still exist in the .shp file.
                long offset = (shapeHeaders[shp].ByteOffset);
                bbReader.Seek(offset, SeekOrigin.Begin);

                // time: 200 ms
                ShapeRange shape = new ShapeRange(FeatureType.MultiPoint)
                                   {
                                       RecordNumber = bbReader.ReadInt32(false),
                                       ContentLength = bbReader.ReadInt32(false),
                                       ShapeType = (ShapeType)bbReader.ReadInt32(),
                                       StartIndex = pointOffset
                                   };

                //bbReader.Read(bigEndians, shp * 8, 8);
                if (shape.ShapeType == ShapeType.NullShape)
                {
                    continue;
                }
                bbReader.Read(allBounds, shp * 32, 32);
                shape.NumParts = 1;
                shape.NumPoints = bbReader.ReadInt32();
                allCoords.Read(shape.NumPoints * 16, bbReader);
                pointOffset += shape.NumPoints;

                if (header.ShapeType == ShapeType.MultiPointM)
                {
                    // These are listed as "optional" but there isn't a good indicator of
                    // how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints)
                    {
                        IExtentM mExt = (IExtentM)MyExtent;
                        mExt.MinM = bbReader.ReadDouble();
                        mExt.MaxM = bbReader.ReadDouble();
                        if (allM != null) allM.Read(shape.NumPoints * 8, bbReader);
                    }
                }
                if (header.ShapeType == ShapeType.MultiPointZ)
                {
                    bool hasM = shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints;
                    IExtentZ zExt = (IExtentZ)MyExtent;
                    zExt.MinZ = bbReader.ReadDouble();
                    zExt.MaxZ = bbReader.ReadDouble();
                    // For Z shapefiles, the Z part is not optional.
                    if (allZ != null) allZ.Read(shape.NumPoints * 8, bbReader);

                    // These are listed as "optional" but there isn't a good indicator of
                    // how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (hasM)
                    {
                        IExtentM mExt = (IExtentM)MyExtent;
                        mExt.MinM = bbReader.ReadDouble();
                        mExt.MaxM = bbReader.ReadDouble();
                        if (allM != null) allM.Read(shape.NumPoints * 8, bbReader);
                    }
                }
                // Now that we have read all the values, create the geometries from the points and parts arrays.
                ShapeIndices.Add(shape);
            }
            double[] vert = allCoords.ToDoubleArray();
            Vertex = vert;
            if (isM) M = allM.ToDoubleArray();
            if (isZ) Z = allZ.ToDoubleArray();
            Array.Reverse(bigEndians);
            List<ShapeRange> shapes = ShapeIndices;
            double[] bounds = new double[numShapes * 4];
            Buffer.BlockCopy(allBounds, 0, bounds, 0, allBounds.Length);
            for (int shp = 0; shp < numShapes; shp++)
            {
                ShapeRange shape = shapes[shp];
                shape.Extent = new Extent(bounds, shp * 4);
                int endIndex = shape.NumPoints + shape.StartIndex;
                int startIndex = shape.StartIndex;
                int count = endIndex - startIndex;
                PartRange partR = new PartRange(vert, shape.StartIndex, 0, FeatureType.MultiPoint) { NumVertices = count };
                shape.Parts.Add(partR);
            }

            bbReader.Dispose();
        }
Ejemplo n.º 30
0
        // X Y Poly Lines: Total Length = 28 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 3        Integer     1           Little
        // Byte 12      Xmin                Double      1           Little
        // Byte 20      Ymin                Double      1           Little
        // Byte 28      Xmax                Double      1           Little
        // Byte 36      Ymax                Double      1           Little
        // Byte 44      NumParts            Integer     1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte 52      Parts               Integer     NumParts    Little
        // Byte X       Points              Point       NumPoints   Little

        // X Y M Poly Lines: Total Length = 34 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 23       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumParts            Integer     1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte 52      Parts               Integer     NumParts    Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y*      Mmin                Double      1           Little
        // Byte Y + 8*  Mmax                Double      1           Little
        // Byte Y + 16* Marray              Double      NumPoints   Little

        // X Y Z M Poly Lines: Total Length = 44 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number  Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 13       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumParts            Integer     1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte 52      Parts               Integer     NumParts    Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y       Zmin                Double      1           Little
        // Byte Y + 8   Zmax                Double      1           Little
        // Byte Y + 16  Zarray              Double      NumPoints   Little
        // Byte Z*      Mmin                Double      1           Little
        // Byte Z+8*    Mmax                Double      1           Little
        // Byte Z+16*   Marray              Double      NumPoints   Little

        private void FillPolygons(string fileName, IProgressHandler progressHandler)
        {
            // Check to ensure the fileName is not null
            if (fileName == null)
            {
                throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", fileName));
            }

            if (File.Exists(fileName) == false)
            {
                throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName));
            }

            // Get the basic header information.
            ShapefileHeader header = new ShapefileHeader(fileName);
            Extent = new Extent(new[] { header.Xmin, header.Ymin, header.Xmax, header.Ymax });

            // Check to ensure that the fileName is the correct shape type
            if (header.ShapeType != ShapeType.Polygon &&
                 header.ShapeType != ShapeType.PolygonM &&
                 header.ShapeType != ShapeType.PolygonZ)
            {
                throw new ArgumentException(DataStrings.FileNotLines_S.Replace("%S", fileName));
            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List<ShapeHeader> shapeHeaders = ReadIndexFile(fileName);

            // TO DO: replace with a normal reader.  We no longer need Buffered Binary reader as
            // the buffer can be set on the underlying file stream.
            BufferedBinaryReader bbReader = new BufferedBinaryReader(fileName, progressHandler);

            if (bbReader.FileLength == 100)
            {
                // The shapefile is empty so we can simply return here
                bbReader.Close();
                return;
            }

            // Skip the shapefile header by skipping the first 100 bytes in the shapefile
            bbReader.Seek(100, SeekOrigin.Begin);

            int numShapes = shapeHeaders.Count;

            int[] partOffsets = new int[numShapes];
            //byte[] allBounds = new byte[numShapes * 32];

            // probably all will be in one block, but use a byteBlock just in case.
            ByteBlock allParts = new ByteBlock(BLOCKSIZE);
            ByteBlock allCoords = new ByteBlock(BLOCKSIZE);
            bool isM = (header.ShapeType == ShapeType.PolygonM || header.ShapeType == ShapeType.PolygonZ);
            bool isZ = (header.ShapeType == ShapeType.PolygonZ);
            ByteBlock allZ = null;
            ByteBlock allM = null;
            if (isZ)
            {
                allZ = new ByteBlock(BLOCKSIZE);
            }
            if (isM)
            {
                allM = new ByteBlock(BLOCKSIZE);
            }

            int pointOffset = 0;
            for (int shp = 0; shp < numShapes; shp++)
            {
                // Read from the index file because some deleted records
                // might still exist in the .shp file.
                long offset = (shapeHeaders[shp].ByteOffset);
                bbReader.Seek(offset, SeekOrigin.Begin);

                // Position  Value Type    Number  Byte Order
                ShapeRange shape = new ShapeRange(FeatureType.Polygon); //------------------------------------
                shape.RecordNumber = bbReader.ReadInt32(false);         // Byte 0   Record Integer   1     Big
                shape.ContentLength = bbReader.ReadInt32(false);        // Byte 4   Length Integer   1     Big

                // Setting shape type also controls extent class type.
                shape.ShapeType = (ShapeType)bbReader.ReadInt32();      // Byte 8   Type   Integer   1     Little
                shape.StartIndex = pointOffset;
                if (shape.ShapeType == ShapeType.NullShape)
                {
                    continue;
                }
                shape.Extent.MinX = bbReader.ReadDouble();
                shape.Extent.MinY = bbReader.ReadDouble();
                shape.Extent.MaxX = bbReader.ReadDouble();
                shape.Extent.MaxY = bbReader.ReadDouble();
                shape.NumParts = bbReader.ReadInt32();                  // Byte 44  #Parts  Integer  1    Little
                shape.NumPoints = bbReader.ReadInt32();                 // Byte 48  #Points Integer  1    Little
                partOffsets[shp] = allParts.IntOffset();
                allParts.Read(shape.NumParts * 4, bbReader);
                allCoords.Read(shape.NumPoints * 16, bbReader);
                pointOffset += shape.NumPoints;

                if (header.ShapeType == ShapeType.PolygonM)
                {
                    // These are listed as "optional" but there isn't a good indicator of
                    // how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints)
                    {
                        IExtentM mExt = (IExtentM)shape.Extent;
                        mExt.MinM = bbReader.ReadDouble();
                        mExt.MaxM = bbReader.ReadDouble();

                        if (allM != null) allM.Read(shape.NumPoints * 8, bbReader);
                    }
                }

                if (header.ShapeType == ShapeType.PolygonZ)
                {
                    bool hasM = shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints;
                    IExtentZ zExt = (IExtentZ)shape.Extent;
                    zExt.MinZ = bbReader.ReadDouble();
                    zExt.MaxZ = bbReader.ReadDouble();

                    // For Z shapefiles, the Z part is not optional.
                    if (allZ != null) allZ.Read(shape.NumPoints * 8, bbReader);
                    // These are listed as "optional" but there isn't a good indicator of
                    // how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (hasM)
                    {
                        IExtentM mExt = (IExtentM)shape.Extent;
                        mExt.MinM = bbReader.ReadDouble();
                        mExt.MaxM = bbReader.ReadDouble();
                        if (allM != null) allM.Read(shape.NumPoints * 8, bbReader);
                    }
                }
                ShapeIndices.Add(shape);
            }

            double[] vert = allCoords.ToDoubleArray();
            Vertex = vert;
            if (isM) M = allM.ToDoubleArray();
            if (isZ) Z = allZ.ToDoubleArray();
            List<ShapeRange> shapes = ShapeIndices;
            //double[] bounds = new double[numShapes * 4];
            //Buffer.BlockCopy(allBounds, 0, bounds, 0, allBounds.Length);
            int[] parts = allParts.ToIntArray();
            ProgressMeter = new ProgressMeter(ProgressHandler, "Testing Parts and Holes", shapes.Count);
            for (int shp = 0; shp < shapes.Count; shp++)
            {
                ShapeRange shape = shapes[shp];
                //shape.Extent = new Extent(bounds, shp * 4);
                for (int part = 0; part < shape.NumParts; part++)
                {
                    int offset = partOffsets[shp];
                    int endIndex = shape.NumPoints + shape.StartIndex;
                    int startIndex = parts[offset + part] + shape.StartIndex;
                    if (part < shape.NumParts - 1) endIndex = parts[offset + part + 1] + shape.StartIndex;
                    int count = endIndex - startIndex;
                    PartRange partR = new PartRange(vert, shape.StartIndex, parts[offset + part], FeatureType.Polygon);
                    partR.NumVertices = count;
                    shape.Parts.Add(partR);
                }
                ProgressMeter.CurrentValue = shp;
            }
            ProgressMeter.Reset();
        }
Ejemplo n.º 31
0
 protected abstract void InsertGeometry(ShapefileHeader header, int fid, IGeometry geometry);
Ejemplo n.º 32
0
        /// <summary>
        /// This will return the correct shapefile type by reading the fileName.
        /// </summary>
        /// <param name="fileName">A string specifying the file with the extension .shp to open.</param>
        /// <param name="progressHandler">receives progress messages and overrides the ProgressHandler on the DataManager.DefaultDataManager</param>
        /// <returns>A correct shapefile object which is exclusively for reading the .shp data</returns>
        public static new Shapefile OpenFile(string fileName, IProgressHandler progressHandler)
        {
            string ext = Path.GetExtension(fileName).ToLower();
            if (ext != ".shp" && ext != ".shx" && ext != ".dbf")
                throw new ArgumentException(String.Format("The file extension {0} is not supported by Shapefile data provider.", ext));
            string name = Path.ChangeExtension(fileName, ".shp");
            ShapefileHeader head = new ShapefileHeader();
            head.Open(name);
            PointShapefile psf;
            LineShapefile lsf;
            PolygonShapefile pgsf;
            MultiPointShapefile mpsf;
            switch (head.ShapeType)
            {
                case ShapeType.MultiPatch:
                    throw new NotImplementedException("This shape type is not yet supported.");

                case ShapeType.MultiPoint:
                case ShapeType.MultiPointM:
                case ShapeType.MultiPointZ:
                    mpsf = new MultiPointShapefile();
                    mpsf.Open(name, progressHandler);
                    return mpsf;

                case ShapeType.NullShape:
                    throw new NotImplementedException("This shape type is not yet supported.");

                case ShapeType.Point:
                case ShapeType.PointM:
                case ShapeType.PointZ:

                    // Instantiate a new object to handle the point shapefile
                    psf = new PointShapefile();

                    // Open the geometric components of the data (but not the dbf components)
                    psf.Open(name, progressHandler);

                    return psf;

                case ShapeType.Polygon:
                case ShapeType.PolygonM:
                case ShapeType.PolygonZ:
                    pgsf = new PolygonShapefile();
                    pgsf.Open(name, progressHandler);
                    return pgsf;

                case ShapeType.PolyLine:
                case ShapeType.PolyLineM:
                case ShapeType.PolyLineZ:
                    lsf = new LineShapefile();
                    lsf.Open(name, progressHandler);
                    return lsf;
            }

            return null;
        }
Ejemplo n.º 33
0
 /// <summary>
 /// Opens the index file of the specified fileName.  If the fileName is not the .shx extension,
 /// then the fileName will be changed too that extension first.
 /// </summary>
 /// <param name="fileName"></param>
 public void Open(string fileName)
 {
     Filename = Path.ChangeExtension(fileName, ".shx");
     Header = new ShapefileHeader(Filename);
     Shapes = ReadIndexFile(Filename);
 }
Ejemplo n.º 34
0
        /// <inheritdocs/>
        public void AddRange(IEnumerable <IFeature> features)
        {
            // Make sure the Output Directory exists
            string dir = Path.GetDirectoryName(Filename);

            if (dir != null && !Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            // Get the Attribute Table
            AttributeTable dbf = GetAttributeTable(Filename);

            // Open the Header if the Filename exists
            bool filenameExists = File.Exists(Filename);
            var  header         = new ShapefileHeader();

            if (filenameExists)
            {
                header.Open(Filename);
            }

            foreach (var feature in features)
            {
                if (feature.FeatureType != FeatureType)
                {
                    throw new FeatureTypeMismatchException();
                }

                // We must add the dbf entry before changing the shx because if we already have one deleted record, the AttributeTable thinks we have none
                dbf.AddRow(feature.DataRow);

                int numFeatures = 0;
                if (filenameExists)
                {
                    UpdateHeader(header, feature.Geometry, true);
                    numFeatures = (header.ShxLength - 50) / 4;
                }
                else
                {
                    header.Xmin = feature.Geometry.EnvelopeInternal.MinX;
                    header.Xmax = feature.Geometry.EnvelopeInternal.MaxX;
                    header.Ymin = feature.Geometry.EnvelopeInternal.MinY;
                    header.Ymax = feature.Geometry.EnvelopeInternal.MaxY;
                    if (double.IsNaN(feature.Geometry.Coordinates[0].M))
                    {
                        header.ShapeType = ShapeType;
                    }
                    else
                    {
                        if (double.IsNaN(feature.Geometry.Coordinates[0].Z))
                        {
                            header.ShapeType = ShapeTypeM;
                        }
                        else
                        {
                            header.Zmin      = feature.Geometry.EnvelopeInternal.Minimum.Z;
                            header.Zmax      = feature.Geometry.EnvelopeInternal.Maximum.Z;
                            header.ShapeType = ShapeTypeZ;
                        }
                        header.Mmin = feature.Geometry.EnvelopeInternal.Minimum.M;
                        header.Mmax = feature.Geometry.EnvelopeInternal.Maximum.M;
                    }
                    header.ShxLength = 4 + 50;
                    header.SaveAs(Filename);
                    filenameExists = true;
                }

                AppendBasicGeometry(header, feature.Geometry, numFeatures);

                feature.RecordNumber = numFeatures;

                if (null != Quadtree)
                {
                    Quadtree.Insert(feature.Geometry.EnvelopeInternal, numFeatures - 1);
                }
            }
        }
Ejemplo n.º 35
0
 /// <summary>
 /// Creates a new instance of a PolygonShapefile for in-ram handling only.
 /// </summary>
 public PolygonShapefile()
     : base(FeatureType.Polygon)
 {
     Attributes = new AttributeTable();
     Header = new ShapefileHeader { FileLength = 100, ShapeType = ShapeType.Polygon };
 }
Ejemplo n.º 36
0
 /// <summary>
 /// Append the geometry to the shapefile
 /// </summary>
 /// <param name="header"></param>
 /// <param name="feature"></param>
 /// <param name="numFeatures"></param>
 protected abstract void AppendBasicGeometry(ShapefileHeader header, IGeometry feature, int numFeatures);
Ejemplo n.º 37
0
        /// <inheritdoc/>
        protected override void AppendGeometry(ShapefileHeader header, Geometry feature, int numFeatures)
        {
            FileInfo fi     = new FileInfo(Filename);
            int      offset = Convert.ToInt32(fi.Length / 2);

            FileStream shpStream = new FileStream(Filename, FileMode.Append, FileAccess.Write, FileShare.None, 10000);
            FileStream shxStream = new FileStream(header.ShxFilename, FileMode.Append, FileAccess.Write, FileShare.None, 100);

            List <int> parts = new List <int>();

            List <Coordinate> points = new List <Coordinate>();
            int contentLength        = 22;

            for (int iPart = 0; iPart < feature.NumGeometries; iPart++)
            {
                parts.Add(points.Count);
                Polygon pg = feature.GetGeometryN(iPart) as Polygon;
                if (pg == null)
                {
                    continue;
                }
                var bl = pg.Shell;
                IEnumerable <Coordinate> coords = bl.Coordinates;

                if (Orientation.IsCCW(bl.Coordinates))
                {
                    // Exterior rings need to be clockwise
                    coords = coords.Reverse();
                }

                points.AddRange(coords);
                foreach (LineString hole in pg.Holes)
                {
                    parts.Add(points.Count);
                    IEnumerable <Coordinate> holeCoords = hole.Coordinates;
                    if (!Orientation.IsCCW(hole.Coordinates))
                    {
                        // Interior rings need to be counter-clockwise
                        holeCoords = holeCoords.Reverse();
                    }

                    points.AddRange(holeCoords);
                }
            }

            contentLength += 2 * parts.Count;
            if (header.ShapeType == ShapeType.Polygon)
            {
                contentLength += points.Count * 8;
            }
            else if (header.ShapeType == ShapeType.PolygonM)
            {
                contentLength += 8;                 // mmin mmax
                contentLength += points.Count * 12; // x, y, m
            }
            else if (header.ShapeType == ShapeType.PolygonZ)
            {
                contentLength += 16;                // mmin, mmax, zmin, zmax
                contentLength += points.Count * 16; // x, y, m, z
            }

            ////                                              Index File
            //                                                 ---------------------------------------------------------
            //                                                 Position     Value               Type        Number      Byte Order
            //                                                 ---------------------------------------------------------
            shxStream.WriteBe(offset);                         // Byte 0     Offset             Integer     1           Big
            shxStream.WriteBe(contentLength);                  // Byte 4    Content Length      Integer     1           Big
            shxStream.Flush();
            shxStream.Close();
            ////                                                 X Y Poly Lines
            //                                                 ---------------------------------------------------------
            //                                                 Position     Value               Type        Number      Byte Order
            //                                                 ---------------------------------------------------------
            shpStream.WriteBe(numFeatures);                    // Byte 0       Record Number       Integer     1           Big
            shpStream.WriteBe(contentLength);                  // Byte 4       Content Length      Integer     1           Big
            shpStream.WriteLe((int)header.ShapeType);          // Byte 8       Shape Type 3        Integer     1           Little
            if (header.ShapeType == ShapeType.NullShape)
            {
                return;
            }

            shpStream.WriteLe(feature.EnvelopeInternal.MinX);  // Byte 12      Xmin                Double      1           Little
            shpStream.WriteLe(feature.EnvelopeInternal.MinY);  // Byte 20      Ymin                Double      1           Little
            shpStream.WriteLe(feature.EnvelopeInternal.MaxX);  // Byte 28      Xmax                Double      1           Little
            shpStream.WriteLe(feature.EnvelopeInternal.MaxY);  // Byte 36      Ymax                Double      1           Little
            shpStream.WriteLe(parts.Count);                    // Byte 44      NumParts            Integer     1           Little
            shpStream.WriteLe(points.Count);                   // Byte 48      NumPoints           Integer     1           Little

            foreach (int iPart in parts)
            {
                shpStream.WriteLe(iPart);                      // Byte 52      Parts               Integer     NumParts    Little
            }

            double[] xyVals = new double[points.Count * 2];
            for (var i = 0; i < points.Count; i++)
            {
                xyVals[i * 2]     = points[i].X;
                xyVals[i * 2 + 1] = points[i].Y;
            }

            shpStream.WriteLe(xyVals, 0, 2 * points.Count);

            if (header.ShapeType == ShapeType.PolygonZ)
            {
                // Pandell, 2020-06-23: "NetTopologySuite" version 1.7.5 doesn't have "NetTopologySuite.Geometries.Envelope.Minimum" property
                // shpStream.WriteLe(feature.EnvelopeInternal.Minimum.Z);
                // shpStream.WriteLe(feature.EnvelopeInternal.Maximum.Z);
                shpStream.WriteLe(double.NaN);
                shpStream.WriteLe(double.NaN);
                double[] zVals = new double[points.Count];
                for (int ipoint = 0; ipoint < points.Count; ipoint++)
                {
                    zVals[ipoint] = points[ipoint].Z;
                }

                shpStream.WriteLe(zVals, 0, points.Count);
            }

            if (header.ShapeType == ShapeType.PolygonM || header.ShapeType == ShapeType.PolygonZ)
            {
                if (feature.EnvelopeInternal == null)
                {
                    shpStream.WriteLe(0.0);
                    shpStream.WriteLe(0.0);
                }
                else
                {
                    // Pandell, 2020-06-23: "NetTopologySuite" version 1.7.5 doesn't have "NetTopologySuite.Geometries.Envelope.Minimum" property
                    // shpStream.WriteLe(feature.EnvelopeInternal.Minimum.M);
                    // shpStream.WriteLe(feature.EnvelopeInternal.Maximum.M);
                    shpStream.WriteLe(double.NaN);
                    shpStream.WriteLe(double.NaN);
                }

                double[] mVals = new double[points.Count];
                for (int ipoint = 0; ipoint < points.Count; ipoint++)
                {
                    mVals[ipoint] = points[ipoint].M;
                }

                shpStream.WriteLe(mVals, 0, points.Count);
            }

            shpStream.Flush();
            shpStream.Close();
            offset += contentLength;
            Shapefile.WriteFileLength(Filename, offset + 4); // Add 4 for the record header
            Shapefile.WriteFileLength(header.ShxFilename, 50 + numFeatures * 4);
        }
Ejemplo n.º 38
0
        /// <inheritdocs/>
        public Dictionary <int, Shape> GetShapes(ref int startIndex, int count, IEnvelope envelope)
        {
            Dictionary <int, Shape> result = new Dictionary <int, Shape>();
            ShapefileIndexFile      shx    = CacheShapeIndexFile();

            // Check to ensure the fileName is not null
            if (Filename == null)
            {
                throw new NullReferenceException(Filename);
            }

            if (File.Exists(Filename) == false)
            {
                throw new FileNotFoundException(Filename);
            }

            // Get the basic header information.
            ShapefileHeader header = new ShapefileHeader(Filename);
            Extent          ext    = new Extent(new[] { header.Xmin, header.Ymin, header.Xmax, header.Ymax });

            if (envelope != null)
            {
                if (!ext.Intersects(envelope))
                {
                    return(result);
                }
            }

            // Check to ensure that the fileName is the correct shape type
            if (header.ShapeType != ShapeType &&
                header.ShapeType != ShapeTypeM &&
                header.ShapeType != ShapeTypeZ)
            {
                throw new ArgumentException("Wrong feature type.");
            }

            FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.Read);

            if (fs.Length == 100)
            {
                // The shapefile is empty so we can simply return here
                fs.Close();
                return(result);
            }

            int shapesTested   = 0;
            int shapesReturned = 0;

            // Use spatial index if we have one
            if (null != _spatialIndex && null != envelope)
            {
                IList spatialQueryResults = _spatialIndex.Query(envelope);

                // Sort the results from low to high index
                var sqra = new int[spatialQueryResults.Count];
                spatialQueryResults.CopyTo(sqra, 0);
                Array.Sort(sqra);

                foreach (int shp in sqra)
                {
                    if (shp >= startIndex)
                    {
                        Shape myShape = GetShapeAtIndex(fs, shx, header, shp, envelope);
                        shapesTested++;
                        if (null != myShape)
                        {
                            shapesReturned++;
                            result.Add(shp, myShape);
                            if (shapesReturned >= count)
                            {
                                break;
                            }
                        }
                    }
                }
            }
            else
            {
                int numShapes = shx.Shapes.Count;
                for (int shp = startIndex; shp < numShapes; shp++)
                {
                    Shape myShape = GetShapeAtIndex(fs, shx, header, shp, envelope);
                    shapesTested++;
                    if (null != myShape)
                    {
                        shapesReturned++;
                        result.Add(shp, myShape);
                        if (shapesReturned >= count)
                        {
                            break;
                        }
                    }
                }
            }
            startIndex += shapesTested;
            fs.Close();
            return(result);
        }
Ejemplo n.º 39
0
        /// <inheritdocs/>
        protected override Shape GetShapeAtIndex(FileStream fs, ShapefileIndexFile shx, ShapefileHeader header, int shp, IEnvelope envelope)
        {
            // Read from the index file because some deleted records
            // might still exist in the .shp file.
            long offset = (shx.Shapes[shp].ByteOffset);

            fs.Seek(offset, SeekOrigin.Begin);
            Shape myShape = new Shape();
            // Position     Value               Type        Number      Byte Order
            ShapeRange shape = new ShapeRange(FeatureType.Point); //--------------------------------------------------------------------

            shape.RecordNumber  = fs.ReadInt32(Endian.BigEndian); // Byte 0       Record Number       Integer     1           Big
            shape.ContentLength = fs.ReadInt32(Endian.BigEndian); // Byte 4       Content Length      Integer     1           Big
            ShapeType shapeType = (ShapeType)fs.ReadInt32();      // Byte 8       Shape Type          Integer     1           Little

            if (shapeType == ShapeType.NullShape)
            {
                return(null);
            }
            double[] vertices = fs.ReadDouble(2);
            double   x = vertices[0], y = vertices[1];

            // Don't add this shape to the result
            if (envelope != null)
            {
                if (!envelope.Contains(new Coordinate(x, y)))
                {
                    return(null);
                }
            }

            shape.StartIndex = 0;
            shape.NumParts   = 1;
            shape.NumPoints  = 1;
            shape.ShapeType  = shapeType;
            shape.Extent     = new Extent(x, y, x, y);
            myShape.Range    = shape;
            myShape.Vertices = vertices;

            if (header.ShapeType == ShapeType.PointM)
            {
                myShape.M    = fs.ReadDouble(1);
                myShape.MinM = myShape.MaxM = myShape.M[0];
                shape.Extent = new ExtentM(shape.Extent, myShape.MinM, myShape.MaxM);
            }
            else if (header.ShapeType == ShapeType.PointZ)
            {
                // For Z shapefiles, the Z part is not optional.
                myShape.Z    = fs.ReadDouble(1);
                myShape.MinZ = myShape.MaxZ = myShape.Z[0];
                myShape.M    = fs.ReadDouble(1);
                myShape.MinM = myShape.MaxM = myShape.M[0];
                shape.Extent = new ExtentMZ(shape.Extent.MinX, shape.Extent.MinY, myShape.MinM, myShape.MinZ, shape.Extent.MaxX, shape.Extent.MaxY, myShape.MaxM, myShape.MaxZ);
            }

            PartRange partR = new PartRange(myShape.Vertices, 0, 0, FeatureType.Point)
            {
                NumVertices = 1
            };

            shape.Parts.Add(partR);
            myShape.Range = shape;

            return(myShape);
        }
Ejemplo n.º 40
0
        /// <inheritdoc/>
        protected override void AppendBasicGeometry(ShapefileHeader header, IBasicGeometry feature, int numFeatures)
        {
            FileInfo fi     = new FileInfo(Filename);
            int      offset = Convert.ToInt32(fi.Length / 2);

            FileStream shpStream = new FileStream(Filename, FileMode.Append, FileAccess.Write, FileShare.None, 10000);
            FileStream shxStream = new FileStream(header.ShxFilename, FileMode.Append, FileAccess.Write, FileShare.None, 100);

            List <int> parts = new List <int>();

            List <Coordinate> points = new List <Coordinate>();
            int contentLength        = 22;

            for (int iPart = 0; iPart < feature.NumGeometries; iPart++)
            {
                parts.Add(points.Count);
                IBasicPolygon pg = feature.GetBasicGeometryN(iPart) as IBasicPolygon;
                if (pg == null)
                {
                    continue;
                }
                var bl     = pg.Shell;
                var coords = bl.Coordinates;

                if (CgAlgorithms.IsCounterClockwise(coords))
                {
                    // Exterior rings need to be clockwise
                    coords.Reverse();
                }

                points.AddRange(coords);
                foreach (IBasicLineString hole in pg.Holes)
                {
                    parts.Add(points.Count);
                    var holeCoords = hole.Coordinates;
                    if (CgAlgorithms.IsCounterClockwise(holeCoords) == false)
                    {
                        // Interior rings need to be counter-clockwise
                        holeCoords.Reverse();
                    }
                    points.AddRange(holeCoords);
                }
            }
            contentLength += 2 * parts.Count;
            if (header.ShapeType == ShapeType.Polygon)
            {
                contentLength += points.Count * 8;
            }
            if (header.ShapeType == ShapeType.PolygonM)
            {
                contentLength += 8;                 // mmin mmax
                contentLength += points.Count * 12; // x, y, m
            }
            if (header.ShapeType == ShapeType.PolygonZ)
            {
                contentLength += 16;                // mmin, mmax, zmin, zmax
                contentLength += points.Count * 16; // x, y, m, z
            }

            //                                              Index File
            //                                              ---------------------------------------------------------
            //                                              Position     Value               Type        Number      Byte Order
            //                                              ---------------------------------------------------------
            shxStream.WriteBe(offset);                      // Byte 0     Offset             Integer     1           Big
            shxStream.WriteBe(contentLength);               // Byte 4    Content Length      Integer     1           Big
            shxStream.Flush();
            shxStream.Close();
            //                                              X Y Poly Lines
            //                                              ---------------------------------------------------------
            //                                              Position     Value               Type        Number      Byte Order
            //                                              ---------------------------------------------------------
            shpStream.WriteBe(numFeatures);                 // Byte 0       Record Number       Integer     1           Big
            shpStream.WriteBe(contentLength);               // Byte 4       Content Length      Integer     1           Big
            shpStream.WriteLe((int)header.ShapeType);       // Byte 8       Shape Type 3        Integer     1           Little
            if (header.ShapeType == ShapeType.NullShape)
            {
                return;
            }

            shpStream.WriteLe(feature.Envelope.Minimum.X);             // Byte 12      Xmin                Double      1           Little
            shpStream.WriteLe(feature.Envelope.Minimum.Y);             // Byte 20      Ymin                Double      1           Little
            shpStream.WriteLe(feature.Envelope.Maximum.X);             // Byte 28      Xmax                Double      1           Little
            shpStream.WriteLe(feature.Envelope.Maximum.Y);             // Byte 36      Ymax                Double      1           Little
            shpStream.WriteLe(parts.Count);                            // Byte 44      NumParts            Integer     1           Little
            shpStream.WriteLe(points.Count);                           // Byte 48      NumPoints           Integer     1           Little
            // Byte 52      Parts               Integer     NumParts    Little
            foreach (int iPart in parts)
            {
                shpStream.WriteLe(iPart);
            }
            double[] xyVals = new double[points.Count * 2];

            int i = 0;

            foreach (Coordinate coord in points)
            {
                xyVals[i * 2]     = coord.X;
                xyVals[i * 2 + 1] = coord.Y;
                i++;
            }
            shpStream.WriteLe(xyVals, 0, 2 * points.Count);

            if (header.ShapeType == ShapeType.PolygonZ)
            {
                shpStream.WriteLe(feature.Envelope.Minimum.Z);
                shpStream.WriteLe(feature.Envelope.Maximum.Z);
                double[] zVals = new double[points.Count];
                for (int ipoint = 0; ipoint < points.Count; ipoint++)
                {
                    zVals[ipoint] = points[ipoint].Z;
                }
                shpStream.WriteLe(zVals, 0, points.Count);
            }

            if (header.ShapeType == ShapeType.PolygonM || header.ShapeType == ShapeType.PolygonZ)
            {
                if (feature.Envelope == null)
                {
                    shpStream.WriteLe(0.0);
                    shpStream.WriteLe(0.0);
                }
                else
                {
                    shpStream.WriteLe(feature.Envelope.Minimum.M);
                    shpStream.WriteLe(feature.Envelope.Maximum.M);
                }

                double[] mVals = new double[points.Count];
                for (int ipoint = 0; ipoint < points.Count; i++)
                {
                    mVals[ipoint] = points[ipoint].M;
                    ipoint++;
                }
                shpStream.WriteLe(mVals, 0, points.Count);
            }
            shpStream.Flush();
            shpStream.Close();
            offset += contentLength;
            Shapefile.WriteFileLength(Filename, offset);
            Shapefile.WriteFileLength(header.ShxFilename, 50 + numFeatures * 4);
        }
Ejemplo n.º 41
0
        private void FillLines(string fileName, IProgressHandler progressHandler)
        {
            // Check to ensure the fileName is not null
            if (fileName == null)
            {
                throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", "fileName"));
            }

            if (File.Exists(fileName) == false)
            {
                throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName));
            }

            // Get the basic header information.
            ShapefileHeader header = new ShapefileHeader(fileName);

            Extent = new Extent(new[] { header.Xmin, header.Ymin, header.Xmax, header.Ymax });
            // Check to ensure that the fileName is the correct shape type
            if (header.ShapeType != ShapeType.PolyLine &&
                header.ShapeType != ShapeType.PolyLineM &&
                header.ShapeType != ShapeType.PolyLineZ)
            {
                throw new ArgumentException(DataStrings.FileNotLines_S.Replace("%S", fileName));
            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List <ShapeHeader> shapeHeaders = ReadIndexFile(fileName);

            // This will set up a reader so that we can read values in huge chunks, which is much faster
            // than one value at a time.
            BufferedBinaryReader bbReader = new BufferedBinaryReader(fileName, progressHandler);

            if (bbReader.FileLength == 100)
            {
                // We have reached the end of the file so we can close the file
                bbReader.Close();
                return;
            }

            // Skip the shapefile header by skipping the first 100 bytes in the shapefile
            bbReader.Seek(100, SeekOrigin.Begin);

            int numShapes = shapeHeaders.Count;

            int[]  partOffsets = new int[numShapes];
            byte[] allBounds   = new byte[numShapes * 32];
            // probably all will be in one block, but use a byteBlock just in case.
            ByteBlock allParts  = new ByteBlock(BLOCKSIZE);
            ByteBlock allCoords = new ByteBlock(BLOCKSIZE);
            bool      isM       = (header.ShapeType == ShapeType.PolyLineM || header.ShapeType == ShapeType.PolyLineZ);
            bool      isZ       = (header.ShapeType == ShapeType.PolyLineZ);
            ByteBlock allZ      = null;
            ByteBlock allM      = null;

            if (isZ)
            {
                allZ = new ByteBlock(BLOCKSIZE);
            }
            if (isM)
            {
                allM = new ByteBlock(BLOCKSIZE);
            }

            int pointOffset = 0;

            for (int shp = 0; shp < numShapes; shp++)
            {
                // Read from the index file because some deleted records
                // might still exist in the .shp file.
                long offset = (shapeHeaders[shp].ByteOffset);
                bbReader.Seek(offset, SeekOrigin.Begin);

                ShapeRange shape = new ShapeRange(FeatureType.Line)
                {
                    RecordNumber  = bbReader.ReadInt32(false),
                    ContentLength = bbReader.ReadInt32(false),
                    ShapeType     = (ShapeType)bbReader.ReadInt32(),
                    StartIndex    = pointOffset
                };

                if (shape.ShapeType == ShapeType.NullShape)
                {
                    goto fin;
                }
                bbReader.Read(allBounds, shp * 32, 32);
                shape.NumParts  = bbReader.ReadInt32();  // Byte 44      NumParts    Integer     1      Little
                shape.NumPoints = bbReader.ReadInt32();  // Byte 48      NumPoints   Integer     1      Little

                partOffsets[shp] = allParts.IntOffset();
                allParts.Read(shape.NumParts * 4, bbReader);

                allCoords.Read(shape.NumPoints * 16, bbReader);

                pointOffset += shape.NumPoints;

                if (header.ShapeType == ShapeType.PolyLineM)
                {
                    // These are listed as "optional" but there isn't a good indicator of how to
                    // determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints)
                    {
                        //mMin = bbReader.ReadDouble();
                        //mMax = bbReader.ReadDouble();
                        bbReader.Seek(16, SeekOrigin.Current);
                        if (allM != null)
                        {
                            allM.Read(shape.NumPoints * 8, bbReader);
                        }
                    }
                }
                if (header.ShapeType == ShapeType.PolyLineZ)
                {
                    bool     hasM = shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints;
                    IExtentZ zExt = (IExtentZ)shape.Extent;
                    zExt.MinZ = bbReader.ReadDouble();
                    zExt.MaxZ = bbReader.ReadDouble();
                    if (allZ != null)
                    {
                        allZ.Read(shape.NumPoints * 8, bbReader);
                    }

                    // These are listed as "optional" but there isn't a good indicator of how to
                    // determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    IExtentM mExt = (IExtentM)shape.Extent;
                    if (hasM)
                    {
                        mExt.MinM = bbReader.ReadDouble();
                        mExt.MaxM = bbReader.ReadDouble();
                        if (allM != null)
                        {
                            allM.Read(shape.NumPoints * 8, bbReader);
                        }
                    }
                }

                // Now that we have read all the values, create the geometries from the points and parts arrays.
fin:
                ShapeIndices.Add(shape);
            }

            double[] vert = allCoords.ToDoubleArray();
            Vertex = vert;
            if (isM)
            {
                M = allM.ToDoubleArray();
            }
            if (isZ)
            {
                Z = allZ.ToDoubleArray();
            }
            List <ShapeRange> shapes = ShapeIndices;

            double[] bounds = new double[numShapes * 4];
            Buffer.BlockCopy(allBounds, 0, bounds, 0, allBounds.Length);
            int[] parts = allParts.ToIntArray();
            for (int shp = 0; shp < numShapes; shp++)
            {
                ShapeRange shape = shapes[shp];
                shape.Extent = new Extent(bounds, shp * 4);
                for (int part = 0; part < shape.NumParts; part++)
                {
                    int offset     = partOffsets[shp];
                    int endIndex   = shape.NumPoints + shape.StartIndex;
                    int startIndex = parts[offset + part] + shape.StartIndex;
                    if (part < shape.NumParts - 1)
                    {
                        int prt = parts[offset + part + 1];
                        endIndex = prt + shape.StartIndex;
                    }
                    int       count = endIndex - startIndex;
                    PartRange partR = new PartRange(vert, shape.StartIndex, parts[offset + part], FeatureType.Line)
                    {
                        NumVertices = count
                    };
                    shape.Parts.Add(partR);
                }
            }

            bbReader.Dispose();
        }
Ejemplo n.º 42
0
 /// <summary>
 /// Creates a new instance of a MultiPointShapefile for in-ram handling only.
 /// </summary>
 public MultiPointShapefile()
     : base(FeatureType.MultiPoint)
 {
     Attributes = new AttributeTable();
     Header = new ShapefileHeader { FileLength = 100, ShapeType = ShapeType.MultiPoint };
 }
Ejemplo n.º 43
0
        /// <summary>
        /// Obtains a typed list of ShapefilePoint structures with double values associated with the various coordinates.
        /// </summary>
        /// <param name="fileName">A string fileName</param>
        private void FillPoints(string fileName)
        {
            // Check to ensure the fileName is not null
            if (fileName == null)
            {
                throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", fileName));
            }

            if (File.Exists(fileName) == false)
            {
                throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName));
            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List<ShapeHeader> shapeHeaders = ReadIndexFile(fileName);

            // Get the basic header information.
            ShapefileHeader header = new ShapefileHeader(fileName);
            Extent = header.ToExtent();
            // Check to ensure that the fileName is the correct shape type
            if (header.ShapeType != ShapeType.Point && header.ShapeType != ShapeType.PointM
                && header.ShapeType != ShapeType.PointZ)
            {
                throw new ApplicationException(DataStrings.FileNotPoints_S.Replace("%S", fileName));
            }

            if (new FileInfo(fileName).Length == 100)
            {
                // the file is empty so we are done reading
                return;
            }

            var numShapes = shapeHeaders.Count;
            double[] m = null;
            double[] z = null;
            var vert = new double[2 * numShapes]; // X,Y

            if (header.ShapeType == ShapeType.PointM || header.ShapeType == ShapeType.PointZ)
            {
                m = new double[numShapes];
            }
            if (header.ShapeType == ShapeType.PointZ)
            {
                z = new double[numShapes];
            }

            using (var reader = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                for (var shp = 0; shp < numShapes; shp++)
                {
                    reader.Seek(shapeHeaders[shp].ByteOffset, SeekOrigin.Begin);

                    var recordNumber = reader.ReadInt32(Endian.BigEndian);
                    Debug.Assert(recordNumber == shp + 1);
                    var contentLen = reader.ReadInt32(Endian.BigEndian);
                    Debug.Assert(contentLen == shapeHeaders[shp].ContentLength);

                    var shapeType = (ShapeType) reader.ReadInt32(Endian.LittleEndian);
                    if (shapeType == ShapeType.NullShape)
                    {
                        if (m != null)
                        {
                            m[shp] = double.MinValue;
                        }
                        goto fin;
                    }

                    // Read X
                    var ind = 4;
                    vert[shp*2] = reader.ReadDouble(1, Endian.LittleEndian)[0];
                    ind += 8;

                    // Read Y
                    vert[shp*2 + 1] = reader.ReadDouble(1, Endian.LittleEndian)[0];
                    ind += 8;

                    // Read Z
                    if (z != null)
                    {
                        z[shp] = reader.ReadDouble(1, Endian.LittleEndian)[0];
                        ind += 8;
                    }

                    // Read M
                    if (m != null)
                    {
                        if (shapeHeaders[shp].ByteLength <= ind)
                        {
                            m[shp] = double.MinValue;
                        }
                        else
                        {
                            m[shp] = reader.ReadDouble(1, Endian.LittleEndian)[0];
                            ind += 8;
                        }
                    }

               fin:
                    var shape = new ShapeRange(FeatureType.Point)
                    {
                        StartIndex = shp,
                        ContentLength = shapeHeaders[shp].ContentLength,
                        NumPoints = 1,
                        NumParts = 1
                    };
                    ShapeIndices.Add(shape);
                    var part = new PartRange(vert, shp, 0, FeatureType.Point) {NumVertices = 1};
                    shape.Parts.Add(part);
                    shape.Extent = new Extent(new[] {vert[shp*2], vert[shp*2 + 1], vert[shp*2], vert[shp*2 + 1]});

                }
            }

            Vertex = vert;
            M = m;
            Z = z;
        }
Ejemplo n.º 44
0
        /// <summary>
        /// Obtains a typed list of ShapefilePoint structures with double values associated with the various coordinates.
        /// </summary>
        /// <param name="fileName">A string fileName</param>
        /// <param name="progressHandler">Progress handler</param>
        private void FillPoints(string fileName, IProgressHandler progressHandler)
        {
            // Check to ensure the fileName is not null
            if (fileName == null)
            {
                throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", "fileName"));
            }

            if (File.Exists(fileName) == false)
            {
                throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName));
            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List <ShapeHeader> shapeHeaders = ReadIndexFile(fileName);

            // Get the basic header information.
            var header = new ShapefileHeader(fileName);

            Extent = header.ToExtent();
            // Check to ensure that the fileName is the correct shape type
            if (header.ShapeType != ShapeType.Point && header.ShapeType != ShapeType.PointM &&
                header.ShapeType != ShapeType.PointZ)
            {
                throw new ApplicationException(DataStrings.FileNotPoints_S.Replace("%S", fileName));
            }

            if (new FileInfo(fileName).Length == 100)
            {
                // the file is empty so we are done reading
                return;
            }

            var numShapes = shapeHeaders.Count;

            double[] m    = null;
            double[] z    = null;
            var      vert = new double[2 * numShapes]; // X,Y

            if (header.ShapeType == ShapeType.PointM || header.ShapeType == ShapeType.PointZ)
            {
                m = new double[numShapes];
            }
            if (header.ShapeType == ShapeType.PointZ)
            {
                z = new double[numShapes];
            }

            var progressMeter = new ProgressMeter(progressHandler, "Reading from " + Path.GetFileName(fileName))
            {
                StepPercent = 5
            };

            using (var reader = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                for (var shp = 0; shp < numShapes; shp++)
                {
                    progressMeter.CurrentPercent = (int)(shp * 100.0 / numShapes);

                    reader.Seek(shapeHeaders[shp].ByteOffset, SeekOrigin.Begin);

                    var recordNumber = reader.ReadInt32(Endian.BigEndian);
                    Debug.Assert(recordNumber == shp + 1);
                    var contentLen = reader.ReadInt32(Endian.BigEndian);
                    Debug.Assert(contentLen == shapeHeaders[shp].ContentLength);

                    var shapeType = (ShapeType)reader.ReadInt32();
                    if (shapeType == ShapeType.NullShape)
                    {
                        if (m != null)
                        {
                            m[shp] = double.MinValue;
                        }
                        goto fin;
                    }

                    // Read X
                    var ind = 4;
                    vert[shp * 2] = reader.ReadDouble();
                    ind          += 8;

                    // Read Y
                    vert[shp * 2 + 1] = reader.ReadDouble();
                    ind += 8;

                    // Read Z
                    if (z != null)
                    {
                        z[shp] = reader.ReadDouble();
                        ind   += 8;
                    }

                    // Read M
                    if (m != null)
                    {
                        if (shapeHeaders[shp].ByteLength <= ind)
                        {
                            m[shp] = double.MinValue;
                        }
                        else
                        {
                            m[shp] = reader.ReadDouble();
                            ind   += 8;
                        }
                    }

fin:
                    var shape = new ShapeRange(FeatureType.Point)
                    {
                        RecordNumber  = recordNumber,
                        StartIndex    = shp,
                        ContentLength = shapeHeaders[shp].ContentLength,
                        NumPoints     = 1,
                        NumParts      = 1
                    };
                    ShapeIndices.Add(shape);
                    var part = new PartRange(vert, shp, 0, FeatureType.Point)
                    {
                        NumVertices = 1
                    };
                    shape.Parts.Add(part);
                    shape.Extent = new Extent(new[] { vert[shp * 2], vert[shp * 2 + 1], vert[shp * 2], vert[shp * 2 + 1] });
                }
            }

            Vertex = vert;
            M      = m;
            Z      = z;

            progressMeter.Reset();
        }
        /// <inheritdocs/>
        protected override void AppendBasicGeometry(ShapefileHeader header, IBasicGeometry feature, int numFeatures)
        {
            FileInfo fi = new FileInfo(Filename);
            int offset = Convert.ToInt32(fi.Length / 2);

            FileStream shpStream = new FileStream(Filename, FileMode.Append, FileAccess.Write, FileShare.None, 10000);
            FileStream shxStream = new FileStream(header.ShxFilename, FileMode.Append, FileAccess.Write, FileShare.None, 100);

            List<int> parts = new List<int>();

            List<Coordinate> points = new List<Coordinate>();
            int contentLength = 22;
            for (int iPart = 0; iPart < feature.NumGeometries; iPart++)
            {
                parts.Add(points.Count);
                IBasicLineString pg = feature.GetBasicGeometryN(iPart) as IBasicLineString;
                if (pg == null) continue;
                points.AddRange(pg.Coordinates);
            }
            contentLength += 2 * parts.Count;
            if (header.ShapeType == ShapeType.PolyLine)
            {
                contentLength += points.Count * 8;
            }
            if (header.ShapeType == ShapeType.PolyLineM)
            {
                contentLength += 8; // mmin mmax
                contentLength += points.Count * 12; // x, y, m
            }
            if (header.ShapeType == ShapeType.PolyLineZ)
            {
                contentLength += 16; // mmin, mmax, zmin, zmax
                contentLength += points.Count * 16; // x, y, m, z
            }

            //                                              Index File
            //                                              ---------------------------------------------------------
            //                                              Position     Value               Type        Number      Byte Order
            //                                              ---------------------------------------------------------
            shxStream.WriteBe(offset);                      // Byte 0     Offset             Integer     1           Big
            shxStream.WriteBe(contentLength);               // Byte 4    Content Length      Integer     1           Big
            shxStream.Flush();
            shxStream.Close();
            //                                              X Y Poly Lines
            //                                              ---------------------------------------------------------
            //                                              Position     Value               Type        Number      Byte Order
            //                                              ---------------------------------------------------------
            shpStream.WriteBe(numFeatures);                 // Byte 0       Record Number       Integer     1           Big
            shpStream.WriteBe(contentLength);               // Byte 4       Content Length      Integer     1           Big
            shpStream.WriteLe((int)header.ShapeType);       // Byte 8       Shape Type 3        Integer     1           Little
            if (header.ShapeType == ShapeType.NullShape)
            {
                return;
            }

            shpStream.WriteLe(feature.Envelope.Minimum.X);             // Byte 12      Xmin                Double      1           Little
            shpStream.WriteLe(feature.Envelope.Minimum.Y);             // Byte 20      Ymin                Double      1           Little
            shpStream.WriteLe(feature.Envelope.Maximum.X);             // Byte 28      Xmax                Double      1           Little
            shpStream.WriteLe(feature.Envelope.Maximum.Y);             // Byte 36      Ymax                Double      1           Little
            shpStream.WriteLe(parts.Count);                            // Byte 44      NumParts            Integer     1           Little
            shpStream.WriteLe(points.Count);                           // Byte 48      NumPoints           Integer     1           Little
            // Byte 52      Parts               Integer     NumParts    Little
            foreach (int iPart in parts)
            {
                shpStream.WriteLe(iPart);
            }
            double[] xyVals = new double[points.Count * 2];

            int i = 0;
            foreach (Coordinate coord in points)
            {
                xyVals[i * 2] = coord.X;
                xyVals[i * 2 + 1] = coord.Y;
                i++;
            }
            shpStream.WriteLe(xyVals, 0, 2 * points.Count);

            if (header.ShapeType == ShapeType.PolyLineZ)
            {
                shpStream.WriteLe(feature.Envelope.Minimum.Z);
                shpStream.WriteLe(feature.Envelope.Maximum.Z);
                double[] zVals = new double[points.Count];
                for (int ipoint = 0; ipoint < points.Count; ipoint++)
                {
                    zVals[ipoint] = points[ipoint].Z;
                }
                shpStream.WriteLe(zVals, 0, points.Count);
            }

            if (header.ShapeType == ShapeType.PolyLineM || header.ShapeType == ShapeType.PolyLineZ)
            {
                if (feature.Envelope == null)
                {
                    shpStream.WriteLe(0.0);
                    shpStream.WriteLe(0.0);
                }
                else
                {
                    shpStream.WriteLe(feature.Envelope.Minimum.M);
                    shpStream.WriteLe(feature.Envelope.Maximum.M);
                }

                double[] mVals = new double[points.Count];
                for (int ipoint = 0; ipoint < points.Count; i++)
                {
                    mVals[ipoint] = points[ipoint].M;
                    ipoint++;
                }
                shpStream.WriteLe(mVals, 0, points.Count);
            }
            shpStream.Flush();
            shpStream.Close();
            offset += contentLength;
            Shapefile.WriteFileLength(Filename, offset + 4); // Add 4 for the record header
            Shapefile.WriteFileLength(header.ShxFilename, 50 + numFeatures * 4);
        }
        /// <inheritdocs/>
        protected override Shape GetShapeAtIndex(FileStream fs, ShapefileIndexFile shx, ShapefileHeader header, int shp, IEnvelope envelope)
        {
            // Read from the index file because some deleted records
            // might still exist in the .shp file.
            long offset = (shx.Shapes[shp].ByteOffset);

            fs.Seek(offset, SeekOrigin.Begin);
            // Position     Value               Type        Number      Byte Order
            ShapeRange shape = new ShapeRange(FeatureType.Polygon); //--------------------------------------------------------------------

            shape.RecordNumber  = fs.ReadInt32(Endian.BigEndian);   // Byte 0       Record Number       Integer     1           Big
            shape.ContentLength = fs.ReadInt32(Endian.BigEndian);   // Byte 4       Content Length      Integer     1           Big
            shape.ShapeType     = (ShapeType)fs.ReadInt32();        // Byte 8       Shape Type          Integer     1           Little
            shape.StartIndex    = 0;
            if (shape.ShapeType == ShapeType.NullShape)
            {
                return(null);
            }

            Shape myShape = new Shape();

            myShape.Range = shape;

            //bbReader.Read(allBounds, shp*32, 32);
            double xMin = fs.ReadDouble();                // Byte 12      Xmin                Double      1           Little
            double yMin = fs.ReadDouble();                // Byte 20      Ymin                Double      1           Little
            double xMax = fs.ReadDouble();                // Byte 28      Xmax                Double      1           Little
            double yMax = fs.ReadDouble();                // Byte 36      Ymax                Double      1           Little

            shape.Extent = new Extent(xMin, yMin, xMax, yMax);
            // Don't add this shape to the result
            if (envelope != null)
            {
                if (!myShape.Range.Extent.Intersects(envelope))
                {
                    return(null);
                }
            }

            shape.NumParts = fs.ReadInt32();              // Byte 44      NumParts            Integer     1           Little
            //feature.NumPoints = bbReader.ReadInt32();             // Byte 48      NumPoints           Integer     1           Little
            shape.NumPoints = fs.ReadInt32();

            // Create an envelope from the extents box in the file.
            //feature.Envelope = new Envelope(xMin, xMax, yMin, yMax);
            int[] partIndices = fs.ReadInt32(shape.NumParts);
            myShape.Vertices = fs.ReadDouble(shape.NumPoints * 2);

            if (header.ShapeType == ShapeType.PolygonM)
            {
                // These are listed as "optional" but there isn't a good indicator of how to determine if they were added.
                // To handle the "optional" M values, check the contentLength for the feature.
                // The content length does not include the 8-byte record header and is listed in 16-bit words.
                if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints)
                {
                    myShape.MinM = fs.ReadDouble();
                    myShape.MaxM = fs.ReadDouble();

                    myShape.M    = fs.ReadDouble(shape.NumPoints);
                    shape.Extent = new ExtentM(shape.Extent, myShape.MinM, myShape.MaxM);
                }
            }
            else if (header.ShapeType == ShapeType.PolygonZ)
            {
                bool hasM = shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints;
                myShape.MinZ = fs.ReadDouble();
                myShape.MaxZ = fs.ReadDouble();
                // For Z shapefiles, the Z part is not optional.
                myShape.Z = fs.ReadDouble(shape.NumPoints);

                // These are listed as "optional" but there isn't a good indicator of how to determine if they were added.
                // To handle the "optional" M values, check the contentLength for the feature.
                // The content length does not include the 8-byte record header and is listed in 16-bit words.)
                if (hasM)
                {
                    myShape.MinM = fs.ReadDouble();
                    myShape.MaxM = fs.ReadDouble();
                    myShape.M    = fs.ReadDouble(shape.NumPoints);
                    shape.Extent = new ExtentMZ(shape.Extent.MinX, shape.Extent.MinY, myShape.MinM, myShape.MinZ, shape.Extent.MaxX, shape.Extent.MaxY, myShape.MaxM, myShape.MaxZ);
                }
                else
                {
                    shape.Extent = new ExtentMZ(shape.Extent.MinX, shape.Extent.MinY, double.MaxValue, myShape.MinZ, shape.Extent.MaxX, shape.Extent.MaxY, double.MinValue, myShape.MaxZ);
                }
            }

            myShape.Range = shape;

            for (int part = 0; part < shape.NumParts; part++)
            {
                int partOff    = partIndices[part];
                int pointCount = shape.NumPoints - partOff;
                if (part < shape.NumParts - 1)
                {
                    pointCount = partIndices[part + 1] - partOff;
                }
                PartRange partR = new PartRange(myShape.Vertices, 0, partOff, FeatureType.Polygon)
                {
                    NumVertices = pointCount
                };
                shape.Parts.Add(partR);
            }

            return(myShape);
        }
Ejemplo n.º 47
0
        // X Y MultiPoints: Total Length = 28 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 8        Integer     1           Little
        // Byte 12      Xmin                Double      1           Little
        // Byte 20      Ymin                Double      1           Little
        // Byte 28      Xmax                Double      1           Little
        // Byte 36      Ymax                Double      1           Little
        // Byte 48      NumPoints           Integer     1           Little
        // Byte X       Points              Point       NumPoints   Little

        // X Y M MultiPoints: Total Length = 34 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number      Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 28       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumPoints           Integer     1           Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y*      Mmin                Double      1           Little
        // Byte Y + 8*  Mmax                Double      1           Little
        // Byte Y + 16* Marray              Double      NumPoints   Little

        // X Y Z M MultiPoints: Total Length = 44 Bytes
        // ---------------------------------------------------------
        // Position     Value               Type        Number  Byte Order
        // ---------------------------------------------------------
        // Byte 0       Record Number       Integer     1           Big
        // Byte 4       Content Length      Integer     1           Big
        // Byte 8       Shape Type 18       Integer     1           Little
        // Byte 12      Box                 Double      4           Little
        // Byte 44      NumPoints           Integer     1           Little
        // Byte X       Points              Point       NumPoints   Little
        // Byte Y       Zmin                Double      1           Little
        // Byte Y + 8   Zmax                Double      1           Little
        // Byte Y + 16  Zarray              Double      NumPoints   Little
        // Byte Z*      Mmin                Double      1           Little
        // Byte Z+8*    Mmax                Double      1           Little
        // Byte Z+16*   Marray              Double      NumPoints   Little

        private void FillPoints(string fileName, IProgressHandler progressHandler)
        {
            // Check to ensure the fileName is not null
            if (fileName == null)
            {
                throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", "fileName"));
            }

            if (File.Exists(fileName) == false)
            {
                throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName));
            }

            // Get the basic header information.
            ShapefileHeader header = new ShapefileHeader(fileName);

            Extent = header.ToExtent();
            // Check to ensure that the fileName is the correct shape type
            if (header.ShapeType != ShapeType.MultiPoint &&
                header.ShapeType != ShapeType.MultiPointM &&
                header.ShapeType != ShapeType.MultiPointZ)
            {
                throw new ArgumentException(DataStrings.FileNotLines_S.Replace("%S", fileName));
            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List <ShapeHeader> shapeHeaders = ReadIndexFile(fileName);

            // This will set up a reader so that we can read values in huge chunks, which is much faster than one value at a time.
            BufferedBinaryReader bbReader = new BufferedBinaryReader(fileName, progressHandler);

            if (bbReader.FileLength == 100)
            {
                // The shapefile is empty so we can simply return here
                bbReader.Close();
                return;
            }

            // Skip the shapefile header by skipping the first 100 bytes in the shapefile
            bbReader.Seek(100, SeekOrigin.Begin);

            int numShapes = shapeHeaders.Count;

            byte[] bigEndians = new byte[numShapes * 8];
            byte[] allBounds  = new byte[numShapes * 32];

            ByteBlock allCoords = new ByteBlock(BLOCKSIZE);
            bool      isM       = (header.ShapeType == ShapeType.MultiPointZ || header.ShapeType == ShapeType.MultiPointM);
            bool      isZ       = (header.ShapeType == ShapeType.MultiPointZ);
            ByteBlock allZ      = null;
            ByteBlock allM      = null;

            if (isZ)
            {
                allZ = new ByteBlock(BLOCKSIZE);
            }
            if (isM)
            {
                allM = new ByteBlock(BLOCKSIZE);
            }
            int pointOffset = 0;

            for (int shp = 0; shp < numShapes; shp++)
            {
                // Read from the index file because some deleted records
                // might still exist in the .shp file.
                long offset = (shapeHeaders[shp].ByteOffset);
                bbReader.Seek(offset, SeekOrigin.Begin);

                // time: 200 ms
                ShapeRange shape = new ShapeRange(FeatureType.MultiPoint)
                {
                    RecordNumber  = bbReader.ReadInt32(false),
                    ContentLength = bbReader.ReadInt32(false),
                    ShapeType     = (ShapeType)bbReader.ReadInt32(),
                    StartIndex    = pointOffset
                };

                //bbReader.Read(bigEndians, shp * 8, 8);
                if (shape.ShapeType == ShapeType.NullShape)
                {
                    continue;
                }
                bbReader.Read(allBounds, shp * 32, 32);
                shape.NumParts  = 1;
                shape.NumPoints = bbReader.ReadInt32();
                allCoords.Read(shape.NumPoints * 16, bbReader);
                pointOffset += shape.NumPoints;

                if (header.ShapeType == ShapeType.MultiPointM)
                {
                    // These are listed as "optional" but there isn't a good indicator of
                    // how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints)
                    {
                        IExtentM mExt = (IExtentM)MyExtent;
                        mExt.MinM = bbReader.ReadDouble();
                        mExt.MaxM = bbReader.ReadDouble();
                        if (allM != null)
                        {
                            allM.Read(shape.NumPoints * 8, bbReader);
                        }
                    }
                }
                if (header.ShapeType == ShapeType.MultiPointZ)
                {
                    bool     hasM = shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints;
                    IExtentZ zExt = (IExtentZ)MyExtent;
                    zExt.MinZ = bbReader.ReadDouble();
                    zExt.MaxZ = bbReader.ReadDouble();
                    // For Z shapefiles, the Z part is not optional.
                    if (allZ != null)
                    {
                        allZ.Read(shape.NumPoints * 8, bbReader);
                    }

                    // These are listed as "optional" but there isn't a good indicator of
                    // how to determine if they were added.
                    // To handle the "optional" M values, check the contentLength for the feature.
                    // The content length does not include the 8-byte record header and is listed in 16-bit words.
                    if (hasM)
                    {
                        IExtentM mExt = (IExtentM)MyExtent;
                        mExt.MinM = bbReader.ReadDouble();
                        mExt.MaxM = bbReader.ReadDouble();
                        if (allM != null)
                        {
                            allM.Read(shape.NumPoints * 8, bbReader);
                        }
                    }
                }
                // Now that we have read all the values, create the geometries from the points and parts arrays.
                ShapeIndices.Add(shape);
            }
            double[] vert = allCoords.ToDoubleArray();
            Vertex = vert;
            if (isM)
            {
                M = allM.ToDoubleArray();
            }
            if (isZ)
            {
                Z = allZ.ToDoubleArray();
            }
            Array.Reverse(bigEndians);
            List <ShapeRange> shapes = ShapeIndices;

            double[] bounds = new double[numShapes * 4];
            Buffer.BlockCopy(allBounds, 0, bounds, 0, allBounds.Length);
            for (int shp = 0; shp < numShapes; shp++)
            {
                ShapeRange shape = shapes[shp];
                shape.Extent = new Extent(bounds, shp * 4);
                int       endIndex   = shape.NumPoints + shape.StartIndex;
                int       startIndex = shape.StartIndex;
                int       count      = endIndex - startIndex;
                PartRange partR      = new PartRange(vert, shape.StartIndex, 0, FeatureType.MultiPoint)
                {
                    NumVertices = count
                };
                shape.Parts.Add(partR);
            }

            bbReader.Dispose();
        }
        /// <inheritdocs/>
        protected override Shape GetShapeAtIndex(FileStream fs, ShapefileIndexFile shx, ShapefileHeader header, int shp, IEnvelope envelope)
        {
            // Read from the index file because some deleted records
            // might still exist in the .shp file.
            long offset = (shx.Shapes[shp].ByteOffset);
            fs.Seek(offset, SeekOrigin.Begin);
            Shape myShape = new Shape();
            // Position     Value               Type        Number      Byte Order
            ShapeRange shape = new ShapeRange(FeatureType.Line);
            //--------------------------------------------------------------------
            shape.RecordNumber = fs.ReadInt32(Endian.BigEndian);
            // Byte 0       Record Number       Integer     1           Big
            shape.ContentLength = fs.ReadInt32(Endian.BigEndian);
            // Byte 4       Content Length      Integer     1           Big
            shape.ShapeType = (ShapeType)fs.ReadInt32();
            // Byte 8       Shape Type          Integer     1           Little
            shape.StartIndex = 0;
            if (shape.ShapeType == ShapeType.NullShape)
            {
                return null;
            }

            myShape.Range = shape;

            //bbReader.Read(allBounds, shp*32, 32);
            double xMin = fs.ReadDouble(); // Byte 12      Xmin                Double      1           Little
            double yMin = fs.ReadDouble(); // Byte 20      Ymin                Double      1           Little
            double xMax = fs.ReadDouble(); // Byte 28      Xmax                Double      1           Little
            double yMax = fs.ReadDouble(); // Byte 36      Ymax                Double      1           Little
            shape.Extent = new Extent(xMin, yMin, xMax, yMax);
            // Don't add this shape to the result
            if (envelope != null)
            {
                if (!myShape.Range.Extent.Intersects(envelope))
                {
                    return null;
                }
            }

            shape.NumParts = fs.ReadInt32(); // Byte 44      NumParts            Integer     1           Little
            //feature.NumPoints = bbReader.ReadInt32();             // Byte 48      NumPoints           Integer     1           Little
            shape.NumPoints = fs.ReadInt32();

            // Create an envelope from the extents box in the file.
            //feature.Envelope = new Envelope(xMin, xMax, yMin, yMax);
            int[] partIndices = fs.ReadInt32(shape.NumParts);
            myShape.Vertices = fs.ReadDouble(shape.NumPoints * 2);

            if (header.ShapeType == ShapeType.PolyLineM)
            {
                // These are listed as "optional" but there isn't a good indicator of how to determine if they were added.
                // To handle the "optional" M values, check the contentLength for the feature.
                // The content length does not include the 8-byte record header and is listed in 16-bit words.
                if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints)
                {
                    myShape.MinM = fs.ReadDouble();
                    myShape.MaxM = fs.ReadDouble();

                    myShape.M = fs.ReadDouble(shape.NumPoints);
                    shape.Extent = new ExtentM(shape.Extent, myShape.MinM, myShape.MaxM);
                }
            }
            else if (header.ShapeType == ShapeType.PolyLineZ)
            {
                bool hasM = shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints;
                myShape.MinZ = fs.ReadDouble();
                myShape.MaxZ = fs.ReadDouble();

                // For Z shapefiles, the Z part is not optional.
                myShape.Z = fs.ReadDouble(shape.NumPoints);

                // These are listed as "optional" but there isn't a good indicator of how to determine if they were added.
                // To handle the "optional" M values, check the contentLength for the feature.
                // The content length does not include the 8-byte record header and is listed in 16-bit words.)
                if (hasM)
                {
                    myShape.MinM = fs.ReadDouble();
                    myShape.MaxM = fs.ReadDouble();
                    myShape.M = fs.ReadDouble(shape.NumPoints);
                    shape.Extent = new ExtentMZ(shape.Extent.MinX, shape.Extent.MinY, myShape.MinM, myShape.MinZ, shape.Extent.MaxX, shape.Extent.MaxY, myShape.MaxM, myShape.MaxZ);
                }
                else
                    shape.Extent = new ExtentMZ(shape.Extent.MinX, shape.Extent.MinY, double.MaxValue, myShape.MinZ, shape.Extent.MaxX, shape.Extent.MaxY, double.MinValue, myShape.MaxZ);
            }

            myShape.Range = shape;

            for (int part = 0; part < shape.NumParts; part++)
            {
                int partOff = partIndices[part];
                int pointCount = shape.NumPoints - partOff;
                if (part < shape.NumParts - 1)
                {
                    pointCount = partIndices[part + 1] - partOff;
                }
                PartRange partR = new PartRange(myShape.Vertices, 0, partOff, FeatureType.Line) { NumVertices = pointCount };
                shape.Parts.Add(partR);
            }
            return myShape;
        }
Ejemplo n.º 49
0
        /// <summary>
        /// Obtains a typed list of ShapefilePoint structures with double values associated with the various coordinates.
        /// </summary>
        /// <param name="fileName">A string fileName</param>
        /// <param name="progressHandler">A progress indicator</param>
        private void FillPoints(string fileName, IProgressHandler progressHandler)
        {
            // Check to ensure the fileName is not null
            if (fileName == null)
            {
                throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", fileName));
            }

            if (File.Exists(fileName) == false)
            {
                throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName));
            }

            // Reading the headers gives us an easier way to track the number of shapes and their overall length etc.
            List<ShapeHeader> shapeHeaders = ReadIndexFile(fileName);

            // Get the basic header information.
            ShapefileHeader header = new ShapefileHeader(fileName);
            MyExtent = header.ToExtent();
            // Check to ensure that the fileName is the correct shape type
            if (header.ShapeType != ShapeType.Point && header.ShapeType != ShapeType.PointM
                && header.ShapeType != ShapeType.PointZ)
            {
                throw new ApplicationException(DataStrings.FileNotPoints_S.Replace("%S", fileName));
            }

            // This will set up a reader so that we can read values in huge chunks, which is much
            // faster than one value at a time.
            BufferedBinaryReader bbReader = new BufferedBinaryReader(fileName, progressHandler);

            if (bbReader.FileLength == 100)
            {
                bbReader.Close();
                // the file is empty so we are done reading
                return;
            }

            // Skip the shapefile header by skipping the first 100 bytes in the shapefile
            bbReader.Seek(100, SeekOrigin.Begin);
            int numShapes = shapeHeaders.Count;
            byte[] bigEndian = new byte[numShapes * 8];
            byte[] allCoords = new byte[numShapes * 16];
            bool isM = false;
            bool isZ = false;
            if (header.ShapeType == ShapeType.PointM || header.ShapeType == ShapeType.PointZ)
            {
                isM = true;
            }
            if (header.ShapeType == ShapeType.PointZ)
            {
                isZ = true;
            }
            byte[] allM = new byte[8];
            if (isM) allM = new byte[numShapes * 8];
            byte[] allZ = new byte[8];
            if (isZ) allZ = new byte[numShapes * 8];
            for (int shp = 0; shp < numShapes; shp++)
            {
                // Read from the index file because some deleted records
                // might still exist in the .shp file.
                long offset = (shapeHeaders[shp].ByteOffset);
                bbReader.Seek(offset, SeekOrigin.Begin);
                bbReader.Read(bigEndian, shp * 8, 8);
                bbReader.ReadInt32(); // Skip ShapeType.  Null shapes may break this.
                //bbReader.Seek(4, SeekOrigin.Current);
                bbReader.Read(allCoords, shp * 16, 16);
                if (isZ)
                {
                    bbReader.Read(allZ, shp * 8, 8);
                }
                if (isM)
                {
                    bbReader.Read(allM, shp * 8, 8);
                }
                ShapeRange shape = new ShapeRange(FeatureType.Point)
                                   {
                                       StartIndex = shp,
                                       ContentLength = 8,
                                       NumPoints = 1,
                                       NumParts = 1
                                   };
                ShapeIndices.Add(shape);
            }
            double[] vert = new double[2 * numShapes];
            Buffer.BlockCopy(allCoords, 0, vert, 0, numShapes * 16);
            Vertex = vert;
            if (isM)
            {
                double[] m = new double[numShapes];
                Buffer.BlockCopy(allM, 0, m, 0, numShapes * 8);
                M = m;
            }
            if (isZ)
            {
                double[] z = new double[numShapes];
                Buffer.BlockCopy(allZ, 0, z, 0, numShapes * 8);
                Z = z;
            }
            for (int shp = 0; shp < numShapes; shp++)
            {
                PartRange part = new PartRange(vert, shp, 0, FeatureType.Point);
                part.NumVertices = 1;
                ShapeRange shape = ShapeIndices[shp];
                shape.Parts.Add(part);
                shape.Extent = new Extent(new[] { vert[shp * 2], vert[shp * 2 + 1], vert[shp * 2], vert[shp * 2 + 1] });
            }

            bbReader.Dispose();
        }
Ejemplo n.º 50
0
        /// <summary>
        /// This will return the correct shapefile type by reading the fileName.
        /// </summary>
        /// <param name="fileName">A string specifying the file with the extension .shp to open.</param>
        /// <param name="progressHandler">receives progress messages and overrides the ProgressHandler on the DataManager.DefaultDataManager</param>
        /// <returns>A correct shapefile object which is exclusively for reading the .shp data</returns>
        public static new Shapefile OpenFile(string fileName, IProgressHandler progressHandler)
        {
            string ext = Path.GetExtension(fileName).ToLower();

            if (ext != ".shp" && ext != ".shx" && ext != ".dbf")
            {
                throw new ArgumentException(String.Format("The file extension {0} is not supported by Shapefile data provider.", ext));
            }
            string          name = Path.ChangeExtension(fileName, ".shp");
            ShapefileHeader head = new ShapefileHeader();

            head.Open(name);
            PointShapefile      psf;
            LineShapefile       lsf;
            PolygonShapefile    pgsf;
            MultiPointShapefile mpsf;

            switch (head.ShapeType)
            {
            case ShapeType.MultiPatch:
                throw new NotImplementedException("This shape type is not yet supported.");

            case ShapeType.MultiPoint:
            case ShapeType.MultiPointM:
            case ShapeType.MultiPointZ:
                mpsf = new MultiPointShapefile();
                mpsf.Open(name, progressHandler);
                return(mpsf);

            case ShapeType.NullShape:
                throw new NotImplementedException("This shape type is not yet supported.");

            case ShapeType.Point:
            case ShapeType.PointM:
            case ShapeType.PointZ:

                // Instantiate a new object to handle the point shapefile
                psf = new PointShapefile();

                // Open the geometric components of the data (but not the dbf components)
                psf.Open(name, progressHandler);

                return(psf);

            case ShapeType.Polygon:
            case ShapeType.PolygonM:
            case ShapeType.PolygonZ:
                pgsf = new PolygonShapefile();
                pgsf.Open(name, progressHandler);
                return(pgsf);

            case ShapeType.PolyLine:
            case ShapeType.PolyLineM:
            case ShapeType.PolyLineZ:
                lsf = new LineShapefile();
                lsf.Open(name, progressHandler);
                return(lsf);
            }

            return(null);
        }
Ejemplo n.º 51
0
 /// <summary>
 /// Opens the index file of the specified fileName. If the fileName is not the .shx extension,
 /// then the fileName will be changed too that extension first.
 /// </summary>
 /// <param name="fileName">The file name.</param>
 public void Open(string fileName)
 {
     Filename = Path.ChangeExtension(fileName, ".shx");
     Header   = new ShapefileHeader(Filename);
     Shapes   = ReadIndexFile(Filename);
 }
Ejemplo n.º 52
0
        /// <summary>
        /// This will return the correct shapefile type by reading the fileName.
        /// </summary>
        /// <param name="fileName">A string specifying the file with the extension .shp to open.</param>
        /// <param name="progressHandler">receives progress messages and overrides the ProgressHandler on the DataManager.DefaultDataManager</param>
        /// <returns>A correct shapefile object which is exclusively for reading the .shp data</returns>
        public static new Shapefile OpenFile(string fileName, IProgressHandler progressHandler)
        {
            var ext = Path.GetExtension(fileName);
            if (ext != null) ext = ext.ToLower();
            if (ext != ".shp" && ext != ".shx" && ext != ".dbf")
                throw new ArgumentException(String.Format("The file extension {0} is not supported by Shapefile data provider.", ext));
            string name = Path.ChangeExtension(fileName, ".shp");
            var head = new ShapefileHeader();
            head.Open(name);
            switch (head.ShapeType)
            {
                case ShapeType.MultiPatch:
                    throw new NotImplementedException("This shape type is not yet supported.");

                case ShapeType.MultiPoint:
                case ShapeType.MultiPointM:
                case ShapeType.MultiPointZ:
                    var mpsf = new MultiPointShapefile();
                    mpsf.Open(name, progressHandler);
                    return mpsf;

                case ShapeType.NullShape:
                    throw new NotImplementedException("This shape type is not yet supported.");

                case ShapeType.Point:
                case ShapeType.PointM:
                case ShapeType.PointZ:
                    var psf = new PointShapefile();
                    psf.Open(name, progressHandler);
                    return psf;

                case ShapeType.Polygon:
                case ShapeType.PolygonM:
                case ShapeType.PolygonZ:
                    var pgsf = new PolygonShapefile();
                    pgsf.Open(name, progressHandler);
                    return pgsf;

                case ShapeType.PolyLine:
                case ShapeType.PolyLineM:
                case ShapeType.PolyLineZ:
                    var lsf = new LineShapefile();
                    lsf.Open(name, progressHandler);
                    return lsf;
            }

            return null;
        }
Ejemplo n.º 53
0
        /// <inheritdocs/>
        public Dictionary<int, Shape> GetShapes(ref int startIndex, int count, IEnvelope envelope)
        {
            Dictionary<int, Shape> result = new Dictionary<int, Shape>();
            ShapefileIndexFile shx = CacheShapeIndexFile();

            // Check to ensure the fileName is not null
            if (Filename == null)
            {
                throw new NullReferenceException(Filename);
            }

            if (File.Exists(Filename) == false)
            {
                throw new FileNotFoundException(Filename);
            }

            // Get the basic header information.
            ShapefileHeader header = new ShapefileHeader(Filename);
            Extent ext = new Extent(new[] { header.Xmin, header.Ymin, header.Xmax, header.Ymax });
            if (envelope != null)
            {
                if (!ext.Intersects(envelope)) return result;
            }

            // Check to ensure that the fileName is the correct shape type
            if (header.ShapeType != ShapeType &&
                 header.ShapeType != ShapeTypeM &&
                 header.ShapeType != ShapeTypeZ)
            {
                throw new ArgumentException("Wrong feature type.");
            }

            FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.Read);
            if (fs.Length == 100)
            {
                // The shapefile is empty so we can simply return here
                fs.Close();
                return result;
            }

            int shapesTested = 0;
            int shapesReturned = 0;

            // Use spatial index if we have one
            if (null != _spatialIndex && null != envelope)
            {
                IList spatialQueryResults = _spatialIndex.Query(envelope);

                // Sort the results from low to high index
                var sqra = new int[spatialQueryResults.Count];
                spatialQueryResults.CopyTo(sqra, 0);
                Array.Sort(sqra);

                foreach (int shp in sqra)
                {
                    if (shp >= startIndex)
                    {
                        Shape myShape = GetShapeAtIndex(fs, shx, header, shp, envelope);
                        shapesTested++;
                        if (null != myShape)
                        {
                            shapesReturned++;
                            result.Add(shp, myShape);
                            if (shapesReturned >= count) break;
                        }
                    }
                }
            }
            else
            {
                int numShapes = shx.Shapes.Count;
                for (int shp = startIndex; shp < numShapes; shp++)
                {
                    Shape myShape = GetShapeAtIndex(fs, shx, header, shp, envelope);
                    shapesTested++;
                    if (null != myShape)
                    {
                        shapesReturned++;
                        result.Add(shp, myShape);
                        if (shapesReturned >= count) break;
                    }
                }
            }
            startIndex += shapesTested;
            fs.Close();
            return result;
        }
Ejemplo n.º 54
0
        /// <inheritdocs/>
        public Shape[] GetShapes(int[] indices)
        {
            Shape[] result = new Shape[indices.Length];

            ShapefileIndexFile shx = CacheShapeIndexFile();

            // Check to ensure the fileName is not null
            if (Filename == null)
            {
                throw new NullReferenceException(Filename);
            }

            if (File.Exists(Filename) == false)
            {
                throw new FileNotFoundException(Filename);
            }

            // Get the basic header information.
            ShapefileHeader header = new ShapefileHeader(Filename);

            // Check to ensure that the fileName is the correct shape type
            if (header.ShapeType != ShapeType &&
                 header.ShapeType != ShapeTypeM &&
                 header.ShapeType != ShapeTypeZ)
            {
                throw new ArgumentException("Wrong feature type.");
            }

            FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.Read);
            try
            {
                if (fs.Length == 100)
                {
                    // The shapefile is empty so we can simply return here
                    return result;
                }
                int numShapes = shx.Shapes.Count;
                for (int j = 0; j < indices.Length; j++)
                {
                    int index = indices[j];
                    if (index < numShapes)
                        result[j] = GetShapeAtIndex(fs, shx, header, index, null);
                }
                return result;
            }
            finally
            {
                fs.Close();
            }
        }
Ejemplo n.º 55
0
        protected override void InsertGeometry(ShapefileHeader header, int fid, IGeometry geometry)
        {
            var shapeHeaders = ReadIndexFile(header.ShxFilename);

            if (fid < shapeHeaders.Count)
            {
                var        tmpShpPath   = Path.GetTempFileName();
                var        tmpShxPath   = Path.GetTempFileName();
                FileStream tmpShpStream = new FileStream(tmpShpPath, FileMode.Create, FileAccess.ReadWrite);
                FileStream shpStream    = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 10000);
                FileStream tmpShxStream = new FileStream(tmpShxPath, FileMode.Create, FileAccess.ReadWrite);
                FileStream shxStream    = new FileStream(header.ShxFilename, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 100);

                long shpOffset          = shapeHeaders[fid].ByteOffset;
                long shpRemainderOffset = shpOffset;
                long shpRemainderCount  = shpStream.Length - shpRemainderOffset;
                if (shpRemainderCount > 0)
                {
                    CopyTo(shpStream, tmpShpStream, shpRemainderOffset, shpRemainderCount);
                }

                long shxOffset          = 100 + fid * 8;
                long shxRemainderOffset = shxOffset;
                long shxRemainderCount  = shxStream.Length - shxRemainderOffset;
                if (shxRemainderCount > 0)
                {
                    CopyTo(shxStream, tmpShxStream, shxRemainderOffset, shxRemainderCount);
                }

                shpStream.Seek(shpOffset, SeekOrigin.Begin);
                shxStream.Seek(shxOffset, SeekOrigin.Begin);
                int recordNumber = fid + 1;

                List <int>        parts  = new List <int>();
                List <Coordinate> points = new List <Coordinate>();
                int contentLength        = 22;
                for (int iPart = 0; iPart < geometry.NumGeometries; iPart++)
                {
                    parts.Add(points.Count);
                    ILineString pg = geometry.GetGeometryN(iPart) as ILineString;
                    if (pg == null)
                    {
                        continue;
                    }
                    points.AddRange(pg.Coordinates);
                }

                contentLength += 2 * parts.Count;
                switch (header.ShapeType)
                {
                case ShapeType.PolyLine:
                    contentLength += points.Count * 8;
                    break;

                case ShapeType.PolyLineM:
                    contentLength += 8;                 // mmin mmax
                    contentLength += points.Count * 12; // x, y, m
                    break;

                case ShapeType.PolyLineZ:
                    contentLength += 16;                // mmin, mmax, zmin, zmax
                    contentLength += points.Count * 16; // x, y, m, z
                    break;
                }

                ////                                            Index File
                //                                              ---------------------------------------------------------
                //                                              Position     Value               Type        Number      Byte Order
                //                                              ---------------------------------------------------------
                shxStream.WriteBe(shapeHeaders[fid].Offset);    // Byte 0     Offset             Integer     1           Big
                shxStream.WriteBe(contentLength);               // Byte 4    Content Length      Integer     1           Big

                ////                                            X Y Points
                //                                              ---------------------------------------------------------
                //                                              Position     Value               Type        Number      Byte Order
                //                                              ---------------------------------------------------------
                shpStream.WriteBe(recordNumber);             // Byte 0       Record Number       Integer     1           Big
                shpStream.WriteBe(contentLength);            // Byte 4       Content Length      Integer     1           Big
                shpStream.WriteLe((int)header.ShapeType);    // Byte 8       Shape Type 3        Integer     1           Little
                if (header.ShapeType != ShapeType.NullShape)
                {
                    shpStream.WriteLe(geometry.EnvelopeInternal.MinX); // Byte 12   Xmin                Double      1           Little
                    shpStream.WriteLe(geometry.EnvelopeInternal.MinY); // Byte 20   Ymin                Double      1           Little
                    shpStream.WriteLe(geometry.EnvelopeInternal.MaxX); // Byte 28   Xmax                Double      1           Little
                    shpStream.WriteLe(geometry.EnvelopeInternal.MaxY); // Byte 36   Ymax                Double      1           Little
                    shpStream.WriteLe(parts.Count);                    // Byte 44   NumParts            Integer     1           Little
                    shpStream.WriteLe(points.Count);                   // Byte 48   NumPoints           Integer     1           Little

                    foreach (int iPart in parts)
                    {
                        shpStream.WriteLe(iPart);                     // Byte 52   Parts               Integer     NumParts    Little
                    }

                    double[] xyVals = new double[points.Count * 2];

                    for (var i = 0; i < points.Count; i++)
                    {
                        xyVals[i * 2]     = points[i].X;
                        xyVals[i * 2 + 1] = points[i].Y;
                    }

                    shpStream.WriteLe(xyVals, 0, 2 * points.Count);

                    if (header.ShapeType == ShapeType.PolyLineZ)
                    {
                        shpStream.WriteLe(geometry.EnvelopeInternal.Minimum.Z);
                        shpStream.WriteLe(geometry.EnvelopeInternal.Maximum.Z);
                        double[] zVals = new double[points.Count];
                        for (int ipoint = 0; ipoint < points.Count; ipoint++)
                        {
                            zVals[ipoint] = points[ipoint].Z;
                        }

                        shpStream.WriteLe(zVals, 0, points.Count);
                    }

                    if (header.ShapeType == ShapeType.PolyLineM || header.ShapeType == ShapeType.PolyLineZ)
                    {
                        if (geometry.Envelope == null)
                        {
                            shpStream.WriteLe(0.0);
                            shpStream.WriteLe(0.0);
                        }
                        else
                        {
                            shpStream.WriteLe(geometry.EnvelopeInternal.Minimum.M);
                            shpStream.WriteLe(geometry.EnvelopeInternal.Maximum.M);
                        }

                        double[] mVals = new double[points.Count];
                        for (int ipoint = 0; ipoint < points.Count; ipoint++)
                        {
                            mVals[ipoint] = points[ipoint].M;
                        }

                        shpStream.WriteLe(mVals, 0, points.Count);
                    }
                }

                if (shxRemainderCount > 0)
                {
                    CopyTo(tmpShxStream, shxStream, 0, shxRemainderCount);
                }
                int dOffset = (int)((shpStream.Position - shpOffset) / 2);
                if (dOffset != 0)
                {
                    long shpPosition = shpStream.Position;
                    for (int i = fid; i < shapeHeaders.Count; i++)
                    {
                        shxStream.Seek(100 + (i + 1) * 8, SeekOrigin.Begin);
                        shxStream.WriteBe(shapeHeaders[i].Offset + dOffset);

                        shpStream.Seek((shapeHeaders[i].Offset + dOffset) * 2, SeekOrigin.Begin);
                        shpStream.WriteBe(i + 2);
                    }
                    shpStream.Seek(shpPosition, SeekOrigin.Begin);
                }

                int shxLength = Convert.ToInt32(shxStream.Length / 2);
                shxStream.Flush();
                tmpShxStream.Dispose();
                shxStream.Dispose();
                File.Delete(tmpShxPath);

                if (shpRemainderCount > 0)
                {
                    CopyTo(tmpShpStream, shpStream, 0, shpRemainderCount);
                }
                if (shpStream.Length != shpStream.Position + shpRemainderCount)
                {
                    shpStream.SetLength(shpStream.Position + shpRemainderCount);
                }
                ;
                int shpLength = Convert.ToInt32(shpStream.Length / 2);
                shpStream.Flush();
                shpStream.Dispose();
                Shapefile.WriteFileLength(Filename, shpLength);
                Shapefile.WriteFileLength(header.ShxFilename, shxLength);
                tmpShpStream.Dispose();
                File.Delete(tmpShpPath);
            }
        }