/// <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(); }