private void loadShapeFile(string shapeFilePath) { FileInfo shapeFile = new FileInfo(shapeFilePath); FileInfo dbaseFile = new FileInfo(shapeFile.FullName.Replace(".shp", ".dbf")); Random random = new Random(shapeFile.Name.GetHashCode()); ArrayList metaValues = new ArrayList(); if (m_ShapeTileArgs.DataKey != null && dbaseFile.Exists) { using (BinaryReader dbfReader = new BinaryReader(new BufferedStream(dbaseFile.OpenRead()), Encoding.ASCII)) { // First Read 32-byte file header int bytesRead = 0; byte dbfVersion = dbfReader.ReadByte(); byte updateYear = dbfReader.ReadByte(); byte updateMonth = dbfReader.ReadByte(); byte updateDay = dbfReader.ReadByte(); int numberRecords = dbfReader.ReadInt32(); short headerLength = dbfReader.ReadInt16(); short recordLength = dbfReader.ReadInt16(); byte[] reserved = dbfReader.ReadBytes(20); bytesRead += 32; int numberFields = (headerLength - 33)/32; // Read Field Descriptor Array DBF_Field_Header[] fieldHeaders = new DBF_Field_Header[numberFields]; for (int i = 0; i < numberFields; i++) { char[] fieldNameChars = dbfReader.ReadChars(10); char fieldNameTerminator = dbfReader.ReadChar(); string fn = new string(fieldNameChars); fieldHeaders[i].FieldName = fn.Trim().Replace(" ", ""); fieldHeaders[i].FieldType = dbfReader.ReadChar(); byte[] reserved1 = dbfReader.ReadBytes(4); if (String.Compare(fieldHeaders[i].FieldName.Trim(), m_ShapeTileArgs.DataKey, true) == 0) { m_ShapeTileArgs.DataKey = fieldHeaders[i].FieldName; if (fieldHeaders[i].FieldType == 'N') { m_ShapeTileArgs.UseScalar = true; } else { m_ShapeTileArgs.UseScalar = false; } } fieldHeaders[i].FieldLength = dbfReader.ReadByte(); byte[] reserved2 = dbfReader.ReadBytes(15); bytesRead += 32; } byte headerTerminator = dbfReader.ReadByte(); double scalarMin = double.MaxValue; double scalarMax = double.MinValue; for (int i = 0; i < numberRecords; i++) { // Shapefile_Polygon curPoly = (Shapefile_Polygon)this.m_ShapeTileArgs.ShapeRecords[i]; byte isValid = dbfReader.ReadByte(); for (int j = 0; j < fieldHeaders.Length; j++) { char[] fieldDataChars = dbfReader.ReadChars(fieldHeaders[j].FieldLength); string fieldData = new string(fieldDataChars); if (fieldHeaders[j].FieldName == m_ShapeTileArgs.DataKey) { metaValues.Add(fieldData); if (fieldHeaders[j].FieldType == 'N') { try { if (m_ShapeTileArgs.ScaleMin == double.NaN || m_ShapeTileArgs.ScaleMax == double.NaN) { double data = double.Parse(fieldData); if (m_ShapeTileArgs.ScaleMin == double.NaN && data < scalarMin) { scalarMin = data; } if (m_ShapeTileArgs.ScaleMax == double.NaN && data > scalarMax) { scalarMax = data; } } } catch (Exception ex) { Log.Write(ex); } } else { if (!m_ShapeTileArgs.ColorAssignments.Contains(fieldData)) { Color newColor = Color.FromArgb(1 + random.Next(254), 1 + random.Next(254), 1 + random.Next(254)); m_ShapeTileArgs.ColorAssignments.Add(fieldData, newColor); } } } } if (m_ShapeTileArgs.UseScalar && m_ShapeTileArgs.ScaleMin == double.NaN) { m_ShapeTileArgs.ScaleMin = scalarMin; } if (m_ShapeTileArgs.UseScalar && m_ShapeTileArgs.ScaleMax == double.NaN) { m_ShapeTileArgs.ScaleMax = scalarMax; } } } } FileInfo shapeFileInfo = new FileInfo(shapeFilePath); using (FileStream fs = File.OpenRead(shapeFileInfo.FullName)) { using (BinaryReader reader = new BinaryReader(new BufferedStream(fs))) { //get file header info // Big-Endian Integer File Type byte[] fileTypeBytes = reader.ReadBytes(4); int fileType = 16*16*16*16*16*16*fileTypeBytes[0] + 16*16*16*16*fileTypeBytes[1] + 16*16*fileTypeBytes[2] + fileTypeBytes[3]; byte[] unused1 = reader.ReadBytes(5*4); byte[] fileLengthBytes = reader.ReadBytes(4); int fileLength = 16*16*16*16*16*16*fileLengthBytes[0] + 16*16*16*16*fileLengthBytes[1] + 16*16*fileLengthBytes[2] + fileLengthBytes[3]; int version = reader.ReadInt32(); int shapeType = reader.ReadInt32(); m_BoundingBoxXMin = reader.ReadDouble(); m_BoundingBoxYMin = reader.ReadDouble(); m_BoundingBoxXMax = reader.ReadDouble(); m_BoundingBoxYMax = reader.ReadDouble(); m_BoundingBoxZMin = reader.ReadDouble(); m_BoundingBoxZMax = reader.ReadDouble(); m_BoundingBoxMMin = reader.ReadDouble(); m_BoundingBoxMMax = reader.ReadDouble(); //start reading records... int bytesRead = 100; int counter = 0; while (bytesRead < shapeFileInfo.Length) { ArrayList pendingPoints = new ArrayList(); //read record header byte[] recordNumberBytes = reader.ReadBytes(4); byte[] contentLengthBytes = reader.ReadBytes(4); int recordNumber = 16*16*16*16*16*16*recordNumberBytes[0] + 16*16*16*16*recordNumberBytes[1] + 16*16*recordNumberBytes[2] + recordNumberBytes[3]; int contentLength = 16*16*16*16*16*16*contentLengthBytes[0] + 16*16*16*16*contentLengthBytes[1] + 16*16*contentLengthBytes[2] + contentLengthBytes[3]; //read shape type to determine record structure and content int recordShapeType = reader.ReadInt32(); ShapeFileRecord newRecord = new ShapeFileRecord(); if (recordShapeType == 0) //Null shape type -- generally used as a placeholder { newRecord.Null = new Shapefile_Null(); } else if (recordShapeType == 1) //Point shape type { newRecord.Point = new Shapefile_Point(); newRecord.Point.X = reader.ReadDouble(); newRecord.Point.Y = reader.ReadDouble(); pendingPoints.Add(MathEngine.SphericalToCartesian(newRecord.Point.Y, newRecord.Point.X, m_ShapeTileArgs.LayerRadius)); } else if (recordShapeType == 8) //Multi-point shape type { newRecord.MultiPoint = new Shapefile_MultiPoint(); newRecord.MultiPoint.BoundingBox.West = reader.ReadDouble(); newRecord.MultiPoint.BoundingBox.South = reader.ReadDouble(); newRecord.MultiPoint.BoundingBox.East = reader.ReadDouble(); newRecord.MultiPoint.BoundingBox.North = reader.ReadDouble(); newRecord.MultiPoint.NumPoints = reader.ReadInt32(); newRecord.MultiPoint.Points = new Shapefile_Point[newRecord.MultiPoint.NumPoints]; for (int i = 0; i < newRecord.MultiPoint.NumPoints; i++) { newRecord.MultiPoint.Points[i] = new Shapefile_Point(); newRecord.MultiPoint.Points[i].X = reader.ReadDouble(); newRecord.MultiPoint.Points[i].Y = reader.ReadDouble(); pendingPoints.Add(MathEngine.SphericalToCartesian(newRecord.MultiPoint.Points[i].Y, newRecord.MultiPoint.Points[i].X, m_ShapeTileArgs.LayerRadius)); } } else if (recordShapeType == 3) { newRecord.PolyLine = new Shapefile_PolyLine(); newRecord.PolyLine.BoundingBox.West = reader.ReadDouble(); newRecord.PolyLine.BoundingBox.South = reader.ReadDouble(); newRecord.PolyLine.BoundingBox.East = reader.ReadDouble(); newRecord.PolyLine.BoundingBox.North = reader.ReadDouble(); newRecord.PolyLine.NumParts = reader.ReadInt32(); newRecord.PolyLine.NumPoints = reader.ReadInt32(); newRecord.PolyLine.Parts = new int[newRecord.PolyLine.NumParts]; for (int i = 0; i < newRecord.PolyLine.Parts.Length; i++) { newRecord.PolyLine.Parts[i] = reader.ReadInt32(); } newRecord.PolyLine.Points = new Shapefile_Point[newRecord.PolyLine.NumPoints]; for (int i = 0; i < newRecord.PolyLine.Points.Length; i++) { newRecord.PolyLine.Points[i] = new Shapefile_Point(); newRecord.PolyLine.Points[i].X = reader.ReadDouble(); newRecord.PolyLine.Points[i].Y = reader.ReadDouble(); } } else if (recordShapeType == 5) { newRecord.Polygon = new Shapefile_Polygon(); newRecord.Polygon.BoundingBox.West = reader.ReadDouble(); newRecord.Polygon.BoundingBox.South = reader.ReadDouble(); newRecord.Polygon.BoundingBox.East = reader.ReadDouble(); newRecord.Polygon.BoundingBox.North = reader.ReadDouble(); newRecord.Polygon.NumParts = reader.ReadInt32(); newRecord.Polygon.NumPoints = reader.ReadInt32(); newRecord.Polygon.Parts = new int[newRecord.Polygon.NumParts]; for (int i = 0; i < newRecord.Polygon.Parts.Length; i++) { newRecord.Polygon.Parts[i] = reader.ReadInt32(); } newRecord.Polygon.Points = new Shapefile_Point[newRecord.Polygon.NumPoints]; for (int i = 0; i < newRecord.Polygon.Points.Length; i++) { newRecord.Polygon.Points[i] = new Shapefile_Point(); newRecord.Polygon.Points[i].X = reader.ReadDouble(); newRecord.Polygon.Points[i].Y = reader.ReadDouble(); } } bool ignoreRecord = false; if (metaValues != null && metaValues.Count > 0) { newRecord.Value = metaValues[counter]; if (m_ShapeTileArgs.ActiveDataValues != null) { ignoreRecord = true; if (m_ShapeTileArgs.UseScalar) { double currentValue = double.Parse(newRecord.Value.ToString()); foreach (string activeValueString in m_ShapeTileArgs.ActiveDataValues) { double activeValue = double.Parse(activeValueString); if (activeValue == currentValue) { ignoreRecord = false; break; } } } else { string currentValue = (string) newRecord.Value; foreach (string activeValue in m_ShapeTileArgs.ActiveDataValues) { if (String.Compare(activeValue.Trim(), currentValue.Trim(), true) == 0) { ignoreRecord = false; break; } } } } else { if (m_ShapeTileArgs.UseScalar) { double currentValue = double.Parse(newRecord.Value.ToString()); if (m_ScalarFilterMin != double.NaN) { if (currentValue < m_ScalarFilterMin) { ignoreRecord = true; } } if (m_ScalarFilterMax != double.NaN) { if (currentValue > m_ScalarFilterMax) { ignoreRecord = true; } } if (m_ShapeTileArgs.NoDataValues != null) { foreach (string noDataValueString in m_ShapeTileArgs.NoDataValues) { double noDataValue = double.Parse(noDataValueString); //TODO: might consider using epsilon if floating point errors occur if (noDataValue == currentValue) { ignoreRecord = true; break; } } } } else { string currentValue = (string) newRecord.Value; if (m_ShapeTileArgs.NoDataValues != null) { foreach (string noDataValue in m_ShapeTileArgs.NoDataValues) { if (String.Compare(currentValue.Trim(), noDataValue.Trim(), true) == 0) { ignoreRecord = true; break; } } } } } } if (!ignoreRecord) { m_ShapeTileArgs.ShapeRecords.Add(newRecord); if (pendingPoints.Count > 0) { foreach (Vector3 v in pendingPoints) { m_PointList.Add(v); } } } bytesRead += 8 + contentLength*2; counter++; } } } }
private bool isShapeRecordInBounds(GeographicBoundingBox geoBB, ShapeFileRecord record) { if (record.Point != null) { if (record.Point.X < geoBB.West || record.Point.X > geoBB.East || record.Point.Y > geoBB.North || record.Point.Y < geoBB.South) { return false; } else { return true; } } else if (record.MultiPoint != null) { if (record.MultiPoint.BoundingBox.North <= geoBB.South || record.MultiPoint.BoundingBox.South >= geoBB.North || record.MultiPoint.BoundingBox.West >= geoBB.East || record.MultiPoint.BoundingBox.East <= geoBB.West) { return false; } else { return true; } } else if (record.PolyLine != null) { if (record.PolyLine.BoundingBox.North <= geoBB.South || record.PolyLine.BoundingBox.South >= geoBB.North || record.PolyLine.BoundingBox.West >= geoBB.East || record.PolyLine.BoundingBox.East <= geoBB.West) { return false; } else { return true; } } else if (record.Polygon != null) { if (record.Polygon.BoundingBox.North <= geoBB.South || record.Polygon.BoundingBox.South >= geoBB.North || record.Polygon.BoundingBox.West >= geoBB.East || record.Polygon.BoundingBox.East <= geoBB.West) { return false; } else { return true; } } return false; }