11package com .mapbox .services .android .navigation .v5 ;
22
3- import android .location .Location ;
4-
3+ import com .google .auto .value .AutoValue ;
54import com .mapbox .services .Constants ;
65import com .mapbox .services .Experimental ;
76import com .mapbox .services .android .navigation .v5 .models .RouteLegProgress ;
87import com .mapbox .services .api .directions .v5 .models .DirectionsRoute ;
98import com .mapbox .services .api .directions .v5 .models .RouteLeg ;
109import com .mapbox .services .api .utils .turf .TurfConstants ;
10+ import com .mapbox .services .api .utils .turf .TurfMeasurement ;
1111import com .mapbox .services .api .utils .turf .TurfMisc ;
12- import com .mapbox .services .commons .geojson .Feature ;
12+ import com .mapbox .services .commons .geojson .LineString ;
1313import com .mapbox .services .commons .geojson .Point ;
1414import com .mapbox .services .commons .models .Position ;
1515import com .mapbox .services .commons .utils .PolylineUtils ;
2929 * @since 0.1.0
3030 */
3131@ Experimental
32- public class RouteProgress {
32+ @ AutoValue
33+ public abstract class RouteProgress {
34+
35+ public abstract RouteLegProgress currentLegProgress ();
36+
37+ public abstract DirectionsRoute route ();
38+
39+ public abstract Position userSnappedPosition ();
3340
34- private RouteLegProgress currentLegProgress ;
35- private DirectionsRoute route ;
36- private Location location ;
37- private int LegIndex ;
38- private int alertUserLevel ;
39- private double routeDistance ;
40- private int stepIndex ;
41+ public abstract int legIndex ();
42+
43+ public abstract int alertUserLevel ();
4144
4245 /**
4346 * Constructor for the route routeProgress information.
4447 *
45- * @param route the {@link DirectionsRoute} being used for the navigation session. When a user is
46- * rerouted this route is updated.
47- * @param location the users location most recently used when creating this object.
48- * @param stepIndex an {@code integer} representing the current step index the user is on.
49- * @param alertUserLevel the most recently calculated alert level.
48+ * @param route the {@link DirectionsRoute} being used for the navigation session. When a user is
49+ * rerouted this route is updated.
50+ * @param userSnappedPosition the users position most recently used when creating this object.
51+ * @param stepIndex an {@code integer} representing the current step index the user is on.
52+ * @param alertUserLevel the most recently calculated alert level.
5053 * @since 0.1.0
5154 */
52- RouteProgress (DirectionsRoute route , Location location , int legIndex , int stepIndex , int alertUserLevel ) {
53- this .route = route ;
54- this .alertUserLevel = alertUserLevel ;
55- this .location = location ;
56- this .LegIndex = legIndex ;
57- this .stepIndex = stepIndex ;
58- currentLegProgress = new RouteLegProgress (getCurrentLeg (), stepIndex , getUsersCurrentSnappedPosition ());
59- initialize ();
60- }
61-
62- private void initialize () {
63- // Measure route from beginning to end. This is done since the directions API gives a different distance then the
64- // one we measure using turf.
65- routeDistance = RouteUtils .getDistanceToEndOfRoute (
66- route .getLegs ().get (0 ).getSteps ().get (0 ).getManeuver ().asPosition (),
67- route ,
68- TurfConstants .UNIT_METERS
69- );
55+ public static RouteProgress create (
56+ DirectionsRoute route , Position userSnappedPosition , int legIndex , int stepIndex , int alertUserLevel ) {
57+ RouteLegProgress routeLegProgress
58+ = RouteLegProgress .create (route .getLegs ().get (legIndex ), stepIndex , userSnappedPosition );
59+ return new AutoValue_RouteProgress (
60+ routeLegProgress , route , userSnappedPosition , legIndex , alertUserLevel );
7061 }
7162
7263 /**
@@ -76,7 +67,7 @@ private void initialize() {
7667 * @since 0.1.0
7768 */
7869 public RouteLegProgress getCurrentLegProgress () {
79- return currentLegProgress ;
70+ return currentLegProgress () ;
8071 }
8172
8273 /**
@@ -86,7 +77,7 @@ public RouteLegProgress getCurrentLegProgress() {
8677 * @since 0.1.0
8778 */
8879 public int getLegIndex () {
89- return LegIndex ;
80+ return legIndex () ;
9081 }
9182
9283 /**
@@ -95,7 +86,7 @@ public int getLegIndex() {
9586 * @return a {@link RouteLeg} the user is currently on.
9687 */
9788 public RouteLeg getCurrentLeg () {
98- return route .getLegs ().get (getLegIndex ());
89+ return route () .getLegs ().get (getLegIndex ());
9990 }
10091
10192 /**
@@ -105,7 +96,11 @@ public RouteLeg getCurrentLeg() {
10596 * @since 0.1.0
10697 */
10798 public double getDistanceTraveled () {
108- return routeDistance - getDistanceRemaining ();
99+ double distanceTraveled = route ().getDistance () - getDistanceRemaining ();
100+ if (distanceTraveled < 0 ) {
101+ distanceTraveled = 0 ;
102+ }
103+ return distanceTraveled ;
109104 }
110105
111106 /**
@@ -114,8 +109,8 @@ public double getDistanceTraveled() {
114109 * @return {@code long} value representing the duration remaining till end of route, in unit seconds.
115110 * @since 0.1.0
116111 */
117- public long getDurationRemaining () {
118- return (long ) (( 1 - getFractionTraveled ()) * route .getDuration () );
112+ public double getDurationRemaining () {
113+ return (1 - getFractionTraveled ()) * route () .getDuration ();
119114 }
120115
121116 /**
@@ -126,7 +121,12 @@ public long getDurationRemaining() {
126121 * @since 0.1.0
127122 */
128123 public float getFractionTraveled () {
129- return (float ) (getDistanceTraveled () / routeDistance );
124+ float fractionRemaining = 1 ;
125+
126+ if (route ().getDistance () > 0 ) {
127+ fractionRemaining = (float ) (getDistanceTraveled () / route ().getDistance ());
128+ }
129+ return fractionRemaining ;
130130 }
131131
132132 /**
@@ -136,7 +136,22 @@ public float getFractionTraveled() {
136136 * @since 0.1.0
137137 */
138138 public double getDistanceRemaining () {
139- return RouteUtils .getDistanceToEndOfRoute (getUsersCurrentSnappedPosition (), route , TurfConstants .UNIT_METERS );
139+ double distanceRemaining = 0 ;
140+
141+ List <Position > coords = PolylineUtils .decode (currentLegProgress ().getCurrentStep ().getGeometry (),
142+ Constants .PRECISION_6 );
143+ if (coords .size () > 1 ) {
144+ LineString slicedLine = TurfMisc .lineSlice (
145+ Point .fromCoordinates (userSnappedPosition ()),
146+ Point .fromCoordinates (coords .get (coords .size () - 1 )),
147+ LineString .fromCoordinates (coords )
148+ );
149+ distanceRemaining += TurfMeasurement .lineDistance (slicedLine , TurfConstants .UNIT_METERS );
150+ }
151+ for (int i = currentLegProgress ().getStepIndex () + 1 ; i < getCurrentLeg ().getSteps ().size (); i ++) {
152+ distanceRemaining += getCurrentLeg ().getSteps ().get (i ).getDistance ();
153+ }
154+ return distanceRemaining ;
140155 }
141156
142157 /**
@@ -146,7 +161,7 @@ public double getDistanceRemaining() {
146161 * @since 0.1.0
147162 */
148163 public int getAlertUserLevel () {
149- return alertUserLevel ;
164+ return alertUserLevel () ;
150165 }
151166
152167 /**
@@ -156,25 +171,6 @@ public int getAlertUserLevel() {
156171 * @since 0.1.0
157172 */
158173 public DirectionsRoute getRoute () {
159- return route ;
160- }
161-
162- /**
163- * Provides the users location snapped to the current route they are navigating on.
164- *
165- * @return {@link Position} object with coordinates snapping the user to the route.
166- * @since 0.1.0
167- */
168- public Position getUsersCurrentSnappedPosition () {
169- Point locationToPoint = Point .fromCoordinates (new double [] {location .getLongitude (), location .getLatitude ()});
170- String stepGeometry = route .getLegs ().get (getLegIndex ()).getSteps ().get (stepIndex ).getGeometry ();
171-
172- // Decode the geometry
173- List <Position > coords = PolylineUtils .decode (stepGeometry , Constants .PRECISION_6 );
174-
175- // Uses Turf's pointOnLine, which takes a Point and a LineString to calculate the closest
176- // Point on the LineString.
177- Feature feature = TurfMisc .pointOnLine (locationToPoint , coords );
178- return ((Point ) feature .getGeometry ()).getCoordinates ();
174+ return route ();
179175 }
180176}
0 commit comments