CreatePointOfInterestTextMeshes.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. using System.Collections;
  2. using System.Globalization;
  3. using System.Xml;
  4. using UnityEngine;
  5. using UnityEngine.Networking;
  6. // ReSharper disable InconsistentNaming
  7. // ReSharper disable Unity.PerformanceCriticalCodeInvocation
  8. namespace ARLocation.Utils
  9. {
  10. public class POIData
  11. {
  12. public Location location;
  13. public string name;
  14. }
  15. [System.Serializable]
  16. public class OverpassRequestData
  17. {
  18. [Tooltip("The SouthWest end of the bounding box.")]
  19. public Location SouthWest;
  20. [Tooltip("The NorthEast end of the bounding box.")]
  21. public Location NorthEast;
  22. }
  23. [System.Serializable]
  24. public class OpenStreetMapOptions
  25. {
  26. [Tooltip("A XML with the results of a Overpass API query. You can use http://overpass-turbo.eu/ to generate one.")]
  27. public TextAsset OsmXmlFile;
  28. [Tooltip("If true, instead of the XML file above, we fetch the data directly from a Overpass API request to https://www.overpass-api.de/api/interpreter.")]
  29. public bool FetchFromOverpassApi;
  30. [Tooltip("The data configuration used for the Overpass API request. Basically a bounding box rectangle defined by two points.")]
  31. public OverpassRequestData overPassRequestData;
  32. }
  33. public class CreatePointOfInterestTextMeshes : MonoBehaviour
  34. {
  35. [Tooltip("The height of the text mesh, relative to the device.")]
  36. public float height = 1f;
  37. [Tooltip("The TextMesh prefab.")]
  38. public TextMesh textPrefab;
  39. [Tooltip("The smoothing factor for movement due to GPS location adjustments; if set to zero it is disabled."), Range(0, 500)]
  40. public float movementSmoothingFactor = 100.0f;
  41. [Tooltip("Locations where the text will be displayed. The text will be the Label property. (Optional)")]
  42. public Location[] locations;
  43. [Tooltip("Use this to either fetch OpenStreetMap data from a Overpass API request, or via a locally stored XML file. (Optional)")]
  44. public OpenStreetMapOptions openStreetMapOptions;
  45. POIData[] poiData;
  46. // List<ARLocationManagerEntry> entries = new List<ARLocationManagerEntry>();
  47. string xmlFileText;
  48. // Use this for initialization
  49. void Start()
  50. {
  51. // CreateTextObjects();
  52. AddLocationsPOIs();
  53. if (openStreetMapOptions.FetchFromOverpassApi && openStreetMapOptions.overPassRequestData != null)
  54. {
  55. StartCoroutine(nameof(LoadXMLFileFromOverpassRequest));
  56. }
  57. else if (openStreetMapOptions.OsmXmlFile != null)
  58. {
  59. LoadXMLFileFromTextAsset();
  60. }
  61. }
  62. private void LoadXMLFileFromTextAsset()
  63. {
  64. CreateTextObjects(openStreetMapOptions.OsmXmlFile.text);
  65. }
  66. string GetOverpassRequestURL(OverpassRequestData data)
  67. {
  68. var lat1 = data.SouthWest.Latitude;
  69. var lng1 = data.SouthWest.Longitude;
  70. var lat2 = data.NorthEast.Latitude;
  71. var lng2 = data.NorthEast.Longitude;
  72. return "https://www.overpass-api.de/api/interpreter?data=[out:xml];node[amenity](" + lat1 + "," + lng1 + "," + lat2 + "," + lng2 + ");out%20meta;";
  73. }
  74. IEnumerator LoadXMLFileFromOverpassRequest()
  75. {
  76. var www = UnityWebRequest.Get(GetOverpassRequestURL(openStreetMapOptions.overPassRequestData));
  77. yield return www.SendWebRequest();
  78. if (Utils.Misc.WebRequestResultIsError(www))
  79. {
  80. Debug.Log(www.error);
  81. Debug.Log(GetOverpassRequestURL(openStreetMapOptions.overPassRequestData));
  82. }
  83. else
  84. {
  85. // Show results as text
  86. Debug.Log(www.downloadHandler.text);
  87. CreateTextObjects(www.downloadHandler.text);
  88. }
  89. }
  90. public string GetNodeTagValue(XmlNode node, string tagName)
  91. {
  92. var children = node.ChildNodes;
  93. foreach (XmlNode nodeTag in children)
  94. {
  95. if (nodeTag.Attributes != null && nodeTag.Attributes["k"].Value == tagName)
  96. {
  97. return nodeTag.Attributes["v"].Value;
  98. }
  99. }
  100. return null;
  101. }
  102. public string GetNodeName(XmlNode node)
  103. {
  104. return (GetNodeTagValue(node, "poiName") ?? GetNodeTagValue(node, "amenity")) ?? "No Name";
  105. }
  106. // Update is called once per frame
  107. void CreateTextObjects(string text)
  108. {
  109. XmlDocument xmlDoc = new XmlDocument();
  110. xmlDoc.LoadXml(text);
  111. var nodes = xmlDoc.GetElementsByTagName("node");
  112. poiData = new POIData[nodes.Count];
  113. var i = 0;
  114. foreach (XmlNode node in nodes)
  115. {
  116. if (node.Attributes != null)
  117. {
  118. double lat = double.Parse(node.Attributes["lat"].Value, CultureInfo.InvariantCulture);
  119. double lng = double.Parse(node.Attributes["lon"].Value, CultureInfo.InvariantCulture);
  120. var nodeName = GetNodeName(node);
  121. poiData[i] = new POIData
  122. {
  123. location = new Location()
  124. {
  125. Latitude = lat,
  126. Longitude = lng,
  127. AltitudeMode = AltitudeMode.GroundRelative,
  128. Altitude = height
  129. },
  130. name = nodeName
  131. };
  132. }
  133. i++;
  134. }
  135. for (var k = 0; k < poiData.Length; k++)
  136. {
  137. AddPOI(poiData[k].location, poiData[k].name);
  138. }
  139. }
  140. void AddLocationsPOIs()
  141. {
  142. foreach (var location in locations)
  143. {
  144. AddPOI(location, location.Label);
  145. }
  146. }
  147. // ReSharper disable once UnusedParameter.Local
  148. void AddPOI(Location location, string poiName)
  149. {
  150. var textInstance = PlaceAtLocation.CreatePlacedInstance(textPrefab.gameObject, location,
  151. new PlaceAtLocation.PlaceAtOptions()
  152. {
  153. MovementSmoothing = 0.1f,
  154. HideObjectUntilItIsPlaced = true,
  155. MaxNumberOfLocationUpdates = 10,
  156. UseMovingAverage = false
  157. }, true);
  158. textInstance.GetComponent<TextMesh>().text = poiName;
  159. }
  160. }
  161. }