325 lines
12 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|