static List<XElement> RenderShapeFile(Shapefile shapefile) { const string pathStyle = "fill:#eeeeee;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"; const string polypathStyle = "fill:#ffffff;fill-opacity:0;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"; var elements = new List<XElement>(); foreach (var feature in shapefile.Features) { if (feature.BasicGeometry is MultiPolygon) { IBasicGeometry basicGeometry = feature.BasicGeometry; var multiPolygon = basicGeometry as MultiPolygon; foreach (var geometry in multiPolygon.Geometries) { var polygon = geometry as Polygon; var polygonPath = GetPolygonPath(polygon); elements.Add(new XElement(XName.Get("path"), new XAttribute(XName.Get("style"), pathStyle), new XAttribute("d", polygonPath))); } } else if (feature.BasicGeometry is Polygon) { var polygon = feature.BasicGeometry as Polygon; var polygonPath = GetPolygonPath(polygon); var xElement = new XElement(XName.Get("path"), new XAttribute(XName.Get("style"), pathStyle), new XAttribute("d", polygonPath)); elements.Add(xElement); } else if (feature.BasicGeometry is LineString) { var lineString = feature.BasicGeometry as LineString; var path = GetLineStringPath(lineString); var xElement = new XElement(XName.Get("polyline"), new XAttribute(XName.Get("style"), polypathStyle), new XAttribute("points", path)); elements.Add(xElement); } else if (feature.BasicGeometry is MultiLineString) { var multiLineString = feature.BasicGeometry as MultiLineString; foreach (var geometry in multiLineString.Geometries) { var lineString = geometry as LineString; var path = GetLineStringPath(lineString); var xElement = new XElement(XName.Get("polyline"), new XAttribute(XName.Get("style"), polypathStyle), new XAttribute("points", path)); elements.Add(xElement); } } else { Console.WriteLine("Unknown basic geometry: " + feature.BasicGeometry.GetType().Name); } } return elements; }
/// <summary> /// Generates a default instance of the data type so that tools have something to write too /// </summary> /// <param name="path"></param> public override void GenerateDefaultOutput(string path) { FeatureSet addedFeatureSet = new Shapefile { Filename = Path.GetDirectoryName(path) + Path.DirectorySeparatorChar + ModelName + ".shp" }; Value = addedFeatureSet; }
public void ClipRasterWithPolygonTest() { if (DotSpatial.Data.DataManager.DefaultDataManager.PreferredProviders.Count == 0) { DotSpatial.Data.Rasters.GdalExtension.GdalRasterProvider lGdalRasterProvider = new DotSpatial.Data.Rasters.GdalExtension.GdalRasterProvider(); } DotSpatial.Data.Shapefile lClipPolygon = DotSpatial.Data.Shapefile.OpenFile(@"C:\Users\Jiri\Desktop\berounka.shp"); DotSpatial.Data.IRaster lGridToClip = DotSpatial.Data.Raster.OpenFile(@"C:\Users\Jiri\Desktop\kriging2.bgd", false); DotSpatial.Data.Raster lGridAfterClip = new DotSpatial.Data.Raster(); lGridAfterClip.Filename = @"C:\Users\Jiri\Desktop\kriging2.bgd"; DotSpatial.Analysis.ClipRaster.ClipRasterWithPolygon(lClipPolygon.Features[0], lGridToClip, lGridAfterClip.Filename); IRaster ras2 = Raster.Open(lGridAfterClip.Filename); Assert.AreEqual(lGridAfterClip.NoDataValue, ras2.NoDataValue); }
/// <summary> /// Populates the given streams for the shp and shx file when not in IndexMode. /// </summary> /// <param name="shpStream">Stream that is used to write the shp file.</param> /// <param name="shxStream">Stream that is used to write the shx file.</param> /// <param name="shapefile">The shapefile that contains the features that are written.</param> /// <param name="addPoints">Function that is used to add the points from the features to the parts and points lists.</param> /// <param name="expectedZType">Indicates which Z-ShapeType the header must have for the z values to be written.</param> /// <param name="expectedMType">Indicates which M-ShapeType the header must have for the m values to be written.</param> /// <param name="withParts">Indicates whether the parts should be written.</param> /// <returns>The lengths of the streams in bytes.</returns> internal static StreamLengthPair PopulateStreamsNotIndexed(Stream shpStream, Stream shxStream, Shapefile shapefile, Action <List <int>, List <Coordinate>, IFeature> addPoints, ShapeType expectedZType, ShapeType expectedMType, bool withParts) { var progressMeter = new ProgressMeter(shapefile.ProgressHandler, "Saving (Not Indexed)...", shapefile.Features.Count); int fid = 0; int offset = 50; // the shapefile header starts at 100 bytes, so the initial offset is 50 words foreach (IFeature f in shapefile.Features) { List <int> parts = new List <int>(); List <Coordinate> points = new List <Coordinate>(); addPoints(parts, points, f); bool isNullShape = false; int contentLength; // null shapes have a contentLength of 2, all other shapes must have the same shape type if (f.Geometry.IsEmpty) { contentLength = 2; isNullShape = true; } else { contentLength = GetContentLength(parts.Count, points.Count, shapefile.Header.ShapeType); } //// 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 //// X Y Poly Lines // --------------------------------------------------------- // Position Value Type Number Byte Order // ------------------------------------------------------- shpStream.WriteBe(fid + 1); // Byte 0 Record Number Integer 1 Big shpStream.WriteBe(contentLength); // Byte 4 Content Length Integer 1 Big if (isNullShape) { shpStream.WriteLe((int)ShapeType.NullShape); // Byte 8 Shape Type 0 Integer 1 Little } else { shpStream.WriteLe((int)shapefile.Header.ShapeType); // Byte 8 Shape Type Integer 1 Little shpStream.WriteLe(f.Geometry.EnvelopeInternal.MinX); // Byte 12 Xmin Double 1 Little shpStream.WriteLe(f.Geometry.EnvelopeInternal.MinY); // Byte 20 Ymin Double 1 Little shpStream.WriteLe(f.Geometry.EnvelopeInternal.MaxX); // Byte 28 Xmax Double 1 Little shpStream.WriteLe(f.Geometry.EnvelopeInternal.MaxY); // Byte 36 Ymax Double 1 Little if (withParts) { shpStream.WriteLe(parts.Count); // Byte 44 NumParts Integer 1 Little } shpStream.WriteLe(points.Count); // Byte 48 NumPoints Integer 1 Little if (withParts) //// Byte 52 Parts Integer NumParts Little { foreach (int part in parts) { shpStream.WriteLe(part); } } double[] xyVals = new double[points.Count * 2]; // Byte X Points Point NumPoints Little for (int i = 0; i < points.Count; i++) { xyVals[i * 2] = points[i].X; xyVals[(i * 2) + 1] = points[i].Y; } shpStream.WriteLe(xyVals); if (shapefile.Header.ShapeType == expectedZType) { // Pandell, 2020-06-23: "NetTopologySuite" version 1.7.5 doesn't have "NetTopologySuite.Geometries.Envelope.Minimum" property // shpStream.WriteLe(f.Geometry.EnvelopeInternal.Minimum.Z); // shpStream.WriteLe(f.Geometry.EnvelopeInternal.Maximum.Z); shpStream.WriteLe(double.NaN); shpStream.WriteLe(double.NaN); double[] zVals = new double[points.Count]; for (int i = 0; i < points.Count; i++) { zVals[i] = points[i].Z; } shpStream.WriteLe(zVals); } if (shapefile.Header.ShapeType == expectedMType || shapefile.Header.ShapeType == expectedZType) { // Pandell, 2020-06-23: "NetTopologySuite" version 1.7.5 doesn't have "NetTopologySuite.Geometries.Envelope.Minimum" property // shpStream.WriteLe(f.Geometry.EnvelopeInternal.Minimum.M); // shpStream.WriteLe(f.Geometry.EnvelopeInternal.Maximum.M); shpStream.WriteLe(double.NaN); shpStream.WriteLe(double.NaN); double[] mVals = new double[points.Count]; for (int i = 0; i < points.Count; i++) { mVals[i] = points[i].M; } shpStream.WriteLe(mVals); } } progressMeter.CurrentValue = fid; fid++; offset += 4; // header bytes offset += contentLength; // adding the content length from each loop calculates the word offset } progressMeter.Reset(); return(new StreamLengthPair { ShpLength = offset, ShxLength = 50 + (fid * 4) }); }
/// <summary> /// Populates the given streams for the shp and shx file when in IndexMode. /// </summary> /// <param name="shpStream">Stream that is used to write the shp file.</param> /// <param name="shxStream">Stream that is used to write the shx file.</param> /// <param name="shapefile">The shapefile that contains the features that are written.</param> /// <param name="expectedZType">Indicates which Z-ShapeType the header must have for the z values to be written.</param> /// <param name="expectedMType">Indicates which M-ShapeType the header must have for the m values to be written.</param> /// <param name="withParts">Indicates whether the parts should be written.</param> /// <returns>The lengths of the streams in bytes.</returns> internal static StreamLengthPair PopulateStreamsIndexed(Stream shpStream, Stream shxStream, Shapefile shapefile, ShapeType expectedZType, ShapeType expectedMType, bool withParts) { int fid = 0; int offset = 50; // the shapefile header starts at 100 bytes, so the initial offset is 50 words foreach (ShapeRange shape in shapefile.ShapeIndices) { // null shapes have a contentLength of 2, all other shapes must have the same shape type int contentLength = shape.ShapeType == ShapeType.NullShape ? 2 : GetContentLength(shape.NumParts, shape.NumPoints, shapefile.Header.ShapeType); //// 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 //// X Y Poly Lines // --------------------------------------------------------- // Position Value Type Number Byte Order // --------------------------------------------------------- shpStream.WriteBe(fid + 1); // Byte 0 Record Number Integer 1 Big shpStream.WriteBe(contentLength); // Byte 4 Content Length Integer 1 Big if (shape.ShapeType == ShapeType.NullShape) { shpStream.WriteLe((int)ShapeType.NullShape); // Byte 8 Shape Type 3 Integer 1 Little } else { shpStream.WriteLe((int)shapefile.Header.ShapeType); // Byte 8 Shape Type 3 Integer 1 Little shpStream.WriteLe(shape.Extent.MinX); // Byte 12 Xmin Double 1 Little shpStream.WriteLe(shape.Extent.MinY); // Byte 20 Ymin Double 1 Little shpStream.WriteLe(shape.Extent.MaxX); // Byte 28 Xmax Double 1 Little shpStream.WriteLe(shape.Extent.MaxY); // Byte 36 Ymax Double 1 Little if (withParts) { shpStream.WriteLe(shape.NumParts); // Byte 44 NumParts Integer 1 Little } shpStream.WriteLe(shape.NumPoints); // Byte 48 NumPoints Integer 1 Little if (withParts) //// Byte 52 Parts Integer NumParts Little { foreach (PartRange part in shape.Parts) { shpStream.WriteLe(part.PartOffset); } } int start = shape.StartIndex; int count = shape.NumPoints; shpStream.WriteLe(shapefile.Vertex, start * 2, count * 2); // Byte X Points Point NumPoints Little if (shapefile.Header.ShapeType == expectedZType) { WriteValues(shapefile.Z, start, count, shpStream); } if (shapefile.Header.ShapeType == expectedMType || shapefile.Header.ShapeType == expectedZType) { WriteValues(shapefile.M, start, count, shpStream); } } fid++; offset += 4; // header bytes offset += contentLength; // adding the content length from each loop calculates the word offset } return(new StreamLengthPair { ShpLength = offset, ShxLength = 50 + (fid * 4) }); }
/// <summary> /// Loads the shapes from the given file into the given shapefile. /// </summary> /// <param name="fileName">Name of the file whose shapes should get loaded.</param> /// <param name="progressHandler">ProgressHandler that shows the progress.</param> /// <param name="shapefile">Shapefile the shapes are loaded into.</param> /// <param name="featureType">FeatureType that should be inside the file.</param> /// <exception cref="ArgumentNullException">Throws an ArgumentNullException, if the shapefile is null.</exception> /// <exception cref="ArgumentException">Throws an ArgumentException, if the FeatureType is Line but the files doesn't contain lines or the FeatureType is Polygon and the file doesn't contain polygons.</exception> /// <exception cref="NotSupportedException">Throws a NotSupportedException, if a FeatureType other than Line or Polygon is passed.</exception> /// <exception cref="FileNotFoundException">Throws a FileNotFoundException, if the file whith the path from fileName doesn't exist.</exception> /// <exception cref="NullReferenceException">Throws a NullReferenceException, if the fileName is null.</exception> internal static void FillLines(string fileName, IProgressHandler progressHandler, Shapefile shapefile, FeatureType featureType) { // Check to ensure that the fileName is the correct shape type switch (featureType) { case FeatureType.Line: if (!CanBeRead(fileName, shapefile, ShapeType.PolyLine, ShapeType.PolyLineM, ShapeType.PolyLineZ)) { return; } break; case FeatureType.Polygon: if (!CanBeRead(fileName, shapefile, ShapeType.Polygon, ShapeType.PolygonM, ShapeType.PolygonZ)) { return; } break; default: throw new NotSupportedException(DataStrings.ShapeType0NotSupported); } // Reading the headers gives us an easier way to track the number of shapes and their overall length etc. var header = shapefile.Header; var shapeHeaders = shapefile.ReadIndexFile(fileName); int numShapes = shapeHeaders.Count; bool isM = false, isZ = false; switch (header.ShapeType) { case ShapeType.PolyLineM: case ShapeType.PolygonM: isM = true; break; case ShapeType.PolyLineZ: case ShapeType.PolygonZ: isZ = true; isM = true; break; } int totalPointsCount = 0; int totalPartsCount = 0; var shapeIndices = new List <ShapeRange>(numShapes); var progressMeter = new ProgressMeter(progressHandler, "Reading from " + Path.GetFileName(fileName)) { StepPercent = 5 }; using (var reader = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 65536)) { var boundsBytes = new byte[4 * 8]; var bounds = new double[4]; for (int shp = 0; shp < numShapes; shp++) { progressMeter.CurrentPercent = (int)(shp * 50.0 / numShapes); // Read from the index file because some deleted records // might still exist in the .shp file. long offset = shapeHeaders[shp].ByteOffset; reader.Seek(offset, SeekOrigin.Begin); var shape = new ShapeRange(featureType, shapefile.CoordinateType) { RecordNumber = reader.ReadInt32(Endian.BigEndian), ContentLength = reader.ReadInt32(Endian.BigEndian), ShapeType = (ShapeType)reader.ReadInt32(), StartIndex = totalPointsCount }; Debug.Assert(shape.RecordNumber == shp + 1, "The shapes record number should equal" + shp + 1); if (shape.ShapeType != ShapeType.NullShape) { // Bounds reader.Read(boundsBytes, 0, boundsBytes.Length); Buffer.BlockCopy(boundsBytes, 0, bounds, 0, boundsBytes.Length); shape.Extent.MinX = bounds[0]; shape.Extent.MinY = bounds[1]; shape.Extent.MaxX = bounds[2]; shape.Extent.MaxY = bounds[3]; // Num Parts shape.NumParts = reader.ReadInt32(); totalPartsCount += shape.NumParts; // Num Points shape.NumPoints = reader.ReadInt32(); totalPointsCount += shape.NumPoints; } shapeIndices.Add(shape); } var vert = new double[totalPointsCount * 2]; var vertInd = 0; var parts = new int[totalPartsCount]; var partsInd = 0; double[] mArray = null, zArray = null; if (isM) { mArray = new double[totalPointsCount]; } int mArrayInd = 0; if (isZ) { zArray = new double[totalPointsCount]; } int zArrayInd = 0; int partsOffset = 0; for (int shp = 0; shp < numShapes; shp++) { progressMeter.CurrentPercent = (int)(50 + (shp * 50.0 / numShapes)); var shape = shapeIndices[shp]; if (shape.ShapeType == ShapeType.NullShape) { continue; } reader.Seek(shapeHeaders[shp].ByteOffset, SeekOrigin.Begin); reader.Seek((3 * 4) + 32 + (2 * 4), SeekOrigin.Current); // Skip first bytes (Record Number, Content Length, Shapetype + BoundingBox + NumParts, NumPoints) // Read parts var partsBytes = reader.ReadBytes(4 * shape.NumParts); // Numparts * Integer(4) = existing Parts Buffer.BlockCopy(partsBytes, 0, parts, partsInd, partsBytes.Length); partsInd += 4 * shape.NumParts; // Read points var pointsBytes = reader.ReadBytes(8 * 2 * shape.NumPoints); // Numpoints * Point (X(8) + Y(8)) Buffer.BlockCopy(pointsBytes, 0, vert, vertInd, pointsBytes.Length); vertInd += 8 * 2 * shape.NumPoints; // Fill parts shape.Parts.Capacity = shape.NumParts; for (int part = 0; part < shape.NumParts; part++) { int endIndex = shape.NumPoints + shape.StartIndex; int startIndex = parts[partsOffset + part] + shape.StartIndex; if (part < shape.NumParts - 1) { endIndex = parts[partsOffset + part + 1] + shape.StartIndex; } int count = endIndex - startIndex; var partR = new PartRange(vert, shape.StartIndex, parts[partsOffset + part], featureType) { NumVertices = count }; shape.Parts.Add(partR); } partsOffset += shape.NumParts; // Fill M and Z arrays switch (header.ShapeType) { case ShapeType.PolyLineM: case ShapeType.PolygonM: if (shape.ContentLength * 2 > 44 + (4 * shape.NumParts) + (16 * shape.NumPoints)) { var mExt = (IExtentM)shape.Extent; mExt.MinM = reader.ReadDouble(); mExt.MaxM = reader.ReadDouble(); var mBytes = reader.ReadBytes(8 * shape.NumPoints); Buffer.BlockCopy(mBytes, 0, mArray, mArrayInd, mBytes.Length); mArrayInd += 8 * shape.NumPoints; } break; case ShapeType.PolyLineZ: case ShapeType.PolygonZ: var zExt = (IExtentZ)shape.Extent; zExt.MinZ = reader.ReadDouble(); zExt.MaxZ = reader.ReadDouble(); var zBytes = reader.ReadBytes(8 * shape.NumPoints); Buffer.BlockCopy(zBytes, 0, zArray, zArrayInd, zBytes.Length); zArrayInd += 8 * 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 (shape.ContentLength * 2 > 60 + (4 * shape.NumParts) + (24 * shape.NumPoints)) { goto case ShapeType.PolyLineM; } break; } } if (isM) { shapefile.M = mArray; } if (isZ) { shapefile.Z = zArray; } shapefile.ShapeIndices = shapeIndices; shapefile.Vertex = vert; } progressMeter.Reset(); }
private void btnApplyColorScheme_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog1 = new OpenFileDialog(); Shapefile sf = new Shapefile(); openFileDialog1.Filter = "Shapefiles|*.shp"; if (openFileDialog1.ShowDialog() == DialogResult.OK) { sf = Shapefile.OpenFile(openFileDialog1.FileName, null); App.Map.AddLayer(sf.Filename); App.Map.Refresh(); } }
/// <summary> /// Creates a default output locations for tools. /// </summary> /// <param name="par"></param> public void GenerateDefaultOutput(Parameter par) { IFeatureSet addedFeatureSet; switch (par.ParamType) { case "DotSpatial FeatureSet Param": addedFeatureSet = new Shapefile { Filename = Path.GetTempPath() + Path.DirectorySeparatorChar + par.ModelName + ".shp" }; par.Value = addedFeatureSet; break; case "DotSpatial LineFeatureSet Param": addedFeatureSet = new LineShapefile { Filename = Path.GetTempPath() + Path.DirectorySeparatorChar + par.ModelName + ".shp" }; par.Value = addedFeatureSet; break; case "DotSpatial PointFeatureSet Param": addedFeatureSet = new PointShapefile { Filename = Path.GetTempPath() + Path.DirectorySeparatorChar + par.ModelName + ".shp" }; par.Value = addedFeatureSet; break; case "DotSpatial PolygonFeatureSet Param": addedFeatureSet = new PolygonShapefile { Filename = Path.GetTempPath() + Path.DirectorySeparatorChar + par.ModelName + ".shp" }; par.Value = addedFeatureSet; break; case "DotSpatial Raster Param": break; default: par.GenerateDefaultOutput(Path.GetTempPath()); break; } }
/// <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); }
private void btnAddData_Click(object sender, EventArgs e) { ///////////////////////////////// //Replace with something that uses the default data provider SaveFileDialog sfd = new SaveFileDialog(); sfd.OverwritePrompt = true; sfd.Filter = "Shape Files|*.shp"; if (sfd.ShowDialog() == DialogResult.OK) { IFeatureSet _addedFeatureSet = new Shapefile(); _addedFeatureSet.Filename = sfd.FileName; //If the features set is null do nothing the user probably hit cancel if (_addedFeatureSet == null) return; //If the feature type is good save it //This inserts the new featureset into the list textBox1.Text = Path.GetFileNameWithoutExtension(_addedFeatureSet.Filename); Param.Value = _addedFeatureSet; base.Status = ToolStatus.Ok; LightTipText = ModelingMessageStrings.FeaturesetValid; } }
/// <summary> /// Merge basins using IGeometry, and only converting each shape once /// </summary> /// <param name="shed"></param> /// <param name="drainage"></param> /// <returns></returns> private static IGeometry mergeBasinsByDrainageI(Shapefile shed, BinTree drainage) { if (drainage == null) return null; IGeometry left = mergeBasinsByDrainageI(shed, drainage.left); IGeometry right = mergeBasinsByDrainageI(shed, drainage.right); IFeature outlet = shed.get_Shape(drainage.val); // will this work? IGeometry outg = outlet.BasicGeometry as IGeometry; if (left == null) { if (right == null) return outg; else return right.Union(outg); } else { if (right == null) return left.Union(outg); else return left.Union(right.Union(outg)); } }
private static void getJoinShapesFromSubBasin(Shapefile shed, int sindx, ArrayList shapeIdxList) { int dsNodeFieldNum = 3; int USlink1FieldNum = 5; int USlink2FieldNum = 6; Stack currStack = new Stack(); int currLink1ID; int currLink2ID; int currIdx; int currLinkIdx; shapeIdxList.Clear(); shapeIdxList.Add(sindx); currLink1ID = int.Parse(shed.get_CellValue(USlink1FieldNum, sindx).ToString()); currLink2ID = int.Parse(shed.get_CellValue(USlink2FieldNum, sindx).ToString()); if (currLink1ID != -1) { currLinkIdx = GetBasinIndexByID(shed, currLink1ID); if (currLinkIdx != -1) { currStack.Push(currLinkIdx); } } if (currLink2ID != -1) { currLinkIdx = GetBasinIndexByID(shed, currLink2ID); if (currLinkIdx != -1) { currStack.Push(currLinkIdx); } } while (currStack.Count > 0) { currIdx = int.Parse(currStack.Pop().ToString()); if (int.Parse(shed.get_CellValue(dsNodeFieldNum, currIdx).ToString()) == -1) { shapeIdxList.Add(currIdx); currLink1ID = int.Parse(shed.get_CellValue(USlink1FieldNum, currIdx).ToString()); currLink2ID = int.Parse(shed.get_CellValue(USlink2FieldNum, currIdx).ToString()); if (currLink1ID != -1) { currLinkIdx = GetBasinIndexByID(shed, currLink1ID); if (currLinkIdx != -1) { currStack.Push(currLinkIdx); } } if (currLink2ID != -1) { currLinkIdx = GetBasinIndexByID(shed, currLink2ID); if (currLinkIdx != -1) { currStack.Push(currLinkIdx); } } } } }
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); } }
/// <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)); }
/// <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); }
/// <summary> /// This open method is only called if this plugin has been given priority for one /// of the file extensions supported in the DialogReadFilter property supplied by /// this control. Failing to provide a DialogReadFilter will result in this plugin /// being added to the list of DataProviders being supplied under the Add Other Data /// option in the file menu. /// </summary> /// <param name="fileName">A string specifying the complete path and extension of the file to open.</param> /// <returns>A List of IDataSets to be added to the Map. These can also be groups of datasets.</returns> public virtual IFeatureSet Open(string fileName) { return(Shapefile.OpenFile(fileName)); }
internal static void FillLines(string fileName, IProgressHandler progressHandler, Shapefile shapefile, FeatureType featureType) { // Check to ensure the fileName is not null if (fileName == null) { throw new NullReferenceException(DataStrings.ArgumentNull_S.Replace("%S", "fileName")); } if (shapefile == null) throw new ArgumentNullException("shapefile"); if (File.Exists(fileName) == false) { throw new FileNotFoundException(DataStrings.FileNotFound_S.Replace("%S", fileName)); } if (featureType != FeatureType.Line && featureType != FeatureType.Polygon) { throw new NotSupportedException(); } var header = shapefile.Header; // 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.FileNotLines_S.Replace("%S", fileName)); } break; } if (new FileInfo(fileName).Length == 100) { // the file is empty so we are done reading return; } // Reading the headers gives us an easier way to track the number of shapes and their overall length etc. var shapeHeaders = shapefile.ReadIndexFile(fileName); int numShapes = shapeHeaders.Count; bool isM = false, isZ = false; switch (header.ShapeType) { case ShapeType.PolyLineM: case ShapeType.PolygonM: isM = true; break; case ShapeType.PolyLineZ: case ShapeType.PolygonZ: isZ = true; isM = true; break; } int totalPointsCount = 0; int totalPartsCount = 0; var shapeIndices = new List<ShapeRange>(numShapes); var progressMeter = new ProgressMeter(progressHandler, "Reading from " + Path.GetFileName(fileName)) { StepPercent = 5 }; using (var reader = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 65536)) { var boundsBytes = new byte[4 * 8]; var bounds = new double[4]; for (int shp = 0; shp < numShapes; shp++) { progressMeter.CurrentPercent = (int)(shp * 50.0 / numShapes); // Read from the index file because some deleted records // might still exist in the .shp file. long offset = (shapeHeaders[shp].ByteOffset); reader.Seek(offset, SeekOrigin.Begin); var shape = new ShapeRange(featureType, shapefile.CoordinateType) { RecordNumber = reader.ReadInt32(Endian.BigEndian), ContentLength = reader.ReadInt32(Endian.BigEndian), ShapeType = (ShapeType)reader.ReadInt32(), StartIndex = totalPointsCount }; Debug.Assert(shape.RecordNumber == shp + 1); if (shape.ShapeType != ShapeType.NullShape) { // Bounds reader.Read(boundsBytes, 0, boundsBytes.Length); Buffer.BlockCopy(boundsBytes, 0, bounds, 0, boundsBytes.Length); shape.Extent.MinX = bounds[0]; shape.Extent.MinY = bounds[1]; shape.Extent.MaxX = bounds[2]; shape.Extent.MaxY = bounds[3]; // Num Parts shape.NumParts = reader.ReadInt32(); totalPartsCount += shape.NumParts; // Num Points shape.NumPoints = reader.ReadInt32(); totalPointsCount += shape.NumPoints; } shapeIndices.Add(shape); } var vert = new double[totalPointsCount * 2]; var vertInd = 0; var parts = new int[totalPartsCount]; var partsInd = 0; double[] mArray = null, zArray = null; if (isM) { mArray = new double[totalPointsCount]; } int mArrayInd = 0; if (isZ) { zArray = new double[totalPointsCount]; } int zArrayInd = 0; int partsOffset = 0; for (int shp = 0; shp < numShapes; shp++) { progressMeter.CurrentPercent = (int)(50 + shp * 50.0 / numShapes); var shape = shapeIndices[shp]; if (shape.ShapeType == ShapeType.NullShape) continue; reader.Seek(shapeHeaders[shp].ByteOffset, SeekOrigin.Begin); reader.Seek(3 * 4 + 32 + 2 * 4, SeekOrigin.Current); // Skip first bytes // Read parts var partsBytes = reader.ReadBytes(4 * shape.NumParts); Buffer.BlockCopy(partsBytes, 0, parts, partsInd, partsBytes.Length); partsInd += 4 * shape.NumParts; // Read points var pointsBytes = reader.ReadBytes(8 * 2 * shape.NumPoints); Buffer.BlockCopy(pointsBytes, 0, vert, vertInd, pointsBytes.Length); vertInd += 8 * 2 * shape.NumPoints; // Fill parts shape.Parts.Capacity = shape.NumParts; for (int part = 0; part < shape.NumParts; part++) { int endIndex = shape.NumPoints + shape.StartIndex; int startIndex = parts[partsOffset + part] + shape.StartIndex; if (part < shape.NumParts - 1) { endIndex = parts[partsOffset + part + 1] + shape.StartIndex; } int count = endIndex - startIndex; var partR = new PartRange(vert, shape.StartIndex, parts[partsOffset + part], featureType) { NumVertices = count }; shape.Parts.Add(partR); } partsOffset += shape.NumParts; // Fill M and Z arrays switch (header.ShapeType) { case ShapeType.PolyLineM: case ShapeType.PolygonM: if (shape.ContentLength * 2 > 44 + 4 * shape.NumParts + 16 * shape.NumPoints) { var mExt = (IExtentM)shape.Extent; mExt.MinM = reader.ReadDouble(); mExt.MaxM = reader.ReadDouble(); var mBytes = reader.ReadBytes(8 * shape.NumPoints); Buffer.BlockCopy(mBytes, 0, mArray, mArrayInd, mBytes.Length); mArrayInd += 8 * shape.NumPoints; } break; case ShapeType.PolyLineZ: case ShapeType.PolygonZ: var zExt = (IExtentZ)shape.Extent; zExt.MinZ = reader.ReadDouble(); zExt.MaxZ = reader.ReadDouble(); var zBytes = reader.ReadBytes(8 * shape.NumPoints); Buffer.BlockCopy(zBytes, 0, zArray, zArrayInd, zBytes.Length); zArrayInd += 8 * 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 (shape.ContentLength * 2 > 60 + 4 * shape.NumParts + 24 * shape.NumPoints) { goto case ShapeType.PolyLineM; } break; } } if (isM) shapefile.M = mArray; if (isZ) shapefile.Z = zArray; shapefile.ShapeIndices = shapeIndices; shapefile.Vertex = vert; } progressMeter.Reset(); }
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); } }