Skip to content

Commit 5d0c1b9

Browse files
jl-skylinezugaldia
authored andcommitted
Add map matching property getters (#270)
* Add mapmatching property parsers and their tests * Clean up unused imports and unthrown exception * Fix Typo * Fix more typo * Testing user name * Update property parser and testing * Remove coord times from response * Clean up unused import. validate checkstyle, test-java, test-android
1 parent 5a3f31c commit 5d0c1b9

5 files changed

Lines changed: 141 additions & 7 deletions

File tree

mapbox/app/src/main/java/com/mapbox/services/android/testapp/utils/MapMatchingActivity.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,15 @@ public void onResponse(Call<MapMatchingResponse> call, Response<MapMatchingRespo
221221
// Check that the map matching API response is "OK".
222222
if (response.code() == 200) {
223223
// Convert the map matched response list from position to latlng coordinates.
224-
for (int i = 0; i < response.body().getMatchedPoints().length; i++) {
224+
Position[] positions = response.body().getMatchedPoints();
225+
if (positions == null) {
226+
return;
227+
}
228+
229+
for (int i = 0; i < positions.length; i++) {
225230
mapMatchedPoints.add(new LatLng(
226-
response.body().getMatchedPoints()[i].getLatitude(),
227-
response.body().getMatchedPoints()[i].getLongitude()));
231+
positions[i].getLatitude(),
232+
positions[i].getLongitude()));
228233
}
229234

230235
if (mapMatchedRoute != null) {

mapbox/libjava-geojson/src/test/java/com/mapbox/services/commons/geojson/FeatureTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,4 @@ public void testNonNullProperties() {
5252
Feature feature = Feature.fromGeometry(line, properties);
5353
assertTrue(feature.toJson().contains("\"properties\":{\"key\":\"value\"}"));
5454
}
55-
5655
}

mapbox/libjava-services/src/main/java/com/mapbox/services/api/mapmatching/v4/models/MapMatchingResponse.java

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
import com.mapbox.services.commons.geojson.FeatureCollection;
77
import com.mapbox.services.commons.models.Position;
88

9+
import java.util.ArrayList;
910
import java.util.List;
1011

1112
/**
12-
* Mapbox map matching API response
13+
* Mapbox map matching API response and convenience getter methods for optional properties
14+
* @see <a href="https://www.mapbox.com/api-documentation/#retrieve-a-match">Map Matching API Documentation</a>
1315
*
1416
* @since 1.2.0
1517
*/
@@ -19,6 +21,9 @@ public class MapMatchingResponse extends FeatureCollection {
1921

2022
private String code;
2123

24+
/** A placeholder for the best matched points for optimizing multiple calls */
25+
private Position[] bestMatchedPoints;
26+
2227
public MapMatchingResponse(List<Feature> features) {
2328
super(features);
2429
}
@@ -56,7 +61,7 @@ public void setCode(String code) {
5661
* @since 1.2.0
5762
*/
5863
public Position[] getMatchedPoints() {
59-
return getMatchedPoints(0);
64+
return bestMatchedPoints != null ? bestMatchedPoints : (bestMatchedPoints = getMatchedPoints(0));
6065
}
6166

6267
/**
@@ -65,6 +70,31 @@ public Position[] getMatchedPoints() {
6570
* create several sub-matches, each as a feature. The higher the number of features, the more
6671
* likely that the input traces are poorly aligned to the road network.
6772
*
73+
* <p>
74+
* Implementation Note:<br>
75+
* A caller should consider using returned array as an instance rather than as a reference to the array
76+
*
77+
* <pre>
78+
* for (int index = 0; index < MapMatchingResponse.getMatchedPoints(bestIndex).length; index++) {
79+
* .. do some work
80+
* double latitude = MapMatchingResponse.getMatchedPoints(bestIndex).getLatitude();
81+
* .. do more work
82+
* }
83+
* </pre>
84+
* <p>This can be optimized in performance as below</p>
85+
* <pre>
86+
* Position[] points = MapMatchingResponse.getMatchedPoints(bestIndex);
87+
* if (points == null) {
88+
* return;
89+
* }
90+
*
91+
* for (int index = 0; index < points.length; index++) {
92+
* .. do some work
93+
* double latitude = points[index].getLatitude();
94+
* .. do more work
95+
* }
96+
* </pre>
97+
*
6898
* @param submatch Which sub-match you want to get the position for.
6999
* @return Array of {@link Position} that have been map matched.
70100
* @since 1.2.0
@@ -79,7 +109,73 @@ public Position[] getMatchedPoints(int submatch) {
79109
points.get(i).getAsJsonArray().get(0).getAsDouble(),
80110
points.get(i).getAsJsonArray().get(1).getAsDouble());
81111
}
112+
82113
return positions;
83114
}
84115

116+
/**
117+
* Convenience method to get a confidence value from Map Matching Response
118+
*
119+
* @param submatch A MapMatching sub-match value
120+
* @return a confidence value when a property exists and contains non-null value, otherwise null
121+
*/
122+
public Number getConfidence(int submatch) {
123+
final String CONFIDENCE = "confidence";
124+
if (!getFeatures().get(submatch).hasNonNullValueForProperty(CONFIDENCE)) {
125+
return null;
126+
}
127+
128+
return getFeatures().get(submatch).getProperties().get(CONFIDENCE).getAsNumber();
129+
}
130+
131+
/**
132+
* Convenience method to get distance property on Map Matching Response
133+
*
134+
* @param submatch A MapMatching sub-match value
135+
* @return total distance in meters when a property exists and contains non-null value, otherwise null
136+
*/
137+
public Number getDistance(int submatch) {
138+
final String DISTANCE = "distance";
139+
if (!getFeatures().get(submatch).hasNonNullValueForProperty(DISTANCE)) {
140+
return null;
141+
}
142+
143+
return getFeatures().get(submatch).getProperties().get(DISTANCE).getAsNumber();
144+
}
145+
146+
/**
147+
* Convenience method to get duration property on Map Matching Response
148+
*
149+
* @param submatch A MapMatching sub-match value
150+
* @return travel time in seconds when a property exists and contains non-null value, otherwise null
151+
*/
152+
public Number getDuration(int submatch) {
153+
final String DURATION = "duration";
154+
if (!getFeatures().get(submatch).hasNonNullValueForProperty(DURATION)) {
155+
return null;
156+
}
157+
158+
return getFeatures().get(submatch).getProperties().get(DURATION).getAsNumber();
159+
}
160+
161+
/**
162+
* Convenience method to get coordinate times property on Feature
163+
*
164+
* @param submatch A MapMatching sub-match value
165+
* @return Array of indices when a property exists and contains non-null value, otherwise null
166+
*/
167+
public List<Integer> getIndices(int submatch) {
168+
final String INDICES = "indices";
169+
if (!getFeatures().get(submatch).hasNonNullValueForProperty(INDICES)) {
170+
return null;
171+
}
172+
173+
JsonArray rawIndices = getFeatures().get(submatch).getProperty(INDICES).getAsJsonArray();
174+
List<Integer> indices = new ArrayList<>();
175+
for (int i = 0; i < rawIndices.size(); i ++) {
176+
indices.add(rawIndices.get(i).getAsInt());
177+
}
178+
179+
return indices;
180+
}
85181
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"code":"Ok","type":"FeatureCollection","features":[{"type":"Feature","geometry":"}}_rXahkccBz@OzEs@{O{Ws@kAaG}JsIoMwIwMuU}]uBgDg[sg@","properties":{"confidence":0.8820996720716853,"distance":291.6,"duration":40.5,"matchedPoints":[[13.418991,52.500625],[13.419147,52.501095],[13.419618,52.501754],[13.42004,52.502333],[13.420492,52.502983]],"indices":[0,1,2,3,4]}}]}
1+
{"code":"Ok","type":"FeatureCollection","features":[{"type":"Feature","geometry":"}}_rXahkccBz@OzEs@{O{Ws@kAaG}JsIoMwIwMuU}]uBgDg[sg@","properties":{"confidence":0.8820996720716853,"distance":291.6,"duration":40.5,"matchedPoints":[[13.418991,52.500625],[13.419147,52.501095],[13.419618,52.501754],[13.42004,52.502333],[13.420492,52.502983]],"indices":[0,1,2,3,4]}}]}

mapbox/libjava-services/src/test/java/com/mapbox/services/api/mapmatching/v4/MapboxMapMatchingTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
import java.nio.charset.Charset;
1616
import java.nio.file.Files;
1717
import java.nio.file.Paths;
18+
import java.text.ParseException;
1819
import java.util.ArrayList;
20+
import java.util.List;
1921

2022
import okhttp3.HttpUrl;
2123
import okhttp3.mockwebserver.Dispatcher;
@@ -215,6 +217,38 @@ public void testUserAgent() throws ServicesException, IOException {
215217
assertTrue(service.executeCall().raw().request().header("User-Agent").contains("APP"));
216218
}
217219

220+
@Test
221+
public void validConvenientMethodsFetchingMapMatchingProperties()
222+
throws ServicesException, IOException, ParseException {
223+
MapboxMapMatching client = new MapboxMapMatching.Builder()
224+
.setAccessToken(ACCESS_TOKEN)
225+
.setProfile(MapMatchingCriteria.PROFILE_DRIVING)
226+
.setTrace(trace)
227+
.setBaseUrl(mockUrl.toString())
228+
.build();
229+
Response<MapMatchingResponse> response = client.executeCall();
230+
assertEquals(response.code(), 200);
231+
232+
// Check the response body
233+
assertNotNull(response.body());
234+
assertEquals(1, response.body().getFeatures().size());
235+
236+
assertEquals("property confidence", 0.8820996720716853,
237+
response.body().getConfidence(0).doubleValue(), 0);
238+
assertEquals("property distance", 291.6,
239+
response.body().getDistance(0).doubleValue(), 0);
240+
assertEquals("property duration", 40.5,
241+
response.body().getDuration(0).doubleValue(), 0);
242+
243+
int[] mockIndices = new int[] {0, 1, 2, 3, 4};
244+
List<Integer> indices = response.body().getIndices(0);
245+
246+
// test indices counts
247+
assertEquals("property indices count", 5, indices.size());
248+
// sampling indices at 2
249+
assertEquals("property indices count", mockIndices[2], indices.get(2).doubleValue(), 0);
250+
}
251+
218252
// @Test
219253
// public void testPost() throws ServicesException, IOException {
220254
// MapboxMapMatching client = new MapboxMapMatching.Builder()

0 commit comments

Comments
 (0)