Skip to content

Support for StepIntersection.formOfWays and StepIntersection.geometries #1611

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Mapbox welcomes participation and contributions from everyone.

### main

- Added `StepIntersection#formOfWays` property which provides a list representing the "form of way" values for all roads at the step intersection. [#1611](https://github.com/mapbox/mapbox-java/pull/1611)
- Added `StepIntersection#geometries` property which provides a list representing geometry for all roads at the step intersection. [#1611](https://github.com/mapbox/mapbox-java/pull/1611)

### v7.4.0 - April 11, 2025

- Added `IntersectionLanes#access` property which provides lane access attributes, such as allowed vehicle types for designated lanes. [#1608](https://github.com/mapbox/mapbox-java/pull/1608)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,40 @@ public List<String> paymentMethodsList() {
@Nullable
public abstract Boolean suppressVoiceInstructionLocalNames();

/**
* Defines whether to return "form of way" values for roads at each {@link StepIntersection}.
* See {@link StepIntersection#formOfWays()} for details.
*
* @return boolean representing the `intersectionLinkFormOfWay` value
*/
@SerializedName("intersection_link_form_of_way")
@Nullable
public abstract Boolean intersectionLinkFormOfWay();

/**
* A comma-separated list of road types for which intersection geometry data should be included
* at each {@link StepIntersection}. See {@link StepIntersection#geometries()} for details.
* Possible values include:
* - "motorway"
* - "trunk"
* - "primary"
* - "secondary"
* - "tertiary"
* - "unclassified"
* - "residential"
* - "service_other"
* Geometry data will be provided for each intersection along the requested route.
* Be aware that enabling this option can significantly increase the response size
* and the memory required to store the response object. Use this option selectively, for example,
* if geometry is only needed for motorways, specify only "motorway".
*
* @return a comma-separated list of road types for which intersection geometry data
* should be included
*/
@SerializedName("intersection_link_geometry")
@Nullable
public abstract String intersectionLinkGeometry();

/**
* Gson type adapter for parsing Gson to this class.
*
Expand Down Expand Up @@ -1088,6 +1122,8 @@ public URL toUrl(@NonNull String accessToken) {
"suppress_voice_instruction_local_names",
suppressVoiceInstructionLocalNames()
);
appendQueryParameter(sb, "intersection_link_form_of_way", intersectionLinkFormOfWay());
appendQueryParameter(sb, "intersection_link_geometry", intersectionLinkGeometry());

Map<String, SerializableJsonElement> unrecognized = unrecognized();
if (unrecognized != null) {
Expand Down Expand Up @@ -2127,6 +2163,71 @@ public abstract Builder suppressVoiceInstructionLocalNames(
@Nullable Boolean suppressVoiceInstructionLocalNames
);

/**
* Defines whether to return "form of way" values for roads at each {@link StepIntersection}.
* See {@link StepIntersection#formOfWays()} for details.
*
* @param intersectionLinkFormOfWay whether to return "form of way" values
* @return this builder
*/
@NonNull
public abstract Builder intersectionLinkFormOfWay(
@Nullable Boolean intersectionLinkFormOfWay
);

/**
* A comma-separated list of road types for which intersection geometry data should be included
* at each {@link StepIntersection}. See {@link StepIntersection#geometries()} for details.
* Possible values include:
* - "motorway"
* - "trunk"
* - "primary"
* - "secondary"
* - "tertiary"
* - "unclassified"
* - "residential"
* - "service_other"
* Geometry data will be provided for each intersection along the requested route.
* Be aware that enabling this option can significantly increase the response size
* and the memory required to store the response object. Use this option selectively,
* for example, if geometry is only needed for motorways, specify only "motorway".
*
* @param intersectionLinkGeometry a comma-separated list of road types for which intersection
* geometry data should be included
* @return this builder
*/
@NonNull
public abstract Builder intersectionLinkGeometry(
@Nullable String intersectionLinkGeometry
);

/**
* A list of road types for which intersection geometry data should be included
* at each {@link StepIntersection}. See {@link StepIntersection#geometries()} for details.
* Possible values include:
* - "motorway"
* - "trunk"
* - "primary"
* - "secondary"
* - "tertiary"
* - "unclassified"
* - "residential"
* - "service_other"
* Geometry data will be provided for each intersection along the requested route.
* Be aware that enabling this option can significantly increase the response size
* and the memory required to store the response object. Use this option selectively,
* for example, if geometry is only needed for motorways, specify only "motorway".
*
* @param intersectionLinkGeometry a list of road types for which intersection geometry data
* should be included
* @return this builder
*/
@NonNull
public Builder intersectionLinkGeometry(@Nullable List<String> intersectionLinkGeometry) {
String result = FormatUtils.join(",", intersectionLinkGeometry);
return intersectionLinkGeometry(result);
}

/**
* Use this method to add request parameters,
* which are not present in the model yet but are supported on the Directions API,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,44 @@ public Point location() {
@Nullable
public abstract List<Boolean> entry();

/**
* A list representing the "form of way" values for all roads at the step intersection.
* This list has a 1:1 correspondence with the {@link #bearings()}, {@link #entry()},
* and {@link #geometries()} lists.
* Each element is either:
* - A list of strings representing the form(s) of way for a specific road, or
* - `null` if the form of way is unknown.
* Possible values for the form of way include:
* - "ramp"
* - "elevated"
* - "roundabout"
* - "service_road"
* Example:
* "form_of_way": [
* ["ramp", "elevated"],
* ["ramp"],
* null
* ]
*
* @return A list of form of way values for all roads at the step intersection
*/
@Nullable
@SerializedName("form_of_way")
public abstract List<List<String>> formOfWays();

/**
* A list representing geometry for all roads at the step intersection.
* This list has a 1:1 correspondence with the {@link #bearings()}, {@link #entry()},
* and {@link #formOfWays()} lists.
* Each element is either:
* - A strings representing geometry of a specific road, or
* - `null` if the geometry is unknown.
* @return A list of geometry for all roads at the step intersection
*/
@Nullable
@SerializedName("geometries")
public abstract List<String> geometries();

/**
* Index into bearings/entry array. Used to calculate the bearing before the turn. Namely, the
* clockwise angle from true north to the direction of travel before the maneuver/passing the
Expand Down Expand Up @@ -360,6 +398,45 @@ public abstract static class Builder extends DirectionsJsonObject.Builder<Builde
@NonNull
public abstract Builder entry(@Nullable List<Boolean> entry);

/**
* A list representing the "form of way" values for all roads at the step intersection.
* This list has a 1:1 correspondence with the {@link #bearings()}, {@link #entry()},
* and {@link #geometries()} lists.
* Each element is either:
* - A list of strings representing the form(s) of way for a specific road, or
* - `null` if the form of way is unknown.
* Possible values for the form of way include:
* - "ramp"
* - "elevated"
* - "roundabout"
* - "service_road"
* Example:
* "form_of_way": [
* ["ramp", "elevated"],
* ["ramp"],
* null
* ]
*
* @param formOfWays a list of form of way values for all roads at the step intersection
* @return this builder for chaining options together
*/
@NonNull
public abstract Builder formOfWays(List<List<String>> formOfWays);

/**
* A list representing geometry for all roads at the step intersection.
* This list has a 1:1 correspondence with the {@link #bearings()}, {@link #entry()},
* and {@link #formOfWays()} lists.
* Each element is either:
* - A strings representing geometry of a specific road, or
* - `null` if the geometry is unknown.
*
* @param geometries a list of geometry for all roads at the step intersection
* @return this builder for chaining options together
*/
@NonNull
public abstract Builder geometries(List<String> geometries);

/**
* Index into bearings/entry array. Used to calculate the bearing before the turn. Namely, the
* clockwise angle from true north to the direction of travel before the maneuver/passing the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.hamcrest.junit.ExpectedException;
Expand Down Expand Up @@ -261,4 +262,54 @@ public void directionsRoute_hasLaneAttributes() throws IOException {
.build();
assertEquals(access, lane.access());
}

@Test
public void directionsRoute_hasFormOfWays() throws IOException {
String json = loadJsonFixture("directions_v5_with_toll_costs_and_lanes.json");
RouteOptions options = RouteOptions.builder()
.profile(DirectionsCriteria.PROFILE_DRIVING_TRAFFIC)
.coordinatesList(new ArrayList<Point>() {{
add(Point.fromLngLat(1.0, 1.0));
add(Point.fromLngLat(2.0, 2.0));
}})
.build();
String uuid = "123";
DirectionsRoute route = DirectionsRoute.fromJson(json, options, uuid);

final List<List<String>> formOfWays = route.legs().get(0).steps().get(0).intersections().get(0)
.formOfWays();

final List<List<String>> expectedFormOfWays = Arrays.asList(
Collections.singletonList("ramp"),
Arrays.asList("ramp", "elevated"),
null
);

assertEquals(expectedFormOfWays, formOfWays);
}

@Test
public void directionsRoute_hasGeometries() throws IOException {
String json = loadJsonFixture("directions_v5_with_toll_costs_and_lanes.json");
RouteOptions options = RouteOptions.builder()
.profile(DirectionsCriteria.PROFILE_DRIVING_TRAFFIC)
.coordinatesList(new ArrayList<Point>() {{
add(Point.fromLngLat(1.0, 1.0));
add(Point.fromLngLat(2.0, 2.0));
}})
.build();
String uuid = "123";
DirectionsRoute route = DirectionsRoute.fromJson(json, options, uuid);

final List<String> geometries = route.legs().get(0).steps().get(0).intersections().get(0)
.geometries();

final List<String> expectedGeometries = Arrays.asList(
"k}fiyAcxhgOjCRrD?rDS~CSrDSbQ{@rIg@nFSfES~HSjMSrNRjMz@jHz@jMjCnK~CzJrD~MvG",
null,
null
);

assertEquals(expectedGeometries, geometries);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class RouteOptionsTest extends TestUtils {
*/
private static final String ROUTE_OPTIONS_JSON = "route_options_v5.json";
private static final String ROUTE_OPTIONS_URL =
"https://api.mapbox.com/directions/v5/mapbox/driving/-122.4003312,37.7736941;-122.4187529,37.7689715;-122.4255172,37.7775835?access_token=pk.token&geometries=polyline6&alternatives=false&overview=full&radiuses=%3Bunlimited%3B5.1&steps=true&avoid_maneuver_radius=200.0&bearings=0%2C90%3B90%2C0%3B&layers=-42%3B%3B0&continue_straight=false&annotations=congestion%2Cdistance%2Cduration&language=ru&roundabout_exits=false&voice_instructions=true&banner_instructions=true&voice_units=metric&exclude=toll%2Cferry%2Cpoint%2811.0+-22.0%29&include=hot%2Chov2&approaches=%3Bcurb%3B&waypoints=0%3B1%3B2&waypoint_names=%3BSerangoon+Garden+Market+%26+Food+Centre%3BFunky+%26nAmE*&waypoint_targets=%3B12.2%2C21.2%3B&enable_refresh=true&walking_speed=5.11&walkway_bias=-0.2&alley_bias=0.75&snapping_include_closures=%3Bfalse%3Btrue&snapping_include_static_closures=true%3B%3Bfalse&arrive_by=2021-01-01%27T%2701%3A01&depart_at=2021-02-02%27T%2702%3A02&max_height=1.5&max_width=1.4&max_weight=2.9&compute_toll_cost=true&waypoints_per_route=true&metadata=true&payment_methods=general&suppress_voice_instruction_local_names=true";
"https://api.mapbox.com/directions/v5/mapbox/driving/-122.4003312,37.7736941;-122.4187529,37.7689715;-122.4255172,37.7775835?access_token=pk.token&geometries=polyline6&alternatives=false&overview=full&radiuses=%3Bunlimited%3B5.1&steps=true&avoid_maneuver_radius=200.0&bearings=0%2C90%3B90%2C0%3B&layers=-42%3B%3B0&continue_straight=false&annotations=congestion%2Cdistance%2Cduration&language=ru&roundabout_exits=false&voice_instructions=true&banner_instructions=true&voice_units=metric&exclude=toll%2Cferry%2Cpoint%2811.0+-22.0%29&include=hot%2Chov2&approaches=%3Bcurb%3B&waypoints=0%3B1%3B2&waypoint_names=%3BSerangoon+Garden+Market+%26+Food+Centre%3BFunky+%26nAmE*&waypoint_targets=%3B12.2%2C21.2%3B&enable_refresh=true&walking_speed=5.11&walkway_bias=-0.2&alley_bias=0.75&snapping_include_closures=%3Bfalse%3Btrue&snapping_include_static_closures=true%3B%3Bfalse&arrive_by=2021-01-01%27T%2701%3A01&depart_at=2021-02-02%27T%2702%3A02&max_height=1.5&max_width=1.4&max_weight=2.9&compute_toll_cost=true&waypoints_per_route=true&metadata=true&payment_methods=general&suppress_voice_instruction_local_names=true&intersection_link_form_of_way=true&intersection_link_geometry=motorway%2Ctrunk%2Cprimary";
private static final String ACCESS_TOKEN = "pk.token";

private final String optionsJson = loadJsonFixture(ROUTE_OPTIONS_JSON);
Expand Down Expand Up @@ -364,6 +364,18 @@ public void waypointsPerRouteAreValid_fromJson() {
assertEquals(true, routeOptions.waypointsPerRoute());
}

@Test
public void intersectionLinkGeometryAreValid_fromJson() {
RouteOptions routeOptions = RouteOptions.fromJson(optionsJson);
assertEquals("motorway,trunk,primary", routeOptions.intersectionLinkGeometry());
}

@Test
public void intersectionLinkFormOfWayAreValid_fromJson() {
RouteOptions routeOptions = RouteOptions.fromJson(optionsJson);
assertEquals(true, routeOptions.intersectionLinkFormOfWay());
}

@Test
public void defaultTollCost() {
RouteOptions options = defaultRouteOptions();
Expand All @@ -385,6 +397,18 @@ public void defaultWaypointsPerRoute() {
assertNull(options.waypointsPerRoute());
}

@Test
public void defaultIntersectionLinkFormOfWay() {
RouteOptions options = defaultRouteOptions();
assertNull(options.intersectionLinkFormOfWay());
}

@Test
public void defaultIntersectionLinkGeometry() {
RouteOptions options = defaultRouteOptions();
assertNull(options.intersectionLinkGeometry());
}

@Test
public void routeOptions_toJson() {
RouteOptions options = routeOptions();
Expand Down Expand Up @@ -1128,6 +1152,8 @@ private RouteOptions routeOptions() {
.waypointsPerRoute(true)
.paymentMethods(DirectionsCriteria.PAYMENT_METHOD_GENERAL)
.suppressVoiceInstructionLocalNames(true)
.intersectionLinkFormOfWay(true)
.intersectionLinkGeometry("motorway,trunk,primary")
.build();
}

Expand Down Expand Up @@ -1237,6 +1263,8 @@ private RouteOptions routeOptionsList() {
.waypointsPerRoute(true)
.suppressVoiceInstructionLocalNames(true)
.paymentMethodsList(Arrays.asList(DirectionsCriteria.PAYMENT_METHOD_GENERAL))
.intersectionLinkFormOfWay(true)
.intersectionLinkGeometry(Arrays.asList("motorway", "trunk", "primary"))
.build();
}
}
Loading