public static ShapeInfo GetShapeInfoEx(string p_SourceDir, string p_FileName) { ShapeInfo RetVal = null; FileStream _SHXStream; BinaryReader _SHXBinaryReader; FileHeader _SHXFileHeader = new FileHeader(); RetVal = new ShapeInfo(); try { _SHXStream = File.OpenRead(p_SourceDir + "\\" + p_FileName + ".shx"); _SHXBinaryReader = new BinaryReader(_SHXStream); _SHXFileHeader = ReadHeaderInfo(ref _SHXBinaryReader); { RetVal.ID = p_FileName; RetVal.Extent = new RectangleF((float)_SHXFileHeader.BoundingBoxXMin, (float)_SHXFileHeader.BoundingBoxYMin, (float)Math.Abs(_SHXFileHeader.BoundingBoxXMax - _SHXFileHeader.BoundingBoxXMin), (float)Math.Abs(_SHXFileHeader.BoundingBoxYMax - _SHXFileHeader.BoundingBoxYMin)); RetVal.RecordCount = (int)(_SHXFileHeader.FileLength - 50) / 4; RetVal.ShapeType = (DevInfo.Lib.DI_LibBAL.UI.Presentations.Map.ShapeType)_SHXFileHeader.ShapeType; } } finally { // _SHXStream.Close(); _SHXStream = null; // _SHXBinaryReader.Close(); _SHXBinaryReader = null; //_SHXFileHeader = null; } return RetVal; }
public static ShapeInfo GetShapeInfo(string p_SourceDir, string p_FileName) { ShapeInfo RetVal = null; //-- Check for shape file set existence if (File.Exists(p_SourceDir + "\\" + p_FileName + ".shp") && File.Exists(p_SourceDir + "\\" + p_FileName + ".shx") && File.Exists(p_SourceDir + "\\" + p_FileName + ".dbf")) { FileHeader SHPFileHeader = new FileHeader(); SHPRecordHeader SHPRecordHeader = new SHPRecordHeader(); FileStream objSHPStream = null; BinaryReader objSHPBinaryReader = null; FileHeader SHXFileHeader = new FileHeader(); SHXRecordHeader SHXRecordHeader = new SHXRecordHeader(); FileStream objSHXStream = null; BinaryReader objSHXBinaryReader = null; FileStream dbfStream = null; BinaryReader dbfReader = null; System.Text.Encoding FileEncoding; // To hold encoding type on the basis of code Page value defined in .dbf header. int i; int j; int k; try { objSHPStream = File.OpenRead(p_SourceDir + "\\" + p_FileName + ".shp"); objSHPBinaryReader = new BinaryReader(objSHPStream); objSHXStream = File.OpenRead(p_SourceDir + "\\" + p_FileName + ".shx"); objSHXBinaryReader = new BinaryReader(objSHXStream); //-- get Encoding used to create dbf file. This PageCode information is in 29th position of dbfReader. FileEncoding = ShapeFileReader.GetEncodingInDBF(p_SourceDir + "\\" + p_FileName + ".dbf"); dbfStream = File.OpenRead(p_SourceDir + "\\" + p_FileName + ".dbf"); //dbfReader = new BinaryReader(dbfStream, System.Text.Encoding.GetEncoding(65001)); // 65001 is the code page for Unicode UTF-8 encoding taken as default' dbfReader = new BinaryReader(dbfStream, FileEncoding); SHPFileHeader = ReadHeaderInfo(ref objSHPBinaryReader); SHXFileHeader = ReadHeaderInfo(ref objSHXBinaryReader); ShapeInfo _ShapeInfo = new ShapeInfo(); _ShapeInfo.ID = p_FileName; _ShapeInfo.Extent = new RectangleF((float)SHPFileHeader.BoundingBoxXMin, (float)SHPFileHeader.BoundingBoxYMin, (float)Math.Abs(SHPFileHeader.BoundingBoxXMax - SHPFileHeader.BoundingBoxXMin), (float)Math.Abs(SHPFileHeader.BoundingBoxYMax - SHPFileHeader.BoundingBoxYMin)); _ShapeInfo.RecordCount = (int)(SHXFileHeader.FileLength - 50) / 4; _ShapeInfo.ShapeType = (DevInfo.Lib.DI_LibBAL.UI.Presentations.Map.ShapeType)SHPFileHeader.ShapeType; if ((int)(_ShapeInfo.ShapeType) == (int)(ShapeFileReader.ShapeType.PointZ)) { _ShapeInfo.ShapeType = DevInfo.Lib.DI_LibBAL.UI.Presentations.Map.ShapeType.Point; } //*** Read dbf header and set Id and Label Field string sFieldId = ""; string sFieldLabel = ""; byte dbfVersion = dbfReader.ReadByte(); //3 byte updateYear = dbfReader.ReadByte(); byte updateMonth = dbfReader.ReadByte(); byte updateDay = dbfReader.ReadByte(); Int32 numberRecords = dbfReader.ReadInt32(); // short headerLength = dbfReader.ReadInt16(); // short recordLength = dbfReader.ReadInt16(); //**** In Reserved Bytes, there is a byte (flag) at 29th postion of stream which represent code page information, that can be used to get Encoding type. dbfStream.Seek(29, SeekOrigin.Begin); // Seek to 29th postion to fetch code page . FileEncoding = GetDbaseEncodingType(dbfReader.ReadByte()); // Reads code page and gets the corresponding encoding type. dbfStream.Seek(32, SeekOrigin.Begin); // Move to past the reserved bytes. // byte[] reserved = dbfReader.ReadBytes(20); Int32 numberFields = (int)(headerLength - 33) / 32; DBF_Field_Header[] fieldHeaders = new DBF_Field_Header[numberFields]; string FieldName; for (i = 0; i <= numberFields - 1; i++) { //byte[] testBytes = FileEncoding.GetBytes(dbfReader.ReadChars(10)); ////dbfReader.BaseStream.Position -= 10; //testBytes = System.Text.Encoding.Convert(System.Text.Encoding.UTF8, FileEncoding, testBytes); try { char[] fieldNameChars = dbfReader.ReadChars(10); char fieldNameTerminator = dbfReader.ReadChar(); FieldName = new string(fieldNameChars).ToUpper(); fieldHeaders[i].FieldName = FieldName; fieldHeaders[i].FieldType = dbfReader.ReadChar(); if (FieldName.Length >= 3 && fieldHeaders[i].FieldName.Replace("\0","").Trim() == ID_FIELD_NAME) { if (FieldName[0] == 'I' & FieldName[1] == 'D' & FieldName[2] == '_') sFieldId = fieldHeaders[i].FieldName; } if (FieldName.Length >= 6 && fieldHeaders[i].FieldName.Replace("\0", "").Trim() == NAME1_FIELD_NAME) { if (FieldName[0] == 'N' & FieldName[1] == 'A' & FieldName[2] == 'M' & FieldName[3] == 'E' & FieldName[4] == '1' & FieldName[5] == '_') sFieldLabel = fieldHeaders[i].FieldName; } byte[] reserved1 = dbfReader.ReadBytes(4); fieldHeaders[i].FieldLength = dbfReader.ReadByte(); byte[] reserved2 = dbfReader.ReadBytes(15); } catch (Exception ex) { Console.Write(ex.Message); } } byte headerTerminator = dbfReader.ReadByte(); //13 if (sFieldId == "") sFieldId = fieldHeaders[0].FieldName; if (sFieldLabel == "") { if (fieldHeaders.Length > 1) { sFieldLabel = fieldHeaders[1].FieldName; } else { sFieldLabel = fieldHeaders[0].FieldName; } } int numParts; int numPoints; int[] theParts; PointF[] Pt; float Ydiff = 0; //*** Add Ydiff to make all Y coordinates positve for area calculation. if extent of polygon goes below equator //*** Special Handling for centroids of areas lying in 3rd quadrent //*** http://astronomy.swin.edu.au/~pbourke/geometry/polyarea/ //*** http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u33.html //*** X = S ((y(i) - y(i+1)) (x(i)2 + x(i)x(i+1) + x(i+1)2)/6A) Y = S ((x(i+1) - x(i)) (y(i)2 + y(i)y(i+1) + y(i+1)2)/6A) where A is the area of the polygon //*** note: as with the area algorithm, the polygon must be coded clockwise and all y coordinates must be non- negative for (i = 0; i <= _ShapeInfo.RecordCount - 1; i++) { SHXRecordHeader.Offset = BigToLittleEndian(objSHXBinaryReader.ReadInt32()); SHXRecordHeader.ContentLength = BigToLittleEndian(objSHXBinaryReader.ReadInt32()); objSHPStream.Seek(SHXRecordHeader.Offset * 2, SeekOrigin.Begin); SHPRecordHeader.RecordNumber = BigToLittleEndian(objSHPBinaryReader.ReadInt32()); SHPRecordHeader.ContentLength = BigToLittleEndian(objSHPBinaryReader.ReadInt32()); objSHPBinaryReader.ReadInt32(); //ShapeType byte isValid = dbfReader.ReadByte(); //32 Shape _Shape = new Shape(); RectangleF _Extent = new RectangleF(); { for (j = 0; j <= fieldHeaders.Length - 1; j++) { char[] fieldDataChars; if (fieldHeaders[j].FieldName == sFieldId) { //Fetch AreaID from .dbf file using default encoding which is set to UTF-8. fieldDataChars = dbfReader.ReadChars(fieldHeaders[j].FieldLength); _Shape.AreaId = new string(fieldDataChars).Trim(); } else if (fieldHeaders[j].FieldName == sFieldLabel) { //Fetch the value from "NAME1_" column in its original encoded characters using extracted encoding type. fieldDataChars = FileEncoding.GetString(dbfReader.ReadBytes(fieldHeaders[j].FieldLength)).Replace("\0", "").Trim().ToCharArray(); _Shape.AreaName = new string(fieldDataChars).Trim(); } else { fieldDataChars = dbfReader.ReadChars(fieldHeaders[j].FieldLength); } //string fieldData = new string(fieldDataChars).Trim(); // unused statement } switch (SHPFileHeader.ShapeType) { case (int)ShapeType.Point: case (int)(ShapeFileReader.ShapeType.PointZ): PointF _Pt = new PointF(); _Pt.X = (float)objSHPBinaryReader.ReadDouble(); _Pt.Y = (float)objSHPBinaryReader.ReadDouble(); _Shape.Parts.Add(_Pt); break; case (int)ShapeType.PolyLine: _Extent.X = (float)objSHPBinaryReader.ReadDouble(); //Byte 04 Minx _Extent.Y = (float)objSHPBinaryReader.ReadDouble(); //Byte 12 MinY _Extent.Width = (float)Math.Abs(_Extent.X - objSHPBinaryReader.ReadDouble()); //Byte 20 MaxX _Extent.Height = (float)Math.Abs(_Extent.Y - objSHPBinaryReader.ReadDouble()); //Byte 28 MaxY _Shape.Extent = _Extent; numParts = objSHPBinaryReader.ReadInt32(); //Byte 36 Num Parts numPoints = objSHPBinaryReader.ReadInt32(); //Byte 40 Num Points theParts = new int[numParts]; for (j = 0; j <= numParts - 1; j++) { theParts[j] = objSHPBinaryReader.ReadInt32(); } for (j = 0; j <= numParts - 1; j++) { if ((j != numParts - 1)) { Pt = new PointF[theParts[j + 1] - theParts[j]]; for (k = theParts[j]; k <= theParts[j + 1] - 1; k++) { Pt[k - theParts[j]].X = (float)objSHPBinaryReader.ReadDouble(); Pt[k - theParts[j]].Y = (float)objSHPBinaryReader.ReadDouble(); } } else { Pt = new PointF[numPoints - theParts[j]]; for (k = theParts[j]; k <= numPoints - 1; k++) { Pt[k - theParts[j]].X = (float)objSHPBinaryReader.ReadDouble(); Pt[k - theParts[j]].Y = (float)objSHPBinaryReader.ReadDouble(); } } _Shape.Parts.Add(Pt); } break; case (int)ShapeType.Polygon: //*** Bugfix 27 Sep 2006 Centroid calulation for very small polygon 'Mayanmar problem double second_factor; //*** For centroid calculation double[] polygon_area; //*** SignedPolygonArea double[] Cx; double[] Cy; _Extent.X = (float)objSHPBinaryReader.ReadDouble(); //Byte 04 Minx _Extent.Y = (float)objSHPBinaryReader.ReadDouble(); //Byte 12 MinY _Extent.Width = (float)Math.Abs(_Extent.X - objSHPBinaryReader.ReadDouble()); //Byte 20 MaxX _Extent.Height = (float)Math.Abs(_Extent.Y - objSHPBinaryReader.ReadDouble()); //Byte 28 MaxY _Shape.Extent = _Extent; if (_Extent.Y < 0) Ydiff = -(_Extent.Y); numParts = objSHPBinaryReader.ReadInt32(); //Byte 36 Num Parts numPoints = objSHPBinaryReader.ReadInt32(); //Byte 40 Num Points theParts = new int[numParts]; for (j = 0; j <= numParts - 1; j++) { theParts[j] = objSHPBinaryReader.ReadInt32(); } Cx = new double[numParts]; Cy = new double[numParts]; polygon_area = new double[numParts]; for (j = 0; j <= numParts - 1; j++) { if ((j != numParts - 1)) { Pt = new PointF[theParts[j + 1] - theParts[j]]; for (k = theParts[j]; k <= theParts[j + 1] - 1; k++) { Pt[k - theParts[j]].X = (float)objSHPBinaryReader.ReadDouble(); Pt[k - theParts[j]].Y = (float)objSHPBinaryReader.ReadDouble(); if (k > theParts[j]) { polygon_area[j] = polygon_area[j] + (Pt[k - theParts[j]].X - Pt[k - theParts[j] - 1].X) * ((Pt[k - theParts[j]].Y + Ydiff) + (Pt[k - theParts[j] - 1].Y + Ydiff)) / 2; second_factor = Pt[k - theParts[j] - 1].X * (Pt[k - theParts[j]].Y + Ydiff) - Pt[k - theParts[j]].X * (Pt[k - theParts[j] - 1].Y + Ydiff); Cx[j] = Cx[j] + (Pt[k - theParts[j] - 1].X + Pt[k - theParts[j]].X) * second_factor; Cy[j] = Cy[j] + ((Pt[k - theParts[j] - 1].Y + Ydiff) + (Pt[k - theParts[j]].Y + Ydiff)) * second_factor; } } } else { Pt = new PointF[numPoints - theParts[j]]; for (k = theParts[j]; k <= numPoints - 1; k++) { Pt[k - theParts[j]].X = (float)objSHPBinaryReader.ReadDouble(); Pt[k - theParts[j]].Y = (float)objSHPBinaryReader.ReadDouble(); if (k > theParts[j]) { polygon_area[j] = polygon_area[j] + (Pt[k - theParts[j]].X - Pt[k - theParts[j] - 1].X) * ((Pt[k - theParts[j]].Y + Ydiff) + (Pt[k - theParts[j] - 1].Y + Ydiff)) / 2; second_factor = Pt[k - theParts[j] - 1].X * (Pt[k - theParts[j]].Y + Ydiff) - Pt[k - theParts[j]].X * (Pt[k - theParts[j] - 1].Y + Ydiff); Cx[j] = Cx[j] + (Pt[k - theParts[j] - 1].X + Pt[k - theParts[j]].X) * second_factor; Cy[j] = Cy[j] + ((Pt[k - theParts[j] - 1].Y + Ydiff) + (Pt[k - theParts[j]].Y + Ydiff)) * second_factor; } } } _Shape.Parts.Add(Pt); if (polygon_area[j] == 0) { Cx[j] = 0; //*** Indonesia problem Cy[j] = 0; } else { Cx[j] = Cx[j] / 6 / polygon_area[j]; // Divide by 6 times the polygon's area. Cy[j] = Cy[j] / 6 / polygon_area[j]; } } double SumCx = 0; double SumCy = 0; double SumA = 0; for (j = 0; j <= numParts - 1; j++) { SumCx = SumCx + Cx[j] * polygon_area[j]; SumCy = SumCy + Cy[j] * polygon_area[j]; SumA = SumA + polygon_area[j]; } SumCx = SumCx / SumA; SumCy = SumCy / SumA; if (SumCx < 0 | SumCy < 0) { //*** If the values are negative, the polygon is oriented counterclockwise. Reverse the signs. SumCx = -SumCx; SumCy = -SumCy; } _Shape.Centroid = new PointF((float)SumCx, (float)SumCy - Ydiff); break; } _ShapeInfo.Records.Add(_Shape.AreaId, _Shape); _Shape = null; } } RetVal = _ShapeInfo; } catch (Exception ex) { Console.Write(ex.Message); } finally { //-- Deallocate the memory used for garbage collector to remove the memory utilized objSHPStream.Close(); objSHPStream = null; objSHXStream.Close(); objSHXStream = null; dbfStream.Close(); dbfStream = null; objSHPBinaryReader.Close(); objSHPBinaryReader = null; objSHXBinaryReader.Close(); objSHXBinaryReader = null; dbfReader.Close(); dbfReader = null; // SHPFileHeader = null; // SHXFileHeader = null; // SHXRecordHeader = null; // SHPRecordHeader = null; } } return RetVal; }