/Assets/Mapbox/Examples/2_LocationProvider/Scripts/MapMatchingExample.cs

https://github.com/mapbox/mapbox-ar-unity · C# · 176 lines · 145 code · 28 blank · 3 comment · 10 complexity · 42d7d84ba076bc8e8e8f3326b1961fd4 MD5 · raw file

  1. namespace Mapbox.Examples
  2. {
  3. using Mapbox.Unity;
  4. using Mapbox.Utils;
  5. using Mapbox.Unity.Utilities;
  6. using Mapbox.Unity.Map;
  7. using System.Collections.Generic;
  8. using Mapbox.MapMatching;
  9. using UnityEngine;
  10. using System.Linq;
  11. using Mapbox.Unity.Location;
  12. using System;
  13. public class MapMatchingExample : MonoBehaviour
  14. {
  15. [SerializeField]
  16. AbstractMap _map;
  17. [SerializeField]
  18. LineRenderer _originalRoute;
  19. [SerializeField]
  20. LineRenderer _mapMatchRoute;
  21. [SerializeField]
  22. bool _useTransformLocationProvider;
  23. [SerializeField]
  24. Profile _profile;
  25. [SerializeField]
  26. float _lineHeight = 1f;
  27. List<Location> _locations = new List<Location>();
  28. MapMatcher _mapMatcher;
  29. ILocationProvider _locationProvider;
  30. public ILocationProvider LocationProvider
  31. {
  32. private get
  33. {
  34. if (_locationProvider == null)
  35. {
  36. _locationProvider = _useTransformLocationProvider ?
  37. LocationProviderFactory.Instance.TransformLocationProvider : LocationProviderFactory.Instance.DefaultLocationProvider;
  38. }
  39. return _locationProvider;
  40. }
  41. set
  42. {
  43. if (_locationProvider != null)
  44. {
  45. _locationProvider.OnLocationUpdated -= LocationProvider_OnLocationUpdated;
  46. }
  47. _locationProvider = value;
  48. _locationProvider.OnLocationUpdated += LocationProvider_OnLocationUpdated;
  49. }
  50. }
  51. void Awake()
  52. {
  53. _mapMatcher = MapboxAccess.Instance.MapMatcher;
  54. }
  55. void Start()
  56. {
  57. LocationProvider.OnLocationUpdated += LocationProvider_OnLocationUpdated;
  58. }
  59. void OnDestroy()
  60. {
  61. LocationProvider.OnLocationUpdated -= LocationProvider_OnLocationUpdated;
  62. }
  63. void LocationProvider_OnLocationUpdated(Location location)
  64. {
  65. if (location.IsLocationUpdated)
  66. {
  67. _locations.Add(location);
  68. var position = Conversions.GeoToWorldPosition(
  69. location.LatitudeLongitude,
  70. _map.CenterMercator,
  71. _map.WorldRelativeScale).ToVector3xz();
  72. position.y = _lineHeight;
  73. var count = _locations.Count;
  74. _originalRoute.positionCount = count;
  75. _originalRoute.SetPosition(count - 1, position);
  76. }
  77. }
  78. [ContextMenu("Map Match")]
  79. public void Match()
  80. {
  81. if (_locations.Count < 2)
  82. {
  83. Debug.LogWarning("Need at least two coordinates for map matching.");
  84. return;
  85. }
  86. var resource = new MapMatchingResource();
  87. //API allows for max 100 coordinates, take newest.
  88. var locations = _locations.Skip(System.Math.Max(0, _locations.Count - 100)).ToArray();
  89. var coords = new List<Vector2d>();
  90. var radiuses = new List<uint>();
  91. var timestamps = new List<long>();
  92. foreach (var location in locations)
  93. {
  94. coords.Add(location.LatitudeLongitude);
  95. radiuses.Add((uint)Mathf.Min(location.Accuracy, 30));
  96. timestamps.Add((long)location.Timestamp);
  97. }
  98. resource.Coordinates = coords.ToArray();
  99. resource.Radiuses = radiuses.ToArray();
  100. resource.Timestamps = timestamps.ToArray();
  101. resource.Profile = _profile;
  102. _mapMatcher.Match(resource, HandleMapMatchResponse);
  103. }
  104. void HandleMapMatchResponse(MapMatching.MapMatchingResponse response)
  105. {
  106. if (response.HasMatchingError)
  107. {
  108. Debug.LogError("MapMatchingExample: " + response.MatchingError);
  109. return;
  110. }
  111. if (response.HasRequestError)
  112. {
  113. foreach (var exception in response.RequestExceptions)
  114. {
  115. Debug.LogError("MapMatchingExample: " + exception);
  116. }
  117. return;
  118. }
  119. var lineCount = 1;
  120. var tracepointsCount = response.Tracepoints.Length;
  121. foreach (var point in response.Tracepoints)
  122. {
  123. // Tracepoints can be null, so let's avoid trying to process those outliers.
  124. // see https://www.mapbox.com/api-documentation/#match-response-object
  125. if (point == null)
  126. {
  127. continue;
  128. }
  129. _mapMatchRoute.positionCount = lineCount;
  130. Debug.Log(string.Format(
  131. "MapMatchingExample: {1}{0}Location: {2}{0}MatchtingsIndex: {3}{0}WaypointIndex: {4}"
  132. , Environment.NewLine
  133. , point.Name
  134. , point.Location
  135. , point.MatchingsIndex
  136. , point.WaypointIndex
  137. ));
  138. var position = Conversions.GeoToWorldPosition(
  139. point.Location,
  140. _map.CenterMercator,
  141. _map.WorldRelativeScale).ToVector3xz();
  142. position.y = _lineHeight = 1f;
  143. _mapMatchRoute.SetPosition(lineCount - 1, position);
  144. lineCount++;
  145. }
  146. }
  147. }
  148. }