private static void ReadMultiPolygon(Stream data, FeatureSetPack results) { int numPolygons = ReadInt32(data); ShapeRange lShp = new ShapeRange(FeatureType.Polygon); List<double[]> rings = new List<double[]>(); int partOffset = 0; for (int iPoly = 0; iPoly < numPolygons; iPoly++) { data.Seek(5, SeekOrigin.Current); // endian and geometry type int numRings = ReadInt32(data); for (int iRing = 0; iRing < numRings; iRing++) { int numPoints = ReadInt32(data); // ring structures are like a linestring without the final point. double[] coords = ReadDouble(data, 2 * numPoints); if (iRing == 0) { // By shapefile standard, the shell should be clockwise if (IsCounterClockwise(coords)) coords = ReverseCoords(coords); } else { // By shapefile standard, the holes should be counter clockwise. if (!IsCounterClockwise(coords)) coords = ReverseCoords(coords); } PartRange lPrt = new PartRange(FeatureType.Polygon); lPrt.PartOffset = partOffset; lPrt.NumVertices = numPoints; lShp.Parts.Add(lPrt); partOffset += coords.Length / 2; rings.Add(coords); } } double[] allVertices = new double[partOffset * 2]; int offset = 0; foreach (double[] ring in rings) { Array.Copy(ring, 0, allVertices, offset, ring.Length); offset += ring.Length; } results.Add(allVertices, lShp); }
/// <summary> /// Initializes a new instance of the <see cref="FeatureSet"/> class. /// This creates a new featureset by checking each row of the table. If the WKB feature /// type matches the specified featureTypes, then it will copy that. /// </summary> /// <param name="wkbTable"> /// </param> /// <param name="wkbColumnIndex"> /// </param> /// <param name="indexed"> /// </param> /// <param name="type"> /// </param> public FeatureSet(DataTable wkbTable, int wkbColumnIndex, bool indexed, FeatureType type) : this() { if (IndexMode) { // Assume this DataTable has WKB in column[0] and the rest of the columns are attributes. FeatureSetPack result = new FeatureSetPack(); foreach (DataRow row in wkbTable.Rows) { byte[] data = (byte[])row[0]; MemoryStream ms = new MemoryStream(data); WkbFeatureReader.ReadFeature(ms, result); } // convert lists of arrays into a single vertex array for each shape type. result.StopEditing(); // Make sure all the same columns exist in the same order result.Polygons.CopyTableSchema(wkbTable); // Assume that all the features happened to be polygons foreach (DataRow row in wkbTable.Rows) { // Create a new row DataRow dest = result.Polygons.DataTable.NewRow(); dest.ItemArray = row.ItemArray; } } }
private static void ReadLineString(Stream data, FeatureSetPack results) { int count = ReadInt32(data); double[] coords = ReadDouble(data, 2 * count); ShapeRange lShp = new ShapeRange(FeatureType.Line); PartRange lPrt = new PartRange(FeatureType.Line); lPrt.NumVertices = count; lShp.Parts.Add(lPrt); results.Add(coords, lShp); }
private static void ReadMultiLineString(Stream data, FeatureSetPack results) { int numLineStrings = ReadInt32(data); ShapeRange shp = new ShapeRange(FeatureType.Line); List<double[]> strings = new List<double[]>(); int partOffset = 0; for (int iString = 0; iString < numLineStrings; iString++) { // Each of these needs to read a full WKBLineString data.Seek(5, SeekOrigin.Current); //ignore header int numPoints = ReadInt32(data); double[] coords = ReadDouble(data, 2 * numPoints); PartRange lPrt = new PartRange(FeatureType.Line); lPrt.PartOffset = partOffset; lPrt.NumVertices = numPoints; shp.Parts.Add(lPrt); partOffset += coords.Length / 2; strings.Add(coords); } double[] allVertices = new double[partOffset * 2]; int offset = 0; foreach (double[] ring in strings) { Array.Copy(ring, 0, allVertices, offset, ring.Length); offset += ring.Length; } results.Add(allVertices, shp); }
private static void ReadMultiPoint(Stream data, FeatureSetPack results) { int count = ReadInt32(data); ShapeRange sr = new ShapeRange(FeatureType.MultiPoint); PartRange prt = new PartRange(FeatureType.MultiPoint); prt.NumVertices = count; sr.Parts.Add(prt); double[] vertices = new double[count * 2]; for (int iPoint = 0; iPoint < count; iPoint++) { data.ReadByte(); // ignore endian ReadInt32(data); // ignore geometry type double[] coord = ReadDouble(data, 2); Array.Copy(coord, 0, vertices, iPoint * 2, 2); } results.Add(vertices, sr); }
/// <summary> /// This assumes that the byte order and shapetype have already been read. /// </summary> /// <param name="data"></param> /// <param name="results"></param> private static void ReadPoint(Stream data, FeatureSetPack results) { ShapeRange sr = new ShapeRange(FeatureType.MultiPoint); PartRange prt = new PartRange(FeatureType.MultiPoint); prt.NumVertices = 1; sr.Parts.Add(prt); double[] coord = ReadDouble(data, 2); results.Add(coord, sr); }
private static void ReadGeometryCollection(Stream data, FeatureSetPack results) { int numGeometries = ReadInt32(data); // Don't worry about "multi-parting" these. Simply create a separate shape // entry for every single geometry here since we have to split out the features // based on feature type. (currently we don't have a mixed feature type for drawing.) for (int i = 0; i < numGeometries; i++) { _endian = (ByteOrder)data.ReadByte(); WkbGeometryType type = (WkbGeometryType)ReadInt32(data); switch (type) { case WkbGeometryType.Point: ReadPoint(data, results); return; case WkbGeometryType.LineString: ReadLineString(data, results); return; case WkbGeometryType.Polygon: ReadPolygon(data, results); break; case WkbGeometryType.MultiPoint: ReadMultiPoint(data, results); break; case WkbGeometryType.MultiLineString: ReadMultiLineString(data, results); break; case WkbGeometryType.MultiPolygon: ReadMultiPolygon(data, results); break; case WkbGeometryType.GeometryCollection: ReadGeometryCollection(data, results); break; } } }
/// <summary> /// Reads only a single geometry into a feature. This may be a multi-part geometry. /// </summary> /// <param name="data"></param> /// <param name="results"></param> public static void ReadFeature(Stream data, FeatureSetPack results) { _endian = (ByteOrder)data.ReadByte(); WkbGeometryType type = (WkbGeometryType)ReadInt32(data); switch (type) { case WkbGeometryType.Point: ReadPoint(data, results); return; case WkbGeometryType.LineString: ReadLineString(data, results); return; case WkbGeometryType.Polygon: ReadPolygon(data, results); break; case WkbGeometryType.MultiPoint: ReadMultiPoint(data, results); break; case WkbGeometryType.MultiLineString: ReadMultiLineString(data, results); break; case WkbGeometryType.MultiPolygon: ReadMultiPolygon(data, results); break; case WkbGeometryType.GeometryCollection: ReadGeometryCollection(data, results); break; } }
/// <summary> /// Gets a FeatureSetPack from the wkb /// </summary> /// <param name="data"></param> /// <returns></returns> public static FeatureSetPack GetFeatureSets(Stream data) { FeatureSetPack result = new FeatureSetPack(); while (data.Position < data.Length) { ReadFeature(data, result); } result.StopEditing(); return result; }