Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/dev-2.x' into upstream-merge-2…
Browse files Browse the repository at this point in the history
…024-03-04
  • Loading branch information
leonardehrenfried committed Mar 4, 2024
2 parents 7ac7cf2 + 9c17e7a commit 401ab30
Show file tree
Hide file tree
Showing 9 changed files with 268 additions and 4 deletions.
13 changes: 12 additions & 1 deletion doc-templates/sandbox/MapboxVectorTilesApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ The feature must be configured in `router-config.json` as follows
"minZoom": 14,
"cacheMaxSeconds": 600
},
// flex zones
{
"name": "areaStops",
"type": "AreaStop",
"mapper": "OTPRR",
"maxZoom": 20,
"minZoom": 14,
"cacheMaxSeconds": 600
},
{
"name": "stations",
"type": "Station",
Expand Down Expand Up @@ -136,6 +145,7 @@ For each layer, the configuration includes:
- `name` which is used in the url to fetch tiles, and as the layer name in the vector tiles.
- `type` which tells the type of the layer. Currently supported:
- `Stop`
- `AreaStop`: Flex zones
- `Station`
- `VehicleRental`: all rental places: stations and free-floating vehicles
- `VehicleRentalVehicle`: free-floating rental vehicles
Expand Down Expand Up @@ -191,4 +201,5 @@ key, and a function to create the mapper, with a `Graph` object as a parameter,
* Added DigitransitRealtime for vehicle rental stations
* Changed old vehicle parking mapper to be Stadtnavi
* Added a new Digitransit vehicle parking mapper with no real-time information and less fields
- 2024-01-22: Make `basePath` configurable [#5627](https://github.com/opentripplanner/OpenTripPlanner/pull/5627)
- 2024-01-22: Make `basePath` configurable [#5627](https://github.com/opentripplanner/OpenTripPlanner/pull/5627)
- 2024-02-27: Add layer for flex zones [#5704](https://github.com/opentripplanner/OpenTripPlanner/pull/5704)
8 changes: 8 additions & 0 deletions docs/RouterConfiguration.md
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,14 @@ Used to group requests when monitoring OTP.
"minZoom" : 14,
"cacheMaxSeconds" : 600
},
{
"name" : "areaStops",
"type" : "AreaStop",
"mapper" : "OTPRR",
"maxZoom" : 20,
"minZoom" : 14,
"cacheMaxSeconds" : 600
},
{
"name" : "stations",
"type" : "Station",
Expand Down
13 changes: 12 additions & 1 deletion docs/sandbox/MapboxVectorTilesApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ The feature must be configured in `router-config.json` as follows
"minZoom": 14,
"cacheMaxSeconds": 600
},
// flex zones
{
"name": "areaStops",
"type": "AreaStop",
"mapper": "OTPRR",
"maxZoom": 20,
"minZoom": 14,
"cacheMaxSeconds": 600
},
{
"name": "stations",
"type": "Station",
Expand Down Expand Up @@ -136,6 +145,7 @@ For each layer, the configuration includes:
- `name` which is used in the url to fetch tiles, and as the layer name in the vector tiles.
- `type` which tells the type of the layer. Currently supported:
- `Stop`
- `AreaStop`: Flex zones
- `Station`
- `VehicleRental`: all rental places: stations and free-floating vehicles
- `VehicleRentalVehicle`: free-floating rental vehicles
Expand Down Expand Up @@ -286,4 +296,5 @@ key, and a function to create the mapper, with a `Graph` object as a parameter,
* Added DigitransitRealtime for vehicle rental stations
* Changed old vehicle parking mapper to be Stadtnavi
* Added a new Digitransit vehicle parking mapper with no real-time information and less fields
- 2024-01-22: Make `basePath` configurable [#5627](https://github.com/opentripplanner/OpenTripPlanner/pull/5627)
- 2024-01-22: Make `basePath` configurable [#5627](https://github.com/opentripplanner/OpenTripPlanner/pull/5627)
- 2024-02-27: Add layer for flex zones [#5704](https://github.com/opentripplanner/OpenTripPlanner/pull/5704)
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.opentripplanner.ext.vectortiles.layers.areastops;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.opentripplanner.inspector.vector.KeyValue.kv;

import java.util.List;
import java.util.Locale;
import org.junit.jupiter.api.Test;
import org.opentripplanner._support.geometry.Polygons;
import org.opentripplanner.transit.model._data.TransitModelForTest;
import org.opentripplanner.transit.model.network.Route;
import org.opentripplanner.transit.model.site.AreaStop;
import org.opentripplanner.transit.service.StopModel;

class AreaStopPropertyMapperTest {

private static final TransitModelForTest MODEL = new TransitModelForTest(StopModel.of());
private static final AreaStop STOP = MODEL.areaStopForTest("123", Polygons.BERLIN);
private static final Route ROUTE_WITH_COLOR = TransitModelForTest
.route("123")
.withColor("ffffff")
.build();
private static final Route ROUTE_WITHOUT_COLOR = TransitModelForTest.route("456").build();

@Test
void map() {
var mapper = new AreaStopPropertyMapper(
ignored -> List.of(ROUTE_WITH_COLOR, ROUTE_WITHOUT_COLOR),
Locale.ENGLISH
);

var kv = mapper.map(STOP);

assertEquals(
List.of(
kv("gtfsId", "F:123"),
kv("name", "123"),
kv("code", null),
kv("routeColors", "ffffff")
),
kv
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.opentripplanner.ext.vectortiles.layers.areastops;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.opentripplanner.standalone.config.framework.json.JsonSupport.newNodeAdapterForTest;

import java.util.List;
import java.util.Locale;
import org.junit.jupiter.api.Test;
import org.opentripplanner._support.geometry.Polygons;
import org.opentripplanner.ext.vectortiles.VectorTilesResource;
import org.opentripplanner.framework.i18n.I18NString;
import org.opentripplanner.inspector.vector.LayerParameters;
import org.opentripplanner.standalone.config.routerconfig.VectorTileConfig;
import org.opentripplanner.transit.model.framework.Deduplicator;
import org.opentripplanner.transit.model.framework.FeedScopedId;
import org.opentripplanner.transit.model.site.AreaStop;
import org.opentripplanner.transit.service.DefaultTransitService;
import org.opentripplanner.transit.service.StopModel;
import org.opentripplanner.transit.service.StopModelBuilder;
import org.opentripplanner.transit.service.TransitModel;

class AreaStopsLayerBuilderTest {

private static final FeedScopedId ID = new FeedScopedId("FEED", "ID");
private static final I18NString NAME = I18NString.of("Test stop");
private static final String CONFIG =
"""
{
"vectorTiles": {
"layers" : [
{
"name": "areaStops",
"type": "AreaStop",
"mapper": "OTPRR",
"maxZoom": 20,
"minZoom": 14,
"cacheMaxSeconds": 60,
"expansionFactor": 0
}
]
}
}
""";
private static final LayerParameters<VectorTilesResource.LayerType> LAYER_CONFIG = VectorTileConfig
.mapVectorTilesParameters(newNodeAdapterForTest(CONFIG), "vectorTiles")
.layers()
.getFirst();

private final StopModelBuilder stopModelBuilder = StopModel.of();

private final AreaStop AREA_STOP = stopModelBuilder
.areaStop(ID)
.withName(NAME)
.withGeometry(Polygons.BERLIN)
.build();

private final TransitModel transitModel = new TransitModel(
stopModelBuilder.withAreaStop(AREA_STOP).build(),
new Deduplicator()
);

@Test
void getAreaStops() {
transitModel.index();

var subject = new AreaStopsLayerBuilder(
new DefaultTransitService(transitModel),
LAYER_CONFIG,
Locale.ENGLISH
);
var geometries = subject.getGeometries(AREA_STOP.getGeometry().getEnvelopeInternal());
assertEquals(List.of(Polygons.BERLIN), geometries);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.function.Predicate;
import org.glassfish.grizzly.http.server.Request;
import org.opentripplanner.apis.support.TileJson;
import org.opentripplanner.ext.vectortiles.layers.areastops.AreaStopsLayerBuilder;
import org.opentripplanner.ext.vectortiles.layers.stations.StationsLayerBuilder;
import org.opentripplanner.ext.vectortiles.layers.stops.StopsLayerBuilder;
import org.opentripplanner.ext.vectortiles.layers.vehicleparkings.VehicleParkingGroupsLayerBuilder;
Expand Down Expand Up @@ -68,7 +69,7 @@ public Response tileGet(
locale,
Arrays.asList(requestedLayers.split(",")),
serverContext.vectorTileConfig().layers(),
VectorTilesResource::crateLayerBuilder,
VectorTilesResource::createLayerBuilder,
serverContext
);
}
Expand Down Expand Up @@ -115,14 +116,15 @@ private List<FeedInfo> getFeedInfos() {
.toList();
}

private static LayerBuilder<?> crateLayerBuilder(
private static LayerBuilder<?> createLayerBuilder(
LayerParameters<LayerType> layerParameters,
Locale locale,
OtpServerRequestContext context
) {
return switch (layerParameters.type()) {
case Stop -> new StopsLayerBuilder(context.transitService(), layerParameters, locale);
case Station -> new StationsLayerBuilder(context.transitService(), layerParameters, locale);
case AreaStop -> new AreaStopsLayerBuilder(context.transitService(), layerParameters, locale);
case VehicleRental -> new VehicleRentalPlacesLayerBuilder(
context.vehicleRentalService(),
layerParameters,
Expand Down Expand Up @@ -153,6 +155,7 @@ private static LayerBuilder<?> crateLayerBuilder(
public enum LayerType {
Stop,
Station,
AreaStop,
VehicleRental,
VehicleRentalVehicle,
VehicleRentalStation,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.opentripplanner.ext.vectortiles.layers.areastops;

import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.opentripplanner.apis.support.mapping.PropertyMapper;
import org.opentripplanner.framework.i18n.I18NStringMapper;
import org.opentripplanner.inspector.vector.KeyValue;
import org.opentripplanner.transit.model.network.Route;
import org.opentripplanner.transit.model.site.AreaStop;
import org.opentripplanner.transit.model.site.StopLocation;
import org.opentripplanner.transit.service.TransitService;

public class AreaStopPropertyMapper extends PropertyMapper<AreaStop> {

private final Function<StopLocation, Collection<Route>> getRoutesForStop;
private final I18NStringMapper i18NStringMapper;

protected AreaStopPropertyMapper(
Function<StopLocation, Collection<Route>> getRoutesForStop,
Locale locale
) {
this.getRoutesForStop = getRoutesForStop;
this.i18NStringMapper = new I18NStringMapper(locale);
}

protected static AreaStopPropertyMapper create(TransitService transitService, Locale locale) {
return new AreaStopPropertyMapper(transitService::getRoutesForStop, locale);
}

@Override
protected Collection<KeyValue> map(AreaStop stop) {
var routeColors = getRoutesForStop
.apply(stop)
.stream()
.map(Route::getColor)
.filter(Objects::nonNull)
.distinct()
// the MVT spec explicitly doesn't cover how to encode arrays
// https://docs.mapbox.com/data/tilesets/guides/vector-tiles-standards/#what-the-spec-doesnt-cover
.collect(Collectors.joining(","));
return List.of(
new KeyValue("gtfsId", stop.getId().toString()),
new KeyValue("name", i18NStringMapper.mapNonnullToApi(stop.getName())),
new KeyValue("code", stop.getCode()),
new KeyValue("routeColors", routeColors)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.opentripplanner.ext.vectortiles.layers.areastops;

import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.BiFunction;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.opentripplanner.apis.support.mapping.PropertyMapper;
import org.opentripplanner.ext.vectortiles.VectorTilesResource;
import org.opentripplanner.inspector.vector.LayerBuilder;
import org.opentripplanner.inspector.vector.LayerParameters;
import org.opentripplanner.transit.model.site.AreaStop;
import org.opentripplanner.transit.service.TransitService;

public class AreaStopsLayerBuilder extends LayerBuilder<AreaStop> {

static Map<MapperType, BiFunction<TransitService, Locale, PropertyMapper<AreaStop>>> mappers = Map.of(
MapperType.OTPRR,
AreaStopPropertyMapper::create
);
private final TransitService transitService;

public AreaStopsLayerBuilder(
TransitService transitService,
LayerParameters<VectorTilesResource.LayerType> layerParameters,
Locale locale
) {
super(
mappers.get(MapperType.valueOf(layerParameters.mapper())).apply(transitService, locale),
layerParameters.name(),
layerParameters.expansionFactor()
);
this.transitService = transitService;
}

protected List<Geometry> getGeometries(Envelope query) {
return transitService
.findAreaStops(query)
.stream()
.filter(g -> g.getGeometry() != null)
.map(stop -> {
Geometry point = stop.getGeometry().copy();
point.setUserData(stop);
return point;
})
.toList();
}

enum MapperType {
OTPRR,
}
}
8 changes: 8 additions & 0 deletions src/test/resources/standalone/config/router-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@
"minZoom": 14,
"cacheMaxSeconds": 600
},
{
"name": "areaStops",
"type": "AreaStop",
"mapper": "OTPRR",
"maxZoom": 20,
"minZoom": 14,
"cacheMaxSeconds": 600
},
{
"name": "stations",
"type": "Station",
Expand Down

0 comments on commit 401ab30

Please sign in to comment.