325 lines
12 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
namespace IronIntel.Contractor.Shape
{
public static class ShapeFileParser
{
private static void ParsePoints(BinaryReader binaryReader, MapPoints points)
{
while (binaryReader.PeekChar() != -1)
{
binaryReader.ReadUInt32();
binaryReader.ReadInt32();
int shapeType = binaryReader.ReadInt32();
MapPoint p = new MapPoint();
p.Longitude = binaryReader.ReadDouble();
p.Latitude = binaryReader.ReadDouble();
points.Points.Add(p);
if (shapeType == 11)//PointZ
{
binaryReader.ReadDouble();//Z
binaryReader.ReadDouble();//M
}
else if (shapeType == 21)//PointM
{
binaryReader.ReadDouble();//M
}
}
}
private static void ParsePolylines(BinaryReader binaryReader, List<Polyline> polylines)
{
while (binaryReader.PeekChar() != -1)
{
Polyline polyling = new Polyline();
polylines.Add(polyling);
binaryReader.ReadUInt32();
binaryReader.ReadInt32();
int shapeType = binaryReader.ReadInt32();
polyling.TopLeft = new MapPoint();
polyling.BottomRight = new MapPoint();
polyling.TopLeft.Longitude = binaryReader.ReadDouble();
polyling.TopLeft.Latitude = binaryReader.ReadDouble();
polyling.BottomRight.Longitude = binaryReader.ReadDouble();
polyling.BottomRight.Latitude = binaryReader.ReadDouble();
List<int> parts = new List<int>();//记录每条线的起始点索引
int partCount = binaryReader.ReadInt32();
int pointCount = binaryReader.ReadInt32();
for (int i = 0; i < partCount; i++)
{
int part = new int();
part = binaryReader.ReadInt32();
parts.Add(part);
}
MapPoints ring = null;
int partIndex = 0;
for (int j = 0; j < pointCount; j++)
{
if (partIndex < parts.Count && parts[partIndex] == j)
{
ring = new MapPoints();
polyling.Parts.Add(ring);
}
MapPoint mp = new MapPoint();
mp.Longitude = binaryReader.ReadDouble();
mp.Latitude = binaryReader.ReadDouble();
ring.Points.Add(mp);
}
if (shapeType == 13)//PolylineZ
{
binaryReader.ReadDouble();//Zmin
binaryReader.ReadDouble();//Zmax
for (int j = 0; j < pointCount; j++)
{
binaryReader.ReadDouble();//Zarray
}
binaryReader.ReadDouble();//Mmin
binaryReader.ReadDouble();//Mmax
for (int j = 0; j < pointCount; j++)
{
binaryReader.ReadDouble();//Marray
}
}
else if (shapeType == 23)//PolylineM
{
binaryReader.ReadDouble();//Mmin
binaryReader.ReadDouble();//Mmax
for (int j = 0; j < pointCount; j++)
{
binaryReader.ReadDouble();//Marray
}
}
}
}
private static void ParsePolygons(BinaryReader binaryReader, List<Polygon> ls)
{
while (binaryReader.PeekChar() != -1)
{
binaryReader.ReadUInt32();
binaryReader.ReadInt32();
int shapeType = binaryReader.ReadInt32();
Polygon p = new Polygon();
p.TopLeft = new MapPoint();
p.BottomRight = new MapPoint();
p.TopLeft.Longitude = binaryReader.ReadDouble();
p.TopLeft.Latitude = binaryReader.ReadDouble();
p.BottomRight.Longitude = binaryReader.ReadDouble();
p.BottomRight.Latitude = binaryReader.ReadDouble();
List<int> parts = new List<int>();//记录每个区域的起始点索引
int partCount = binaryReader.ReadInt32();
int pointCount = binaryReader.ReadInt32();
for (int j = 0; j < partCount; j++)
{
int part = binaryReader.ReadInt32();
parts.Add(part);
}
MapPoints ring = null;
int partIndex = 0;
for (int j = 0; j < pointCount; j++)
{
if (partIndex < parts.Count && parts[partIndex] == j)
{
ring = new MapPoints();
p.Rings.Add(ring);
partIndex++;
}
MapPoint mp = new MapPoint();
mp.Longitude = binaryReader.ReadDouble();
mp.Latitude = binaryReader.ReadDouble();
ring.Points.Add(mp);
}
ls.Add(p);
if (shapeType == 15)//PolygonZ
{
binaryReader.ReadDouble();//Zmin
binaryReader.ReadDouble();//Zmax
for (int j = 0; j < pointCount; j++)
{
binaryReader.ReadDouble();//Zarray
}
binaryReader.ReadDouble();//Mmin
binaryReader.ReadDouble();//Mmax
for (int j = 0; j < pointCount; j++)
{
binaryReader.ReadDouble();//Marray
}
}
else if (shapeType == 25)//PolygonM
{
binaryReader.ReadDouble();//Mmin
binaryReader.ReadDouble();//Mmax
for (int j = 0; j < pointCount; j++)
{
binaryReader.ReadDouble();//Marray
}
}
}
}
/// <summary>
/// 解析.shp文件
/// </summary>
/// <param name="fileName"></param>
public static void ParseFromShapeFile(string fileName, Shape shape)
{
using (FileStream fileStream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
ParseFromShapeFile(fileStream, shape);
}
}
/// <summary>
/// 解析.shp文件
/// </summary>
/// <param name="buffer">.shp文件数据</param>
/// <param name="shape"></param>
public static void ParseFromShapeFile(byte[] buffer, Shape shape)
{
using (MemoryStream ms = new MemoryStream(buffer, false))
{
ParseFromShapeFile(ms, shape);
}
}
/// <summary>
/// 解析.shp文件
/// </summary>
/// <param name="fs">装载.shp文件数据的流</param>
public static void ParseFromShapeFile(Stream fs, Shape shape)
{
fs.Seek(0, SeekOrigin.Begin);
using (BinaryReader binaryReader = new BinaryReader(fs))
{
binaryReader.ReadBytes(24);
int FileLength = binaryReader.ReadInt32();//<0代表数据长度未知
int FileBanben = binaryReader.ReadInt32();
int ShapeType = binaryReader.ReadInt32();
double xmin = binaryReader.ReadDouble();
double ymax = -1 * binaryReader.ReadDouble();
double xmax = binaryReader.ReadDouble();
double ymin = -1 * binaryReader.ReadDouble();
double width = xmax - xmin;
double height = ymax - ymin;
binaryReader.ReadBytes(32);
switch (ShapeType)
{
case 1://Point
case 11://PointZ
case 21://PointM
MapPoints points = new MapPoints();
shape.Points.Add(points);
ParsePoints(binaryReader, points);
break;
case 3://PolyLine
case 13://PolyLineZ
case 23://PolyLineM
ParsePolylines(binaryReader, shape.Polylines);
break;
case 5://Polygon
case 15://PolygonZ
case 25://PolygonM
ParsePolygons(binaryReader, shape.Polygons);
break;
}
}
}
/// <summary>
/// 从zip文件当中解析.shp
/// </summary>
/// <param name="stream">装载.zip文件内容的流</param>
/// <param name="shape"></param>
public static void ParseFromZipFile(Stream stream, Shape shape)
{
const string EXT = ".shp";
//using (ZipInputStream s = new ZipInputStream(stream))
//{
// ZipEntry zipentry = s.GetNextEntry();
// while (zipentry != null)
// {
// if (zipentry.IsDirectory)
// {
// zipentry = s.GetNextEntry();
// continue;
// }
// string ext = Path.GetExtension(zipentry.FileName);
// if (string.Compare(ext, EXT, true) == 0)
// {
// Stream shpStream = new MemoryStream();
// int size = 0;
// byte[] data = new byte[2048];
// while (true)
// {
// size = s.Read(data, 0, data.Length);
// if (size > 0)
// {
// shpStream.Write(data, 0, size);
// }
// else
// {
// break;
// }
// }
// ParseFromShapeFile(shpStream, shape);
// }
// zipentry = s.GetNextEntry();
// }//while
//}
}
/// <summary>
/// 从.zip文件当中解析.shp
/// </summary>
/// <param name="buffer">.zip文件数据</param>
/// <param name="shape"></param>
public static void ParseFromZipFile(byte[] buffer, Shape shape)
{
using (MemoryStream ms = new MemoryStream(buffer, false))
{
ParseFromZipFile(ms, shape);
}
}
/// <summary>
/// 从.zip文件当中解析.shp
/// </summary>
/// <param name="filename"></param>
/// <param name="shape"></param>
public static void ParseFromZipFile(string filename, Shape shape)
{
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
ParseFromZipFile(fs, shape);
}
}
}
}