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 PointsCollection = new List(); private List LinesCollection = new List(); 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 points = new List(); 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; } }