MegaKML.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. 
  2. using UnityEngine;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Xml;
  6. using System.Collections;
  7. public class MegaKML
  8. {
  9. enum kmlGeometryType
  10. {
  11. POINT,
  12. LINESTRING
  13. }
  14. enum kmlTagType
  15. {
  16. POINT,
  17. LINESTRING,
  18. COORDINATES
  19. }
  20. List<Hashtable> PointsCollection = new List<Hashtable>(); //all parsed kml points
  21. List<Hashtable> LinesCollection = new List<Hashtable>(); //all parsed kml lines
  22. Hashtable Point; //single point (part of PointsCollection)
  23. Hashtable Line; //single line (part of LinesCollection)
  24. Hashtable Coordinates; //object coordinate
  25. Hashtable KMLCollection = new Hashtable();//parsed KML
  26. kmlGeometryType? currentGeometry = null;//currently parsed geometry object
  27. kmlTagType? currentKmlTag = null;//currently parsed kml tag
  28. string lastError;
  29. List<Vector3> points = new List<Vector3>();
  30. public Hashtable KMLDecode(string fileName)
  31. {
  32. points.Clear();
  33. readKML(fileName);
  34. if ( PointsCollection != null )
  35. KMLCollection.Add("POINTS", PointsCollection);
  36. if ( LinesCollection != null )
  37. KMLCollection.Add("LINES", LinesCollection);
  38. return KMLCollection;
  39. }
  40. private void readKML(string fileName)
  41. {
  42. using ( XmlReader kmlread = XmlReader.Create(fileName) )
  43. {
  44. while ( kmlread.Read() )//read kml node by node
  45. {
  46. switch ( kmlread.NodeType )
  47. {
  48. case XmlNodeType.Element:
  49. switch ( kmlread.Name.ToUpper() )
  50. {
  51. case "POINT":
  52. currentGeometry = kmlGeometryType.POINT;
  53. Point = new Hashtable();
  54. break;
  55. case "LINESTRING":
  56. currentGeometry = kmlGeometryType.LINESTRING;
  57. Line = new Hashtable();
  58. break;
  59. case "COORDINATES":
  60. currentKmlTag = kmlTagType.COORDINATES;
  61. break;
  62. }
  63. break;
  64. case XmlNodeType.EndElement:
  65. switch ( kmlread.Name.ToUpper() )
  66. {
  67. case "POINT":
  68. if ( Point != null )
  69. PointsCollection.Add(Point);
  70. Point = null;
  71. currentGeometry = null;
  72. currentKmlTag = null;
  73. break;
  74. case "LINESTRING":
  75. if ( Line != null )
  76. LinesCollection.Add(Line);
  77. Line = null;
  78. currentGeometry = null;
  79. currentKmlTag = null;
  80. break;
  81. }
  82. break;
  83. case XmlNodeType.Text:
  84. case XmlNodeType.CDATA:
  85. case XmlNodeType.Comment:
  86. case XmlNodeType.XmlDeclaration:
  87. switch ( currentKmlTag )
  88. {
  89. case kmlTagType.COORDINATES:
  90. parseGeometryVal(kmlread.Value);//try to parse coordinates
  91. break;
  92. }
  93. break;
  94. case XmlNodeType.DocumentType:
  95. break;
  96. default: break;
  97. }
  98. }
  99. }
  100. }
  101. protected void parseGeometryVal(string tag_value)
  102. {
  103. switch ( currentGeometry )
  104. {
  105. case kmlGeometryType.POINT:
  106. parsePoint(tag_value);
  107. break;
  108. case kmlGeometryType.LINESTRING:
  109. parseLine(tag_value);
  110. break;
  111. }
  112. }
  113. protected void parsePoint(string tag_value)
  114. {
  115. Hashtable value = null;
  116. string[] coordinates;
  117. switch ( currentKmlTag )
  118. {
  119. case kmlTagType.COORDINATES:
  120. value = new Hashtable();
  121. coordinates = tag_value.Split(',');
  122. if ( coordinates.Length < 2 )
  123. lastError = "ERROR IN FORMAT OF POINT COORDINATES";
  124. value.Add("LNG", coordinates[0].Trim());
  125. value.Add("LAT", coordinates[1].Trim());
  126. Point.Add("COORDINATES", value);
  127. break;
  128. }
  129. }
  130. protected void parseLine(string tag_value)
  131. {
  132. string[] vertex;
  133. string[] coordinates;
  134. switch ( currentKmlTag )
  135. {
  136. case kmlTagType.COORDINATES:
  137. vertex = tag_value.Trim().Split(' ');//Split linestring to vertexes
  138. foreach ( string point in vertex )
  139. {
  140. coordinates = point.Split(',');
  141. if ( coordinates.Length < 2 )
  142. LastError = "ERROR IN FORMAT OF LINESTRING COORDINATES";
  143. points.Add(new Vector3(float.Parse(coordinates[0]), float.Parse(coordinates[2]), float.Parse(coordinates[1])));
  144. }
  145. break;
  146. }
  147. }
  148. public string LastError
  149. {
  150. get { return lastError; }
  151. set
  152. {
  153. lastError = value;
  154. throw new System.Exception(lastError);
  155. }
  156. }
  157. public Vector3[] GetPoints(float scale)
  158. {
  159. Bounds bounds = new Bounds(points[0], Vector3.zero);
  160. for ( int i = 0; i < points.Count; i++ )
  161. bounds.Encapsulate(points[i]);
  162. for ( int i = 0; i < points.Count; i++ )
  163. points[i] = ConvertLatLon(points[i], bounds.center, scale, false);
  164. return points.ToArray();
  165. }
  166. Vector3 ConvertLatLon(Vector3 pos, Vector3 centre, float scale, bool adjust)
  167. {
  168. double scl = (111322.3167 / scale);
  169. double x = pos.x - centre.x;
  170. double y = pos.y - centre.y;
  171. double z = pos.z - centre.z;
  172. Vector3 p;
  173. if ( adjust )
  174. {
  175. double r = 6378137.0;
  176. p.x = (float)(z * (2.0 * Mathf.Tan(Mathf.Deg2Rad * (0.5f)) * r * Mathf.Cos(Mathf.Deg2Rad * (float)x)));
  177. }
  178. else
  179. p.x = (float)(z * scl);
  180. p.z = (float)(-x * scl);
  181. p.y = (float)y;
  182. return p;
  183. }
  184. }
  185. // 219