/// <summary>
        /// Saves the file to a new location
        /// </summary>
        /// <param name="filename">The filename to save</param>
        /// <param name="overwrite">Boolean that specifies whether or not to overwrite the existing file</param>
        public override void SaveAs(string filename, bool overwrite)
        {
            if(IndexMode)
            {
                SaveAsIndexed(filename, overwrite);
                return;
            }
            if (File.Exists(filename) && filename != Filename && overwrite == false)
            {
                if (MessageBox.Show("The file already exists.  Do you wish to overwrite it?", "File Exists", MessageBoxButtons.YesNo) == DialogResult.No) return;
                File.Delete(filename);
            }
            string dir = Path.GetDirectoryName(filename);
            if (!Directory.Exists(dir))
            {
                if (MessageBox.Show("Directory " + dir + " does not exist.  Do you want to create it?", "Create Directory?", MessageBoxButtons.YesNo) != DialogResult.OK)
                    return;
                Directory.CreateDirectory(dir);
            }
            InvalidateEnvelope();
            Header.Xmin = Envelope.Minimum.X;
            Header.Xmax = Envelope.Maximum.X;
            Header.Ymin = Envelope.Minimum.Y;
            Header.Ymax = Envelope.Maximum.Y;
            if (CoordinateType == CoordinateTypes.Regular)
            {
                Header.ShapeType = ShapeTypes.MultiPoint;
            }
            if (CoordinateType == CoordinateTypes.M)
            {
                Header.ShapeType = ShapeTypes.MultiPointM;
            }
            if (CoordinateType == CoordinateTypes.Z)
            {
                Header.ShapeType = ShapeTypes.MultiPointZ;
            }
            
            if (Header.ShapeType == ShapeTypes.MultiPoint || Header.ShapeType == ShapeTypes.MultiPointM)
            {
                // test to see if the coordinates have added z or m values in the first coordinate
                Coordinate c = Features[0].BasicGeometry.Coordinates[0];
                if (!double.IsNaN(c.Z))
                {
                    Header.ShapeType = ShapeTypes.MultiPointZ;
                }
            }
            if (Header.ShapeType == ShapeTypes.MultiPointZ)
            {
                Header.Zmin = Envelope.Minimum.Z;
                Header.Zmax = Envelope.Maximum.Z;
            }
            if (Header.ShapeType == ShapeTypes.MultiPointM || Header.ShapeType == ShapeTypes.MultiPointZ)
            {
                Header.Mmin = Envelope.Minimum.M;
                Header.Mmax = Envelope.Maximum.M;
            }
            

            
            Header.ShxLength = 50 + 4 * Features.Count;
            Header.SaveAs(filename);

            IO.BufferedBinaryWriter bbWriter = new IO.BufferedBinaryWriter(filename);
            IO.BufferedBinaryWriter indexWriter = new IO.BufferedBinaryWriter(Header.ShxFilename);
            int fid = 0;
            int offset = 50; // the shapefile header starts at 100 bytes, so the initial offset is 50 words
            int contentLength = 0;
            ProgressMeter = new ProgressMeter(ProgressHandler, "Saving (Not Indexed)...", Features.Count);
            foreach (IFeature f in Features)
            {
                offset += contentLength; // adding the previous content length from each loop calculates the word offset
                List<Coordinate> points = new List<Coordinate>();
                contentLength = 20;
                for (int iPart = 0; iPart < f.NumGeometries; iPart++)
                {
                    IList<Coordinate> coords = f.BasicGeometry.GetBasicGeometryN(iPart).Coordinates;
                    foreach (Coordinate coord in coords)
                    {
                        points.Add(coord);
                    }
                }

                if (Header.ShapeType == ShapeTypes.MultiPoint)
                {

                    contentLength += points.Count * 8;
                }
                if (Header.ShapeType == ShapeTypes.MultiPointM)
                {
                    contentLength += 8; // mmin, mmax
                    contentLength += points.Count * 12;
                }
                if (Header.ShapeType == ShapeTypes.MultiPointZ)
                {
                    contentLength += 16; // mmin, mmax, zmin, zmax
                    contentLength += points.Count * 16;
                }

                //                                              Index File
                //                                              ---------------------------------------------------------
                //                                              Position     Value               Type        Number      Byte Order
                //                                              ---------------------------------------------------------
                indexWriter.Write(offset, false);            // Byte 0       Offset       Integer     1           Big                 
                indexWriter.Write(contentLength, false);     // Byte 4       Content Length       Integer     1           Big

                //                                              X Y Poly Lines
                //                                              ---------------------------------------------------------
                //                                              Position     Value               Type        Number      Byte Order
                //                                              ---------------------------------------------------------
                bbWriter.Write(fid+1, false);                // Byte 0       Record Number       Integer     1           Big
                bbWriter.Write(contentLength, false);        // Byte 4       Content Length      Integer     1           Big
                bbWriter.Write((int)Header.ShapeType);       // Byte 8       Shape Type 3        Integer     1           Little
                if (Header.ShapeType == ShapeTypes.NullShape)
                {
                    continue;
                }
                bbWriter.Write(f.Envelope.Minimum.X);             // Byte 12      Xmin                Double      1           Little
                bbWriter.Write(f.Envelope.Minimum.Y);             // Byte 20      Ymin                Double      1           Little
                bbWriter.Write(f.Envelope.Maximum.X);             // Byte 28      Xmax                Double      1           Little
                bbWriter.Write(f.Envelope.Maximum.Y);             // Byte 36      Ymax                Double      1           Little

                bbWriter.Write(points.Count);                // Byte 44      NumPoints           Integer     1           Little
             

                foreach (Coordinate coord in points)        // Byte X       Points              Point       NumPoints   Little
                {
                    bbWriter.Write(coord.X);
                    bbWriter.Write(coord.Y);
                    //if (Header.ShapeType == ShapeTypes.MultiPointZ)
                    //{
                    //    bbWriter.Write(coord.Z);
                    //}
                }

                if (Header.ShapeType == ShapeTypes.MultiPointZ)
                {
                    bbWriter.Write(f.Envelope.Minimum.Z);
                    bbWriter.Write(f.Envelope.Maximum.Z);
                    foreach (Coordinate coord in points)        // Byte X       Points              Point       NumPoints   Little
                    {
                        bbWriter.Write(coord.Z);
                    }
                }
                if (Header.ShapeType == ShapeTypes.MultiPointM || Header.ShapeType == ShapeTypes.MultiPointZ)
                {
                    if(f.Envelope == null)
                    {
                        bbWriter.Write(0.0);
                        bbWriter.Write(0.0);
                    }
                    else
                    {
                        bbWriter.Write(f.Envelope.Minimum.M);
                        bbWriter.Write(f.Envelope.Maximum.M);
                    }
                    foreach (Coordinate coord in points)        // Byte X       Points              Point       NumPoints   Little
                    {
                        bbWriter.Write(coord.M);
                    }
                }

                ProgressMeter.CurrentValue = fid;
                fid++;
                offset += 4;
            }
            ProgressMeter.Reset();
            bbWriter.Close();
            indexWriter.Close();

            offset += contentLength;
            WriteFileLength(Filename, offset);
            UpdateAttributes();
            SaveProjection();
        }
        /// <summary>
        /// Writes the current content to the specified file.
        /// </summary>
        /// <param name="destFilename">The string filename to write to</param>
        /// <param name="destFileLength">The only difference between the shp header and the shx header is the file length parameter.</param>
        private void Write(string destFilename, int destFileLength)
        {
            string dir = Path.GetDirectoryName(destFilename);
            if (!Directory.Exists(dir))
            {
                if (MessageBox.Show("Directory " + dir + " does not exist.  Do you want to create it?", "Create Directory?", MessageBoxButtons.YesNo) != DialogResult.OK)
                    return;
                Directory.CreateDirectory(dir);
            }
            if (System.IO.File.Exists(destFilename)) System.IO.File.Delete(destFilename);

            BufferedBinaryWriter bbWriter = new BufferedBinaryWriter(destFilename, null, 100);

            bbWriter.Write(_fileCode, false);                     //  Byte 0          File Code       9994        Integer     Big 

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

            bbWriter.Write(destFileLength, false);                //  Byte 24         File Length     File Length Integer     Big

            bbWriter.Write(_version);                             //  Byte 28         Version         1000        Integer     Little

            bbWriter.Write((int)_shapeType);                      //  Byte 32         Shape Type      Shape Type  Integer     Little

            bbWriter.Write(_xMin);                                //  Byte 36         Bounding Box    Xmin        Double      Little

            bbWriter.Write(_yMin);                                //  Byte 44         Bounding Box    Ymin        Double      Little

            bbWriter.Write(_xMax);                                //  Byte 52         Bounding Box    Xmax        Double      Little

            bbWriter.Write(_yMax);                                //  Byte 60         Bounding Box    Ymax        Double      Little

            bbWriter.Write(_zMin);                                //  Byte 68         Bounding Box    Zmin        Double      Little

            bbWriter.Write(_zMax);                                //  Byte 76         Bounding Box    Zmax        Double      Little

            bbWriter.Write(_mMin);                                //  Byte 84         Bounding Box    Mmin        Double      Little

            bbWriter.Write(_mMax);                                //  Byte 92         Bounding Box    Mmax        Double      Little

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


            bbWriter.Close();

        }
        /// <summary>
        /// Saves the file to a new location
        /// </summary>
        /// <param name="filename">The filename to save</param>
        /// <param name="overwrite">Boolean that specifies whether or not to overwrite the existing file</param>
        public override void SaveAs(string filename, bool overwrite)
        {

            if (IndexMode)
            {
                SaveAsIndexed(filename, overwrite);
                return;
            }
            Filename = filename;
            string dir = Path.GetDirectoryName(filename);
            if (!Directory.Exists(dir))
            {
                if (MessageBox.Show("Directory " + dir + " does not exist.  Do you want to create it?", "Create Directory?", MessageBoxButtons.YesNo) != DialogResult.OK)
                    return;
                Directory.CreateDirectory(dir);
            }
            if (File.Exists(filename) && filename != Filename && overwrite == false)
            {
                if (MessageBox.Show("The file already exists.  Do you wish to overwrite it?", "File Exists", System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No) return;
                File.Delete(filename);
            }
            InvalidateEnvelope();
            Header.Xmin = Envelope.Minimum.X;
            Header.Xmax = Envelope.Maximum.X;
            Header.Ymin = Envelope.Minimum.Y;
            Header.Ymax = Envelope.Maximum.Y;
            if (CoordinateType == CoordinateTypes.Regular)
            {
                Header.ShapeType = ShapeTypes.Polygon;
            }
            if (CoordinateType == CoordinateTypes.M)
            {
                Header.ShapeType = ShapeTypes.PolygonM;
            }
            if (CoordinateType == CoordinateTypes.Z)
            {
                Header.ShapeType = ShapeTypes.PolygonZ;
            }
            if (Header.ShapeType == ShapeTypes.PolygonZ)
            {
                Header.Zmin = Envelope.Minimum.Z;
                Header.Zmax = Envelope.Maximum.Z;
            }
            if (Header.ShapeType == ShapeTypes.PolygonM || Header.ShapeType == ShapeTypes.PolygonZ)
            {
                Header.Mmin = Envelope.Minimum.M;
                Header.Mmax = Envelope.Maximum.M;
            }
            
            Header.ShxLength = Features.Count * 4 + 50;
            Header.SaveAs(filename);
            
        

            IO.BufferedBinaryWriter bbWriter = new IO.BufferedBinaryWriter(filename);
            IO.BufferedBinaryWriter indexWriter = new IO.BufferedBinaryWriter(Header.ShxFilename);
            int fid = 0;
            int offset = 50; // the shapefile header starts at 100 bytes, so the initial offset is 50 words
            int contentLength = 0;
            int c = Features.Count;
            foreach (IFeature f in Features)
            {
                List<int> parts = new List<int>();
                
                offset += contentLength; // adding the previous content length from each loop calculates the word offset
                List<Coordinate> points = new List<Coordinate>();
                contentLength = 22;
                for (int iPart = 0; iPart < f.NumGeometries; iPart++)
                {
                    parts.Add(points.Count);
                    IBasicPolygon pg = f.GetBasicGeometryN(iPart) as IBasicPolygon;
                    if (pg == null) continue;
                    IBasicLineString bl = pg.Shell;
                    IList<Coordinate> coords = bl.Coordinates;
                    
                    if (CGAlgorithms.IsCounterClockwise(coords))
                    {
                        // Exterior rings need to be clockwise
                        coords.Reverse();
                    }
                   
                    foreach (Coordinate coord in coords)
                    {
                        points.Add(coord);
                    }
                    foreach (IBasicLineString hole in pg.Holes)
                    {
                        parts.Add(points.Count);
                        IList<Coordinate> holeCoords = hole.Coordinates;
                        if (CGAlgorithms.IsCounterClockwise(holeCoords) == false)
                        {
                            // Interior rings need to be counter-clockwise
                            holeCoords.Reverse();
                        }
                        foreach (Coordinate coord in holeCoords)
                        {
                            points.Add(coord);
                        }
                    }
                   
                }
                contentLength += 2 * parts.Count;
                if (Header.ShapeType == ShapeTypes.Polygon)
                {
                    contentLength += points.Count * 8;
                }
                if (Header.ShapeType == ShapeTypes.PolygonM)
                {
                    contentLength += 8; // mmin mmax
                    contentLength += points.Count * 12; // x, y, m
                }
                if (Header.ShapeType == ShapeTypes.PolygonZ)
                {
                    contentLength += 16; // mmin, mmax, zmin, zmax
                    contentLength += points.Count * 16; // x, y, m, z
                }

                //                                              Index File
                //                                              ---------------------------------------------------------
                //                                              Position     Value               Type        Number      Byte Order
                //                                              ---------------------------------------------------------
                indexWriter.Write(offset, false);               // Byte 0     Offset             Integer     1           Big                 
                indexWriter.Write(contentLength, false);        // Byte 4    Content Length      Integer     1           Big

                //                                              X Y Poly Lines
                //                                              ---------------------------------------------------------
                //                                              Position     Value               Type        Number      Byte Order
                //                                              ---------------------------------------------------------
                bbWriter.Write(fid+1, false);                  // Byte 0       Record Number       Integer     1           Big
                bbWriter.Write(contentLength, false);        // Byte 4       Content Length      Integer     1           Big
                bbWriter.Write((int)Header.ShapeType);       // Byte 8       Shape Type 3        Integer     1           Little
                if (Header.ShapeType == ShapeTypes.NullShape)
                {
                    continue;
                }
                
                bbWriter.Write(f.Envelope.Minimum.X);             // Byte 12      Xmin                Double      1           Little
                bbWriter.Write(f.Envelope.Minimum.Y);             // Byte 20      Ymin                Double      1           Little
                bbWriter.Write(f.Envelope.Maximum.X);             // Byte 28      Xmax                Double      1           Little
                bbWriter.Write(f.Envelope.Maximum.Y);             // Byte 36      Ymax                Double      1           Little
                bbWriter.Write(parts.Count);                 // Byte 44      NumParts            Integer     1           Little
                bbWriter.Write(points.Count);                // Byte 48      NumPoints           Integer     1           Little
                foreach (int iPart in parts)                 // Byte 52      Parts               Integer     NumParts    Little 
                {
                    bbWriter.Write(iPart);
                }
                double[] xyVals = new double[points.Count * 2];

                int i = 0;
                foreach (Coordinate coord in points)        // Byte X       Points              Point       NumPoints   Little
                {
                    xyVals[i * 2] = coord.X;
                    xyVals[i * 2 + 1] = coord.Y;
                    i++;
                }
                bbWriter.Write(xyVals);
                
                if (Header.ShapeType == ShapeTypes.PolygonZ)
                {
                    bbWriter.Write(Envelope.Minimum.Z);
                    bbWriter.Write(Envelope.Maximum.Z);
                    double[] zVals = new double[points.Count];
                    for(int ipoint = 0; ipoint < points.Count; i++)        // Byte X       Points              Point       NumPoints   Little
                    {
                        zVals[ipoint] = points[ipoint].Z;
                        ipoint++;
                    }
                    bbWriter.Write(zVals);
                }

                if (Header.ShapeType == ShapeTypes.PolygonM || Header.ShapeType == ShapeTypes.PolygonZ)
                {
                    if(Envelope == null)
                    {
                        bbWriter.Write(0.0);
                        bbWriter.Write(0.0);
                    }
                    else
                    {
                        bbWriter.Write(Envelope.Minimum.M);
                        bbWriter.Write(Envelope.Maximum.M);
                    }
                    
                    double[] mVals = new double[points.Count];
                    for (int ipoint = 0; ipoint < points.Count; i++)        // Byte X       Points              Point       NumPoints   Little
                    {
                        mVals[ipoint] = points[ipoint].M;
                        ipoint++;
                    }
                    bbWriter.Write(mVals);
                }
                

                fid++;
                offset += 4; // header bytes
            }

            bbWriter.Close();
            indexWriter.Close();

            offset += contentLength;
            //offset += 4;
            WriteFileLength(filename, offset);
            WriteFileLength(Header.ShxFilename, 50 + fid * 4);
            UpdateAttributes();
            SaveProjection();
        }