623 lines
27 KiB
C#
Raw Normal View History

2025-08-13 11:14:39 +08:00
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
namespace Learun.Application.Web.Common
{
/// <summary>
/// KML实体
/// </summary>
public class Placemark
{
public string name { get; set; }
public string typeStr { get; set; }
public List<double> points { get; set; }
public object style { get; set; }
public List<Coordinates> coordinates { get; set; }
}
/// <summary>
/// 坐标
/// </summary>
public class Coordinates
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
}
public class KmlUtility
{
/// <summary>
/// 解压缩文件(压缩文件中含有子目录)
/// </summary>
/// <param name="zipfilepath">待解压缩的文件路径</param>
/// <param name="unzippath">解压缩到指定目录</param>
/// <returns>解压后的文件列表</returns>
public static List<string> UnZip(string zipfilepath, string unzippath)
{
if (!File.Exists(zipfilepath))
{
return new List<string>();
}
//解压出来的文件列表
List<string> unzipFiles = new List<string>();
//检查输出目录是否以“\\”结尾
List<string> kmlfile = new List<string>();
if (unzippath.EndsWith("\\") == false || unzippath.EndsWith(":\\") == false)
{
unzippath += "\\";
}
ZipInputStream s = new ZipInputStream(File.OpenRead(zipfilepath));
ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null)
{
if (Path.GetExtension(theEntry.Name).ToLower() == ".kml")
{
string directoryName = Path.GetDirectoryName(unzippath);
string fileName = Path.GetFileName(theEntry.Name);
//生成解压目录【用户解压到硬盘根目录时,不需要创建】
if (!string.IsNullOrEmpty(directoryName))
{
Directory.CreateDirectory(directoryName);
}
if (fileName != String.Empty)
{
//如果文件的压缩后大小为0那么说明这个文件是空的,因此不需要进行读出写入
if (theEntry.CompressedSize == 0)
continue;
//解压文件到指定的目录
directoryName = Path.GetDirectoryName(unzippath + theEntry.Name);
//建立下面的目录和子目录
Directory.CreateDirectory(directoryName);
kmlfile.Add(unzippath + theEntry.Name);
//记录导出的文件
unzipFiles.Add(unzippath + theEntry.Name);
FileStream streamWriter = File.Create(unzippath + theEntry.Name);
int size = 2048;
byte[] data = new byte[2048];
while (true)
{
size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
break;
}
}
streamWriter.Close();
}
}
}
s.Close();
GC.Collect();
return kmlfile;
}
/// <summary>
/// 获取kml对象
/// </summary>
/// <param name="kmlPath"></param>
/// <returns></returns>
public static List<Placemark> readKml(string kmlPath, bool isAPP = false)
{
List<string> list = new List<string>();
List<Placemark> retMarks = new List<Placemark>();
if (!File.Exists(kmlPath))
{
return new List<Placemark>();
}
if (Path.GetExtension(kmlPath).ToLower() == ".kmz")
{
list = UnZip(kmlPath, Path.GetDirectoryName(kmlPath));
}
else
{
list.Add(kmlPath);
}
foreach (var path in list)
{
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(path);
//申明xml命名空间管理对象
XmlNamespaceManager nsmanager = new XmlNamespaceManager(xmldoc.NameTable);
XmlElement root = xmldoc.DocumentElement;
//添加命名空间
nsmanager.AddNamespace("XX", "" + root.NamespaceURI + "");
/////规范命名空间
XmlNode t = root.GetElementsByTagName("Kml")[0];
XmlNode _document = root.GetElementsByTagName("Document")[0];
// XmlNodeList xmlmark = root.GetElementsByTagName("Placemark");
XmlNodeList xmlmark = xmldoc.SelectNodes("//XX:Placemark", nsmanager);
int tpid = 0;//踏勘点序号
foreach (XmlElement element in xmlmark)
{
Placemark mark = new Placemark();
mark.points = new List<double>();
tpid = tpid + 1;
string note = "";
var nameNode = element.GetElementsByTagName("name");
if (nameNode != null && nameNode.Count > 0)
{
string nmNode = nameNode[0].InnerText;
note = nmNode.Trim();
}
mark.name = note;
XmlElement cNode = null;
var pointNode = element.GetElementsByTagName("Point");
if (pointNode != null && pointNode.Count > 0)
{
mark.typeStr = "point";
cNode = (XmlElement)pointNode[0];
}
else
{
var lineNode = element.GetElementsByTagName("LineString");
if (lineNode != null && lineNode.Count > 0)
{
mark.typeStr = "line";
cNode = (XmlElement)lineNode[0];
}
else
{
continue;
}
}
var coordinatesNode = cNode.GetElementsByTagName("coordinates");
if (coordinatesNode != null && coordinatesNode.Count > 0)
{
string pointstr = coordinatesNode[0].InnerText;
var points = pointstr.Split(new char[] { '\n', ' ' });
var pointsCount = points.Length;
int pIndex = -1;
foreach (var item in points)
{
pIndex++;
if (pointsCount > 50)
{
if (isAPP && pIndex != 0 && pIndex != pointsCount - 1)
{
var yu = pIndex % 4;
if (yu != 0)
{
continue;
}
}
}
var pointStr = item.Trim();
if (string.IsNullOrEmpty(pointStr))
{
continue;
}
var point = pointStr.Split(',');
if (point.Length < 3)
{
continue;
}
double X = Convert.ToDouble(point[0].Trim());
double Y = Convert.ToDouble(point[1].Trim());
mark.points.Add(X);
mark.points.Add(Y);
}
}
//线必须大于两个点
if (mark.points.Count < 4 && (mark.points.Count % 2) != 0 && mark.typeStr == "line")
{
continue;
}
if (mark.points.Count > 0)
{
retMarks.Add(mark);
}
}
}
return retMarks;
}
/// <summary>
/// 获取kml对象
/// </summary>
/// <param name="kmlPath"></param>
/// <returns></returns>
public static List<Placemark> readzKml(string kmlPath, bool isAPP = false)
{
List<string> list = new List<string>();
List<Placemark> retMarks = new List<Placemark>();
if (!File.Exists(kmlPath))
{
return new List<Placemark>();
}
if (Path.GetExtension(kmlPath).ToLower() == ".kmz")
{
list = UnZip(kmlPath, Path.GetDirectoryName(kmlPath));
}
else
{
list.Add(kmlPath);
}
foreach (var path in list)
{
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(path);
//申明xml命名空间管理对象
XmlNamespaceManager nsmanager = new XmlNamespaceManager(xmldoc.NameTable);
XmlElement root = xmldoc.DocumentElement;
//添加命名空间
nsmanager.AddNamespace("XX", "" + root.NamespaceURI + "");
/////规范命名空间
XmlNode t = root.GetElementsByTagName("Kml")[0];
XmlNode _document = root.GetElementsByTagName("Document")[0];
// XmlNodeList xmlmark = root.GetElementsByTagName("Placemark");
XmlNodeList xmlmark = xmldoc.SelectNodes("//XX:Placemark", nsmanager);
int tpid = 0;//踏勘点序号
foreach (XmlElement element in xmlmark)
{
Placemark mark = new Placemark();
mark.points = new List<double>();
tpid = tpid + 1;
string note = "";
var nameNode = element.GetElementsByTagName("name");
if (nameNode != null && nameNode.Count > 0)
{
string nmNode = nameNode[0].InnerText;
note = nmNode.Trim();
}
mark.name = note;
XmlElement cNode = null;
var pointNode = element.GetElementsByTagName("Point");
var lineString = element.GetElementsByTagName("LineString");
var linearRing = element.GetElementsByTagName("LinearRing");
if (pointNode != null && pointNode.Count > 0)
{
mark.typeStr = "point";
cNode = (XmlElement)pointNode[0];
}
else if (lineString != null && lineString.Count > 0)
{
mark.typeStr = "line";
cNode = (XmlElement)lineString[0];
}
else if (linearRing != null && linearRing.Count > 0)
{
mark.typeStr = "ring";
cNode = (XmlElement)linearRing[0];
}
else
{
continue;
}
var coordinatesNode = cNode.GetElementsByTagName("coordinates");
if (coordinatesNode != null && coordinatesNode.Count > 0)
{
string pointstr = coordinatesNode[0].InnerText;
var points = pointstr.Split(new char[] { '\n', ' ' });
var pointsCount = points.Length;
int pIndex = -1;
foreach (var item in points)
{
pIndex++;
var pointStr = item.Trim();
if (string.IsNullOrEmpty(pointStr))
{
continue;
}
var point = pointStr.Split(',');
if (point.Length < 3)
{
continue;
}
double X = Convert.ToDouble(point[0].Trim());
double Y = Convert.ToDouble(point[1].Trim());
double Z = Convert.ToDouble(point[2].Trim());
if (mark.typeStr == "line")
{
Z += 100;
}
mark.points.Add(X);
mark.points.Add(Y);
mark.points.Add(Z);
}
}
//线必须大于两个点
if (mark.points.Count < 6 && (mark.points.Count % 3) != 0 && mark.typeStr == "line")
{
continue;
}
if (mark.points.Count > 0)
{
retMarks.Add(mark);
}
}
}
return retMarks;
}
/// <summary>
/// 获取kml对象
/// </summary>
/// <param name="kmlPath"></param>
/// <returns></returns>
public static List<Placemark> readzKml(string kmlPath)
{
List<string> list = new List<string>();
List<Placemark> retMarks = new List<Placemark>();
if (!File.Exists(kmlPath))
{
return new List<Placemark>();
}
if (Path.GetExtension(kmlPath).ToLower() == ".kmz")
{
list = UnZip(kmlPath, Path.GetDirectoryName(kmlPath));
}
else
{
list.Add(kmlPath);
}
foreach (var path in list)
{
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(path);
//申明xml命名空间管理对象
XmlNamespaceManager nsmanager = new XmlNamespaceManager(xmldoc.NameTable);
XmlElement root = xmldoc.DocumentElement;
//添加命名空间
nsmanager.AddNamespace("XX", "" + root.NamespaceURI + "");
/////规范命名空间
XmlNode t = root.GetElementsByTagName("Kml")[0];
XmlNode _document = root.GetElementsByTagName("Document")[0];
XmlNodeList xmlmark = xmldoc.SelectNodes("//XX:Placemark", nsmanager);
foreach (XmlElement element in xmlmark)
{
Placemark mark = new Placemark();
mark.coordinates = new List<Coordinates>();
string note = "";
var nameNode = element.GetElementsByTagName("name");
if (nameNode != null && nameNode.Count > 0)
{
string nmNode = nameNode[0].InnerText;
note = nmNode.Trim();
}
mark.name = note;
string IconStyleColor = "";
string LabelStyleColor = "";
string LineStyleColor = "";
string LineStyleWidth = "";
var styleNode = element.GetElementsByTagName("Style");
if (styleNode != null && styleNode.Count > 0)
{
XmlElement tempStyleNode = (XmlElement)styleNode[0];
//图标样式
var iconStyle = tempStyleNode.GetElementsByTagName("IconStyle");
if (iconStyle != null && iconStyle.Count > 0)
{
XmlElement iconStyleNode = (XmlElement)iconStyle[0];
var color = iconStyleNode.GetElementsByTagName("color");
IconStyleColor = color[0].InnerText.Trim();
}
//标签样式
var labelStyle = tempStyleNode.GetElementsByTagName("LabelStyle");
if (iconStyle != null && iconStyle.Count > 0)
{
XmlElement labelStyleNode = (XmlElement)labelStyle[0];
var color = labelStyleNode.GetElementsByTagName("color");
LabelStyleColor = color[0].InnerText.Trim();
}
//线样式
var lineStyle = tempStyleNode.GetElementsByTagName("LineStyle");
if (lineStyle != null && lineStyle.Count > 0)
{
XmlElement lineStyleNode = (XmlElement)lineStyle[0];
var lineStyleColor = lineStyleNode.GetElementsByTagName("color");
LineStyleColor = lineStyleColor[0].InnerText.Trim();
var width = lineStyleNode.GetElementsByTagName("width");
LineStyleWidth = width[0].InnerText.Trim();
}
}
XmlElement cNode = null;
var pointNode = element.GetElementsByTagName("Point");
var lineString = element.GetElementsByTagName("LineString");
var linearRing = element.GetElementsByTagName("LinearRing");
if (pointNode != null && pointNode.Count > 0)
{
mark.typeStr = "point";
foreach (var p in pointNode)
{
cNode = (XmlElement)p;
//点的样式
mark.style = new { IconStyleColor, LabelStyleColor };
var coordinatesNode = cNode.GetElementsByTagName("coordinates");
if (coordinatesNode != null && coordinatesNode.Count > 0)
{
string pointstr = coordinatesNode[0].InnerText;
var points = pointstr.Split(new char[] { '\n', ' ' });
var pointsCount = points.Length;
foreach (var item in points)
{
var coordinates = new Coordinates();
var pointStr = item.Trim();
if (string.IsNullOrEmpty(pointStr))
{
continue;
}
var point = pointStr.Split(',');
double X = Convert.ToDouble(point[0].Trim());
double Y = Convert.ToDouble(point[1].Trim());
coordinates.X = X;
coordinates.Y = Y;
coordinates.Z = 0;
mark.coordinates.Add(coordinates);
}
}
}
}
if (lineString != null && lineString.Count > 0)
{
mark.typeStr = "line";
foreach (var p in lineString)
{
cNode = (XmlElement)p;
//线的样式
mark.style = new { LineStyleColor, LineStyleWidth };
var coordinatesNode = cNode.GetElementsByTagName("coordinates");
if (coordinatesNode != null && coordinatesNode.Count > 0)
{
string pointstr = coordinatesNode[0].InnerText;
var points = pointstr.Split(new char[] { '\n', ' ' });
var pointsCount = points.Length;
foreach (var item in points)
{
var coordinates = new Coordinates();
var pointStr = item.Trim();
if (string.IsNullOrEmpty(pointStr))
{
continue;
}
var point = pointStr.Split(',');
double X = Convert.ToDouble(point[0].Trim());
double Y = Convert.ToDouble(point[1].Trim());
coordinates.X = X;
coordinates.Y = Y;
coordinates.Z = 0;
mark.coordinates.Add(coordinates);
}
}
}
}
if (linearRing != null && linearRing.Count > 0)
{
mark.typeStr = "ring";
foreach (var p in linearRing)
{
cNode = (XmlElement)p;
var coordinatesNode = cNode.GetElementsByTagName("coordinates");
if (coordinatesNode != null && coordinatesNode.Count > 0)
{
string pointstr = coordinatesNode[0].InnerText;
var points = pointstr.Split(new char[] { '\n', ' ' });
var pointsCount = points.Length;
foreach (var item in points)
{
var coordinates = new Coordinates();
var pointStr = item.Trim();
if (string.IsNullOrEmpty(pointStr))
{
continue;
}
var point = pointStr.Split(',');
double X = Convert.ToDouble(point[0].Trim());
double Y = Convert.ToDouble(point[1].Trim());
coordinates.X = X;
coordinates.Y = Y;
coordinates.Z = 0;
mark.coordinates.Add(coordinates);
}
}
}
}
retMarks.Add(mark);
}
}
return retMarks;
}
/// <summary>
/// 获取KML桩号坐标集合
/// </summary>
/// <param name="filePath">路径</param>
/// <returns></returns>
public static List<Placemark> GetStakeCoordinate(string filePath)
{
List<string> list = new List<string>();
List<Placemark> retMarks = new List<Placemark>();
if (!File.Exists(filePath))
{
return new List<Placemark>();
}
if (Path.GetExtension(filePath).ToLower() == ".kmz")
{
list = UnZip(filePath, Path.GetDirectoryName(filePath));
}
else
{
list.Add(filePath);
}
foreach (var path in list)
{
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(path);
//申明xml命名空间管理对象
XmlNamespaceManager nsmanager = new XmlNamespaceManager(xmldoc.NameTable);
XmlElement root = xmldoc.DocumentElement;
//添加命名空间
nsmanager.AddNamespace("XX", "" + root.NamespaceURI + "");
/////规范命名空间
XmlNode t = root.GetElementsByTagName("Kml")[0];
XmlNode _document = root.GetElementsByTagName("Document")[0];
XmlNodeList xmlmark = xmldoc.SelectNodes("//XX:Placemark", nsmanager);
//var isselect = false;
foreach (XmlElement element in xmlmark)
{
Placemark mark = new Placemark();
mark.points = new List<double>();
string note = string.Empty;
var nameNode = element.GetElementsByTagName("name");
if (nameNode != null && nameNode.Count > 0)
{
//string nmNode = nameNode[0].InnerText.Trim();
//note = Regex.Replace(nmNode, "[ \\[ \\] \\^ \\-_*×――(^)|'$%~!@#$…&%¥—+=<>《》!??::•`·、。,;,.;\"‘’“”-]", "").ToUpper();
note = nameNode[0].InnerText.Trim();
}
mark.name = note;
// if (name.Contains(mark.name) || isselect)
//{
//if (!isselect)
//{
// mark.name = name;
//}
XmlElement cNode = null;
var pointNode = element.GetElementsByTagName("Point");
if (pointNode != null && pointNode.Count > 0)
{
mark.typeStr = "point";
cNode = (XmlElement)pointNode[0];
}
if (cNode != null)
{
var coordinatesNode = cNode.GetElementsByTagName("coordinates");
if (coordinatesNode != null && coordinatesNode.Count > 0)
{
string pointstr = coordinatesNode[0].InnerText.Trim();
var points = pointstr.Split(',');
double X = Convert.ToDouble(points[0].Trim());
double Y = Convert.ToDouble(points[1].Trim());
mark.points.Add(X);
mark.points.Add(Y);
mark.points.Add(0);
retMarks.Add(mark);
}
}
}
}
return retMarks;
}
}
}