Files
2026-02-21 16:45:37 +08:00

238 lines
4.9 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using UnityEngine;
public class MegaKML
{
private enum kmlGeometryType
{
POINT = 0,
LINESTRING = 1
}
private enum kmlTagType
{
POINT = 0,
LINESTRING = 1,
COORDINATES = 2
}
private List<Hashtable> PointsCollection = new List<Hashtable>();
private List<Hashtable> LinesCollection = new List<Hashtable>();
private Hashtable Point;
private Hashtable Line;
private Hashtable Coordinates;
private Hashtable KMLCollection = new Hashtable();
private kmlGeometryType? currentGeometry;
private kmlTagType? currentKmlTag;
private string lastError;
private List<Vector3> points = new List<Vector3>();
public string LastError
{
get
{
return lastError;
}
set
{
lastError = value;
throw new Exception(lastError);
}
}
public Hashtable KMLDecode(string fileName)
{
points.Clear();
readKML(fileName);
if (PointsCollection != null)
{
KMLCollection.Add("POINTS", PointsCollection);
}
if (LinesCollection != null)
{
KMLCollection.Add("LINES", LinesCollection);
}
return KMLCollection;
}
private void readKML(string fileName)
{
using (XmlReader xmlReader = XmlReader.Create(fileName))
{
while (xmlReader.Read())
{
switch (xmlReader.NodeType)
{
case XmlNodeType.Element:
switch (xmlReader.Name.ToUpper())
{
case "POINT":
currentGeometry = kmlGeometryType.POINT;
Point = new Hashtable();
break;
case "LINESTRING":
currentGeometry = kmlGeometryType.LINESTRING;
Line = new Hashtable();
break;
case "COORDINATES":
currentKmlTag = kmlTagType.COORDINATES;
break;
}
break;
case XmlNodeType.EndElement:
switch (xmlReader.Name.ToUpper())
{
case "POINT":
if (Point != null)
{
PointsCollection.Add(Point);
}
Point = null;
currentGeometry = null;
currentKmlTag = null;
break;
case "LINESTRING":
if (Line != null)
{
LinesCollection.Add(Line);
}
Line = null;
currentGeometry = null;
currentKmlTag = null;
break;
}
break;
case XmlNodeType.Text:
case XmlNodeType.CDATA:
case XmlNodeType.Comment:
case XmlNodeType.XmlDeclaration:
{
kmlTagType? kmlTagType2 = currentKmlTag;
if (kmlTagType2.HasValue)
{
kmlTagType value = kmlTagType2.Value;
if (value == kmlTagType.COORDINATES)
{
parseGeometryVal(xmlReader.Value);
}
}
break;
}
}
}
}
}
protected void parseGeometryVal(string tag_value)
{
kmlGeometryType? kmlGeometryType2 = currentGeometry;
if (kmlGeometryType2.HasValue)
{
switch (kmlGeometryType2.Value)
{
case kmlGeometryType.POINT:
parsePoint(tag_value);
break;
case kmlGeometryType.LINESTRING:
parseLine(tag_value);
break;
}
}
}
protected void parsePoint(string tag_value)
{
Hashtable hashtable = null;
kmlTagType? kmlTagType2 = currentKmlTag;
if (!kmlTagType2.HasValue)
{
return;
}
kmlTagType value = kmlTagType2.Value;
if (value == kmlTagType.COORDINATES)
{
hashtable = new Hashtable();
string[] array = tag_value.Split(',');
if (array.Length < 2)
{
lastError = "ERROR IN FORMAT OF POINT COORDINATES";
}
hashtable.Add("LNG", array[0].Trim());
hashtable.Add("LAT", array[1].Trim());
Point.Add("COORDINATES", hashtable);
}
}
protected void parseLine(string tag_value)
{
kmlTagType? kmlTagType2 = currentKmlTag;
if (!kmlTagType2.HasValue)
{
return;
}
kmlTagType value = kmlTagType2.Value;
if (value != kmlTagType.COORDINATES)
{
return;
}
string[] array = tag_value.Trim().Split(' ');
string[] array2 = array;
foreach (string text in array2)
{
string[] array3 = text.Split(',');
if (array3.Length < 2)
{
LastError = "ERROR IN FORMAT OF LINESTRING COORDINATES";
}
points.Add(new Vector3(float.Parse(array3[0]), float.Parse(array3[2]), float.Parse(array3[1])));
}
}
public Vector3[] GetPoints(float scale)
{
Bounds bounds = new Bounds(points[0], Vector3.zero);
for (int i = 0; i < points.Count; i++)
{
bounds.Encapsulate(points[i]);
}
for (int j = 0; j < points.Count; j++)
{
points[j] = ConvertLatLon(points[j], bounds.center, scale, false);
}
return points.ToArray();
}
private Vector3 ConvertLatLon(Vector3 pos, Vector3 centre, float scale, bool adjust)
{
double num = 111322.3167 / (double)scale;
double num2 = pos.x - centre.x;
double num3 = pos.y - centre.y;
double num4 = pos.z - centre.z;
Vector3 result = default(Vector3);
if (adjust)
{
double num5 = 6378137.0;
result.x = (float)(num4 * (2.0 * (double)Mathf.Tan((float)Math.PI / 360f) * num5 * (double)Mathf.Cos((float)Math.PI / 180f * (float)num2)));
}
else
{
result.x = (float)(num4 * num);
}
result.z = (float)((0.0 - num2) * num);
result.y = (float)num3;
return result;
}
}