From 2218c1af12110e1d84730f25a76870cf94e856ec Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 19 Dec 2023 18:52:42 +0100 Subject: [PATCH 01/25] Add new debug vector tiles --- .../api/configuration/APIEndpoints.java | 2 +- .../GraphInspectorVectorTileResource.java | 58 +++++++++++++++--- .../apis/vectortiles/MapboxStyleJson.java | 53 ++++++++++++++++ .../vector/RegularStopsLayerBuilder.java | 60 +++++++++++++++++++ 4 files changed, 164 insertions(+), 9 deletions(-) rename src/main/java/org/opentripplanner/{api/resource => apis/vectortiles}/GraphInspectorVectorTileResource.java (72%) create mode 100644 src/main/java/org/opentripplanner/apis/vectortiles/MapboxStyleJson.java create mode 100644 src/main/java/org/opentripplanner/inspector/vector/RegularStopsLayerBuilder.java diff --git a/src/main/java/org/opentripplanner/api/configuration/APIEndpoints.java b/src/main/java/org/opentripplanner/api/configuration/APIEndpoints.java index b0d38aa00cd..64bbb2896a2 100644 --- a/src/main/java/org/opentripplanner/api/configuration/APIEndpoints.java +++ b/src/main/java/org/opentripplanner/api/configuration/APIEndpoints.java @@ -19,13 +19,13 @@ import java.util.List; import org.opentripplanner.api.resource.BikeRental; import org.opentripplanner.api.resource.GraphInspectorTileResource; -import org.opentripplanner.api.resource.GraphInspectorVectorTileResource; import org.opentripplanner.api.resource.PlannerResource; import org.opentripplanner.api.resource.Routers; import org.opentripplanner.api.resource.ServerInfo; import org.opentripplanner.api.resource.UpdaterStatusResource; import org.opentripplanner.apis.gtfs.GtfsGraphQLAPI; import org.opentripplanner.apis.transmodel.TransmodelAPI; +import org.opentripplanner.apis.vectortiles.GraphInspectorVectorTileResource; import org.opentripplanner.ext.actuator.ActuatorAPI; import org.opentripplanner.ext.geocoder.GeocoderResource; import org.opentripplanner.ext.parkAndRideApi.ParkAndRideResource; diff --git a/src/main/java/org/opentripplanner/api/resource/GraphInspectorVectorTileResource.java b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java similarity index 72% rename from src/main/java/org/opentripplanner/api/resource/GraphInspectorVectorTileResource.java rename to src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java index 2c21e0396ce..04d2630a301 100644 --- a/src/main/java/org/opentripplanner/api/resource/GraphInspectorVectorTileResource.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java @@ -1,4 +1,4 @@ -package org.opentripplanner.api.resource; +package org.opentripplanner.apis.vectortiles; import static org.opentripplanner.framework.io.HttpUtils.APPLICATION_X_PROTOBUF; @@ -14,13 +14,20 @@ import java.util.Arrays; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Objects; import java.util.function.Predicate; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; import org.glassfish.grizzly.http.server.Request; import org.opentripplanner.api.model.TileJson; +import org.opentripplanner.apis.vectortiles.MapboxStyleJson.LayerStyleBuilder; +import org.opentripplanner.apis.vectortiles.MapboxStyleJson.VectorTileSource; +import org.opentripplanner.framework.io.HttpUtils; import org.opentripplanner.inspector.vector.AreaStopsLayerBuilder; import org.opentripplanner.inspector.vector.LayerBuilder; import org.opentripplanner.inspector.vector.LayerParameters; +import org.opentripplanner.inspector.vector.RegularStopsLayerBuilder; import org.opentripplanner.inspector.vector.VectorTileResponseFactory; import org.opentripplanner.inspector.vector.geofencing.GeofencingZonesLayerBuilder; import org.opentripplanner.model.FeedInfo; @@ -34,6 +41,7 @@ public class GraphInspectorVectorTileResource { private static final List> DEBUG_LAYERS = List.of( + new LayerParams("regularStops", LayerType.RegularStop), new LayerParams("areaStops", LayerType.AreaStop), new LayerParams("geofencingZones", LayerType.GeofencingZones) ); @@ -84,13 +92,7 @@ public TileJson getTileJson( @PathParam("layers") String requestedLayers ) { var envelope = serverContext.worldEnvelopeService().envelope().orElseThrow(); - List feedInfos = serverContext - .transitService() - .getFeedIds() - .stream() - .map(serverContext.transitService()::getFeedInfo) - .filter(Predicate.not(Objects::isNull)) - .toList(); + List feedInfos = feedInfos(); return new TileJson( uri, @@ -103,18 +105,58 @@ public TileJson getTileJson( ); } + @GET + @Path("/style.json") + @Produces(MediaType.APPLICATION_JSON) + public MapboxStyleJson getTileJson(@Context UriInfo uri, @Context HttpHeaders headers) { + var base = HttpUtils.getBaseAddress(uri, headers); + final String allLayers = DEBUG_LAYERS + .stream() + .map(LayerParameters::name) + .collect(Collectors.joining(",")); + var url = + base + + "/otp/routers/" + + ignoreRouterId + + "/inspector/vectortile/" + + allLayers + + "/tilejson.json"; + return new MapboxStyleJson( + "OTP Debug Tiles", + Map.of("debug", new VectorTileSource("vector", url)), + List.of(LayerStyleBuilder.ofId("regular-stop").source("regularStops").circleColor("#f73109").build()) + ); + } + + @Nonnull + private List feedInfos() { + return serverContext + .transitService() + .getFeedIds() + .stream() + .map(serverContext.transitService()::getFeedInfo) + .filter(Predicate.not(Objects::isNull)) + .toList(); + } + private static LayerBuilder createLayerBuilder( LayerParameters layerParameters, Locale locale, OtpServerRequestContext context ) { return switch (layerParameters.type()) { + case RegularStop -> new RegularStopsLayerBuilder( + context.transitService(), + layerParameters, + locale + ); case AreaStop -> new AreaStopsLayerBuilder(context.transitService(), layerParameters, locale); case GeofencingZones -> new GeofencingZonesLayerBuilder(context.graph(), layerParameters); }; } private enum LayerType { + RegularStop, AreaStop, GeofencingZones, } diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/MapboxStyleJson.java b/src/main/java/org/opentripplanner/apis/vectortiles/MapboxStyleJson.java new file mode 100644 index 00000000000..72f92a9c02e --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/MapboxStyleJson.java @@ -0,0 +1,53 @@ +package org.opentripplanner.apis.vectortiles; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.opentripplanner.framework.json.ObjectMappers; + +public record MapboxStyleJson( + String name, + Map sources, + List layers +) { + public record VectorTileSource(String type, String url) {} + + public static class LayerStyleBuilder { + + private static final ObjectMapper OBJECT_MAPPER = ObjectMappers.ignoringExtraFields(); + private final Map props = new HashMap<>(); + private final Map paint = new HashMap<>(); + + public static LayerStyleBuilder ofId(String id) { + return new LayerStyleBuilder(id); + } + + private LayerStyleBuilder(String id) { + props.put("id", id); + } + + /** + * Which vector tile source this should apply to. + */ + public LayerStyleBuilder source(String source) { + props.put("source", source); + return this; + } + + public LayerStyleBuilder circleColor(String color) { + paint.put("circle-color", color); + return this; + } + + public JsonNode build() { + var copy = new HashMap<>(props); + if(!paint.isEmpty()) { + copy.put("paint", paint); + } + return OBJECT_MAPPER.valueToTree(copy); + } + + } +} diff --git a/src/main/java/org/opentripplanner/inspector/vector/RegularStopsLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/RegularStopsLayerBuilder.java new file mode 100644 index 00000000000..c4bf0d88a23 --- /dev/null +++ b/src/main/java/org/opentripplanner/inspector/vector/RegularStopsLayerBuilder.java @@ -0,0 +1,60 @@ +package org.opentripplanner.inspector.vector; + +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.Function; +import org.locationtech.jts.geom.Envelope; +import org.locationtech.jts.geom.Geometry; +import org.opentripplanner.apis.common.mapping.PropertyMapper; +import org.opentripplanner.transit.model.site.AreaStop; +import org.opentripplanner.transit.model.site.RegularStop; +import org.opentripplanner.transit.service.TransitService; + +/** + * A vector tile layer containing all {@link RegularStop}s inside the vector tile bounds. + */ +public class RegularStopsLayerBuilder extends LayerBuilder { + + private static final Map mappers = Map.of( + MapperType.DebugClient, + DebugClientAreaStopPropertyMapper::create + ); + private final Function> findAreaStops; + + public RegularStopsLayerBuilder( + TransitService transitService, + LayerParameters layerParameters, + Locale locale + ) { + super( + mappers.get(MapperType.valueOf(layerParameters.mapper())).build(transitService, locale), + layerParameters.name(), + layerParameters.expansionFactor() + ); + this.findAreaStops = transitService::findRegularStop; + } + + @Override + protected List getGeometries(Envelope query) { + return findAreaStops + .apply(query) + .stream() + .map(stop -> { + Geometry geometry = stop.getGeometry().copy(); + geometry.setUserData(stop); + return geometry; + }) + .toList(); + } + + enum MapperType { + DebugClient, + } + + @FunctionalInterface + private interface MapperFactory { + PropertyMapper build(TransitService transitService, Locale locale); + } +} From 176187c5dba4a735fbd78171d98c5dda0c29c1cb Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 19 Dec 2023 18:48:30 +0100 Subject: [PATCH 02/25] Add stop layer to tile.json --- .../GraphInspectorVectorTileResource.java | 40 ++++++- .../apis/vectortiles/MapboxStyleJson.java | 53 --------- .../vectortiles/model/LayerStyleBuilder.java | 105 ++++++++++++++++++ .../vectortiles/model/MapboxStyleJson.java | 46 ++++++++ .../apis/vectortiles/model/TileSource.java | 25 +++++ .../vector/AreaStopsLayerBuilder.java | 10 +- .../DebugClientAreaStopPropertyMapper.java | 14 +-- .../vector/RegularStopsLayerBuilder.java | 20 +--- .../vector/AreaStopLayerBuilderTest.java | 5 +- 9 files changed, 225 insertions(+), 93 deletions(-) delete mode 100644 src/main/java/org/opentripplanner/apis/vectortiles/MapboxStyleJson.java create mode 100644 src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java create mode 100644 src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java create mode 100644 src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java index 04d2630a301..8df1fd9e388 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java @@ -14,15 +14,17 @@ import java.util.Arrays; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Objects; import java.util.function.Predicate; import java.util.stream.Collectors; import javax.annotation.Nonnull; import org.glassfish.grizzly.http.server.Request; import org.opentripplanner.api.model.TileJson; -import org.opentripplanner.apis.vectortiles.MapboxStyleJson.LayerStyleBuilder; -import org.opentripplanner.apis.vectortiles.MapboxStyleJson.VectorTileSource; +import org.opentripplanner.apis.vectortiles.model.LayerStyleBuilder; +import org.opentripplanner.apis.vectortiles.model.MapboxStyleJson; +import org.opentripplanner.apis.vectortiles.model.TileSource; +import org.opentripplanner.apis.vectortiles.model.TileSource.RasterSource; +import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; import org.opentripplanner.framework.io.HttpUtils; import org.opentripplanner.inspector.vector.AreaStopsLayerBuilder; import org.opentripplanner.inspector.vector.LayerBuilder; @@ -121,10 +123,38 @@ public MapboxStyleJson getTileJson(@Context UriInfo uri, @Context HttpHeaders he "/inspector/vectortile/" + allLayers + "/tilejson.json"; + var vectorSource = new VectorSource("debug", url); + var backgroundSource = new RasterSource( + "background", + List.of("https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"), + 256 + ); + List sources = List.of( + backgroundSource, + vectorSource + ); return new MapboxStyleJson( "OTP Debug Tiles", - Map.of("debug", new VectorTileSource("vector", url)), - List.of(LayerStyleBuilder.ofId("regular-stop").source("regularStops").circleColor("#f73109").build()) + sources, + List.of( + LayerStyleBuilder + .ofId("background") + .typeRaster() + .source(backgroundSource) + .minZoom(0) + .maxZoom(22) + .build(), + LayerStyleBuilder + .ofId("regular-stop") + .source(vectorSource) + .sourceLayer("regularStops") + .typeCircle() + .circleStroke("#140d0e", 1) + .circleColor("#fcf9fa") + .minZoom(13) + .maxZoom(22) + .build() + ) ); } diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/MapboxStyleJson.java b/src/main/java/org/opentripplanner/apis/vectortiles/MapboxStyleJson.java deleted file mode 100644 index 72f92a9c02e..00000000000 --- a/src/main/java/org/opentripplanner/apis/vectortiles/MapboxStyleJson.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.opentripplanner.apis.vectortiles; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.opentripplanner.framework.json.ObjectMappers; - -public record MapboxStyleJson( - String name, - Map sources, - List layers -) { - public record VectorTileSource(String type, String url) {} - - public static class LayerStyleBuilder { - - private static final ObjectMapper OBJECT_MAPPER = ObjectMappers.ignoringExtraFields(); - private final Map props = new HashMap<>(); - private final Map paint = new HashMap<>(); - - public static LayerStyleBuilder ofId(String id) { - return new LayerStyleBuilder(id); - } - - private LayerStyleBuilder(String id) { - props.put("id", id); - } - - /** - * Which vector tile source this should apply to. - */ - public LayerStyleBuilder source(String source) { - props.put("source", source); - return this; - } - - public LayerStyleBuilder circleColor(String color) { - paint.put("circle-color", color); - return this; - } - - public JsonNode build() { - var copy = new HashMap<>(props); - if(!paint.isEmpty()) { - copy.put("paint", paint); - } - return OBJECT_MAPPER.valueToTree(copy); - } - - } -} diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java new file mode 100644 index 00000000000..65a009ec53e --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java @@ -0,0 +1,105 @@ +package org.opentripplanner.apis.vectortiles.model; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Stream; +import org.opentripplanner.framework.json.ObjectMappers; + +/** + * Builds a Maplibre/Mapbox vector tile + * layer style. + */ +public class LayerStyleBuilder { + + private static final ObjectMapper OBJECT_MAPPER = ObjectMappers.ignoringExtraFields(); + private static final String TYPE = "type"; + private static final String SOURCE_LAYER = "source-layer"; + private final Map props = new HashMap<>(); + private final Map paint = new HashMap<>(); + + public static LayerStyleBuilder ofId(String id) { + return new LayerStyleBuilder(id); + } + + public enum LayerType { + Circle, + Raster, + } + + private LayerStyleBuilder(String id) { + props.put("id", id); + } + + public LayerStyleBuilder minZoom(int i) { + props.put("minzoom", i); + return this; + } + + public LayerStyleBuilder maxZoom(int i) { + props.put("maxzoom", i); + return this; + } + + /** + * Which vector tile source this should apply to. + */ + public LayerStyleBuilder source(TileSource source) { + props.put("source", source.id()); + return this; + } + + public LayerStyleBuilder sourceLayer(String source) { + props.put(SOURCE_LAYER, source); + return this; + } + + public LayerStyleBuilder typeRaster() { + return type(LayerType.Raster); + } + + public LayerStyleBuilder typeCircle() { + return type(LayerType.Circle); + } + + private LayerStyleBuilder type(LayerType type) { + props.put(TYPE, type.name().toLowerCase()); + return this; + } + + public LayerStyleBuilder circleColor(String color) { + paint.put("circle-color", validateColor(color)); + return this; + } + + public LayerStyleBuilder circleStroke(String color, int width) { + paint.put("circle-stroke-color", validateColor(color)); + paint.put("circle-stroke-width", width); + return this; + } + + public JsonNode build() { + validate(); + + var copy = new HashMap<>(props); + if (!paint.isEmpty()) { + copy.put("paint", paint); + } + return OBJECT_MAPPER.valueToTree(copy); + } + + private String validateColor(String color) { + if (!color.startsWith("#")) { + throw new IllegalArgumentException("Colors must start with '#'"); + } + return color; + } + + private void validate() { + Stream + .of(TYPE) + .forEach(p -> Objects.requireNonNull(props.get(p), "%s must be set".formatted(p))); + } +} diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java new file mode 100644 index 00000000000..bf84b697b92 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java @@ -0,0 +1,46 @@ +package org.opentripplanner.apis.vectortiles.model; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public final class MapboxStyleJson { + + private final String name; + private final List sources; + private final List layers; + + public MapboxStyleJson( + String name, + List sources, + List layers + ) { + this.name = name; + this.sources = sources; + this.layers = layers; + } + + @JsonSerialize + public int version() { + return 8; + } + + @JsonSerialize + public String name() { + return name; + } + + @JsonSerialize + public Map sources() { + var output = new HashMap(); + sources.forEach(s -> output.put(s.id(), s)); + return output; + } + + @JsonSerialize + public List layers() { + return layers; + } +} diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java new file mode 100644 index 00000000000..2e404d9a1eb --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java @@ -0,0 +1,25 @@ +package org.opentripplanner.apis.vectortiles.model; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import java.util.List; + +public sealed interface TileSource { + @JsonSerialize + String type(); + + String id(); + + record VectorSource(String id, String url) implements TileSource { + @Override + public String type() { + return "vector"; + } + } + + record RasterSource(String id, List tiles, int tileSize) implements TileSource { + @Override + public String type() { + return "raster"; + } + } +} diff --git a/src/main/java/org/opentripplanner/inspector/vector/AreaStopsLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/AreaStopsLayerBuilder.java index 1604cf7d8d1..6ce7b0962ba 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/AreaStopsLayerBuilder.java +++ b/src/main/java/org/opentripplanner/inspector/vector/AreaStopsLayerBuilder.java @@ -3,23 +3,19 @@ import java.util.Collection; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.function.Function; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; import org.opentripplanner.api.mapping.PropertyMapper; import org.opentripplanner.transit.model.site.AreaStop; +import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.service.TransitService; /** * A vector tile layer containing all {@link AreaStop}s inside the vector tile bounds. */ -public class AreaStopsLayerBuilder extends LayerBuilder { +public class AreaStopsLayerBuilder extends LayerBuilder { - private static final Map mappers = Map.of( - MapperType.DebugClient, - DebugClientAreaStopPropertyMapper::create - ); private final Function> findAreaStops; public AreaStopsLayerBuilder( @@ -28,7 +24,7 @@ public AreaStopsLayerBuilder( Locale locale ) { super( - mappers.get(MapperType.valueOf(layerParameters.mapper())).build(transitService, locale), + new DebugClientAreaStopPropertyMapper(locale), layerParameters.name(), layerParameters.expansionFactor() ); diff --git a/src/main/java/org/opentripplanner/inspector/vector/DebugClientAreaStopPropertyMapper.java b/src/main/java/org/opentripplanner/inspector/vector/DebugClientAreaStopPropertyMapper.java index 88f7a17385b..1d507140378 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/DebugClientAreaStopPropertyMapper.java +++ b/src/main/java/org/opentripplanner/inspector/vector/DebugClientAreaStopPropertyMapper.java @@ -5,29 +5,29 @@ import java.util.Locale; import org.opentripplanner.api.mapping.I18NStringMapper; import org.opentripplanner.api.mapping.PropertyMapper; -import org.opentripplanner.transit.model.site.AreaStop; +import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.service.TransitService; /** * A {@link PropertyMapper} for the {@link AreaStopsLayerBuilder} for the OTP debug client. */ -public class DebugClientAreaStopPropertyMapper extends PropertyMapper { +public class DebugClientAreaStopPropertyMapper extends PropertyMapper { private final I18NStringMapper i18NStringMapper; - public DebugClientAreaStopPropertyMapper(TransitService transitService, Locale locale) { + public DebugClientAreaStopPropertyMapper(Locale locale) { this.i18NStringMapper = new I18NStringMapper(locale); } - public static PropertyMapper create(TransitService transitService, Locale locale) { - return new DebugClientAreaStopPropertyMapper(transitService, locale); + public static PropertyMapper create(TransitService ignored, Locale locale) { + return new DebugClientAreaStopPropertyMapper(locale); } @Override - protected Collection map(AreaStop input) { + protected Collection map(StopLocation input) { return List.of( new KeyValue("id", input.getId().toString()), - new KeyValue("name", i18NStringMapper.mapNonnullToApi(input.getName())) + new KeyValue("name", i18NStringMapper.mapToApi(input.getName())) ); } } diff --git a/src/main/java/org/opentripplanner/inspector/vector/RegularStopsLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/RegularStopsLayerBuilder.java index c4bf0d88a23..26e3f8726ae 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/RegularStopsLayerBuilder.java +++ b/src/main/java/org/opentripplanner/inspector/vector/RegularStopsLayerBuilder.java @@ -3,24 +3,18 @@ import java.util.Collection; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.function.Function; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; -import org.opentripplanner.apis.common.mapping.PropertyMapper; -import org.opentripplanner.transit.model.site.AreaStop; import org.opentripplanner.transit.model.site.RegularStop; +import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.service.TransitService; /** * A vector tile layer containing all {@link RegularStop}s inside the vector tile bounds. */ -public class RegularStopsLayerBuilder extends LayerBuilder { +public class RegularStopsLayerBuilder extends LayerBuilder { - private static final Map mappers = Map.of( - MapperType.DebugClient, - DebugClientAreaStopPropertyMapper::create - ); private final Function> findAreaStops; public RegularStopsLayerBuilder( @@ -29,7 +23,7 @@ public RegularStopsLayerBuilder( Locale locale ) { super( - mappers.get(MapperType.valueOf(layerParameters.mapper())).build(transitService, locale), + new DebugClientAreaStopPropertyMapper(locale), layerParameters.name(), layerParameters.expansionFactor() ); @@ -49,12 +43,4 @@ protected List getGeometries(Envelope query) { .toList(); } - enum MapperType { - DebugClient, - } - - @FunctionalInterface - private interface MapperFactory { - PropertyMapper build(TransitService transitService, Locale locale); - } } diff --git a/src/test/java/org/opentripplanner/inspector/vector/AreaStopLayerBuilderTest.java b/src/test/java/org/opentripplanner/inspector/vector/AreaStopLayerBuilderTest.java index 09b64adcf75..6f2ca872f21 100644 --- a/src/test/java/org/opentripplanner/inspector/vector/AreaStopLayerBuilderTest.java +++ b/src/test/java/org/opentripplanner/inspector/vector/AreaStopLayerBuilderTest.java @@ -38,10 +38,7 @@ class AreaStopLayerBuilderTest { @Test void map() { - var subject = new DebugClientAreaStopPropertyMapper( - new DefaultTransitService(new TransitModel()), - Locale.ENGLISH - ); + var subject = new DebugClientAreaStopPropertyMapper(Locale.ENGLISH); var properties = subject.map(areaStop); From 7aaf79ff43d1421786ac5c0e4c8297d783b7b06b Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 19 Dec 2023 23:41:36 +0100 Subject: [PATCH 03/25] Move classes into their own packages --- .../GraphInspectorVectorTileResource.java | 9 ++--- .../vectortiles/model/LayerStyleBuilder.java | 5 +++ .../vectortiles/model/MapboxStyleJson.java | 6 +-- .../opentripplanner/astar/model/BinHeap.java | 12 ------ .../vector/edge/EdgeLayerBuilder.java | 40 +++++++++++++++++++ .../vector/edge/EdgePropertyMapper.java | 18 +++++++++ .../GeofencingZonesLayerBuilder.java | 17 +------- .../{ => stop}/AreaStopsLayerBuilder.java | 18 ++------- .../{ => stop}/RegularStopsLayerBuilder.java | 7 ++-- .../StopLocationPropertyMapper.java} | 9 +++-- .../{ => stop}/AreaStopLayerBuilderTest.java | 7 ++-- 11 files changed, 84 insertions(+), 64 deletions(-) create mode 100644 src/main/java/org/opentripplanner/inspector/vector/edge/EdgeLayerBuilder.java create mode 100644 src/main/java/org/opentripplanner/inspector/vector/edge/EdgePropertyMapper.java rename src/main/java/org/opentripplanner/inspector/vector/{ => stop}/AreaStopsLayerBuilder.java (77%) rename src/main/java/org/opentripplanner/inspector/vector/{ => stop}/RegularStopsLayerBuilder.java (84%) rename src/main/java/org/opentripplanner/inspector/vector/{DebugClientAreaStopPropertyMapper.java => stop/StopLocationPropertyMapper.java} (74%) rename src/test/java/org/opentripplanner/inspector/vector/{ => stop}/AreaStopLayerBuilderTest.java (86%) diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java index 8df1fd9e388..9d083bd5e03 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java @@ -26,12 +26,12 @@ import org.opentripplanner.apis.vectortiles.model.TileSource.RasterSource; import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; import org.opentripplanner.framework.io.HttpUtils; -import org.opentripplanner.inspector.vector.AreaStopsLayerBuilder; import org.opentripplanner.inspector.vector.LayerBuilder; import org.opentripplanner.inspector.vector.LayerParameters; -import org.opentripplanner.inspector.vector.RegularStopsLayerBuilder; import org.opentripplanner.inspector.vector.VectorTileResponseFactory; import org.opentripplanner.inspector.vector.geofencing.GeofencingZonesLayerBuilder; +import org.opentripplanner.inspector.vector.stop.AreaStopsLayerBuilder; +import org.opentripplanner.inspector.vector.stop.RegularStopsLayerBuilder; import org.opentripplanner.model.FeedInfo; import org.opentripplanner.standalone.api.OtpServerRequestContext; @@ -129,10 +129,7 @@ public MapboxStyleJson getTileJson(@Context UriInfo uri, @Context HttpHeaders he List.of("https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"), 256 ); - List sources = List.of( - backgroundSource, - vectorSource - ); + List sources = List.of(backgroundSource, vectorSource); return new MapboxStyleJson( "OTP Debug Tiles", sources, diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java index 65a009ec53e..759ce7eeb30 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java @@ -51,6 +51,11 @@ public LayerStyleBuilder source(TileSource source) { return this; } + /** + * For vector tile sources, specify which source layer in the tile the styles should apply to. + * There is an unfortunate collision in the name "layer" as it can both refer to a styling layer + * and the layer inside the vector tile. + */ public LayerStyleBuilder sourceLayer(String source) { props.put(SOURCE_LAYER, source); return this; diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java index bf84b697b92..6461d697bfc 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java @@ -12,11 +12,7 @@ public final class MapboxStyleJson { private final List sources; private final List layers; - public MapboxStyleJson( - String name, - List sources, - List layers - ) { + public MapboxStyleJson(String name, List sources, List layers) { this.name = name; this.sources = sources; this.layers = layers; diff --git a/src/main/java/org/opentripplanner/astar/model/BinHeap.java b/src/main/java/org/opentripplanner/astar/model/BinHeap.java index 9bc2b0762a8..1e9b540a77a 100644 --- a/src/main/java/org/opentripplanner/astar/model/BinHeap.java +++ b/src/main/java/org/opentripplanner/astar/model/BinHeap.java @@ -79,14 +79,6 @@ public void rekey(T e, double p) { prio[i] = p; } - public void dump() { - for (int i = 0; i <= capacity; i++) { - String topMarker = (i > size) ? "(UNUSED)" : ""; - System.out.printf("%d\t%f\t%s\t%s\n", i, prio[i], elem[i], topMarker); - } - System.out.printf("-----------------------\n"); - } - public void reset() { // empties the queue in one operation size = 0; @@ -135,8 +127,4 @@ public void resize(int capacity) { prio = Arrays.copyOf(prio, capacity + 1); elem = Arrays.copyOf(elem, capacity + 1); } - - public int getCapacity() { - return capacity; - } } diff --git a/src/main/java/org/opentripplanner/inspector/vector/edge/EdgeLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/edge/EdgeLayerBuilder.java new file mode 100644 index 00000000000..3c1bc3436d8 --- /dev/null +++ b/src/main/java/org/opentripplanner/inspector/vector/edge/EdgeLayerBuilder.java @@ -0,0 +1,40 @@ +package org.opentripplanner.inspector.vector.edge; + +import java.util.List; +import org.locationtech.jts.geom.Envelope; +import org.locationtech.jts.geom.Geometry; +import org.opentripplanner.framework.geometry.GeometryUtils; +import org.opentripplanner.inspector.vector.LayerBuilder; +import org.opentripplanner.inspector.vector.LayerParameters; +import org.opentripplanner.routing.graph.Graph; +import org.opentripplanner.routing.graph.index.StreetIndex; +import org.opentripplanner.street.model.edge.Edge; +import org.opentripplanner.street.model.vertex.Vertex; +import org.opentripplanner.transit.model.site.AreaStop; + +/** + * A vector tile layer containing all {@link AreaStop}s inside the vector tile bounds. + */ +public class EdgeLayerBuilder extends LayerBuilder { + + private final StreetIndex streetIndex; + + public EdgeLayerBuilder(Graph graph, LayerParameters layerParameters) { + super(new EdgePropertyMapper(), layerParameters.name(), layerParameters.expansionFactor()); + this.streetIndex = graph.getStreetIndex(); + } + + @Override + protected List getGeometries(Envelope query) { + return streetIndex + .getEdgesForEnvelope(query) + .stream() + .filter(edge -> edge.getGeometry() != null) + .map(edge -> { + Geometry geometry = edge.getGeometry().copy(); + geometry.setUserData(edge); + return geometry; + }) + .toList(); + } +} diff --git a/src/main/java/org/opentripplanner/inspector/vector/edge/EdgePropertyMapper.java b/src/main/java/org/opentripplanner/inspector/vector/edge/EdgePropertyMapper.java new file mode 100644 index 00000000000..936c965c9f5 --- /dev/null +++ b/src/main/java/org/opentripplanner/inspector/vector/edge/EdgePropertyMapper.java @@ -0,0 +1,18 @@ +package org.opentripplanner.inspector.vector.edge; + +import java.util.Collection; +import java.util.List; +import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.inspector.vector.KeyValue; +import org.opentripplanner.street.model.edge.Edge; + +/** + * A {@link PropertyMapper} for the {@link EdgeLayerBuilder} for the OTP debug client. + */ +public class EdgePropertyMapper extends PropertyMapper { + + @Override + protected Collection map(Edge edge) { + return List.of(new KeyValue("java-class", edge.getClass().getSimpleName())); + } +} diff --git a/src/main/java/org/opentripplanner/inspector/vector/geofencing/GeofencingZonesLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/geofencing/GeofencingZonesLayerBuilder.java index 8a77b8502ea..24be8d202a8 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/geofencing/GeofencingZonesLayerBuilder.java +++ b/src/main/java/org/opentripplanner/inspector/vector/geofencing/GeofencingZonesLayerBuilder.java @@ -1,10 +1,8 @@ package org.opentripplanner.inspector.vector.geofencing; import java.util.List; -import java.util.Map; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; -import org.opentripplanner.api.mapping.PropertyMapper; import org.opentripplanner.framework.geometry.GeometryUtils; import org.opentripplanner.inspector.vector.LayerBuilder; import org.opentripplanner.inspector.vector.LayerParameters; @@ -19,15 +17,11 @@ */ public class GeofencingZonesLayerBuilder extends LayerBuilder { - private static final Map mappers = Map.of( - MapperType.DebugClient, - transitService -> new GeofencingZonesPropertyMapper() - ); private final StreetIndex streetIndex; public GeofencingZonesLayerBuilder(Graph graph, LayerParameters layerParameters) { super( - mappers.get(MapperType.valueOf(layerParameters.mapper())).build(graph), + new GeofencingZonesPropertyMapper(), layerParameters.name(), layerParameters.expansionFactor() ); @@ -47,13 +41,4 @@ protected List getGeometries(Envelope query) { }) .toList(); } - - enum MapperType { - DebugClient, - } - - @FunctionalInterface - private interface MapperFactory { - PropertyMapper build(Graph transitService); - } } diff --git a/src/main/java/org/opentripplanner/inspector/vector/AreaStopsLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/stop/AreaStopsLayerBuilder.java similarity index 77% rename from src/main/java/org/opentripplanner/inspector/vector/AreaStopsLayerBuilder.java rename to src/main/java/org/opentripplanner/inspector/vector/stop/AreaStopsLayerBuilder.java index 6ce7b0962ba..d1a2552e4e2 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/AreaStopsLayerBuilder.java +++ b/src/main/java/org/opentripplanner/inspector/vector/stop/AreaStopsLayerBuilder.java @@ -1,4 +1,4 @@ -package org.opentripplanner.inspector.vector; +package org.opentripplanner.inspector.vector.stop; import java.util.Collection; import java.util.List; @@ -6,7 +6,8 @@ import java.util.function.Function; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.inspector.vector.LayerBuilder; +import org.opentripplanner.inspector.vector.LayerParameters; import org.opentripplanner.transit.model.site.AreaStop; import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.service.TransitService; @@ -24,7 +25,7 @@ public AreaStopsLayerBuilder( Locale locale ) { super( - new DebugClientAreaStopPropertyMapper(locale), + new StopLocationPropertyMapper(locale), layerParameters.name(), layerParameters.expansionFactor() ); @@ -38,20 +39,9 @@ protected List getGeometries(Envelope query) { .stream() .map(areaStop -> { Geometry geometry = areaStop.getGeometry().copy(); - geometry.setUserData(areaStop); - return geometry; }) .toList(); } - - enum MapperType { - DebugClient, - } - - @FunctionalInterface - private interface MapperFactory { - PropertyMapper build(TransitService transitService, Locale locale); - } } diff --git a/src/main/java/org/opentripplanner/inspector/vector/RegularStopsLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/stop/RegularStopsLayerBuilder.java similarity index 84% rename from src/main/java/org/opentripplanner/inspector/vector/RegularStopsLayerBuilder.java rename to src/main/java/org/opentripplanner/inspector/vector/stop/RegularStopsLayerBuilder.java index 26e3f8726ae..f943e23eb88 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/RegularStopsLayerBuilder.java +++ b/src/main/java/org/opentripplanner/inspector/vector/stop/RegularStopsLayerBuilder.java @@ -1,4 +1,4 @@ -package org.opentripplanner.inspector.vector; +package org.opentripplanner.inspector.vector.stop; import java.util.Collection; import java.util.List; @@ -6,6 +6,8 @@ import java.util.function.Function; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; +import org.opentripplanner.inspector.vector.LayerBuilder; +import org.opentripplanner.inspector.vector.LayerParameters; import org.opentripplanner.transit.model.site.RegularStop; import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.service.TransitService; @@ -23,7 +25,7 @@ public RegularStopsLayerBuilder( Locale locale ) { super( - new DebugClientAreaStopPropertyMapper(locale), + new StopLocationPropertyMapper(locale), layerParameters.name(), layerParameters.expansionFactor() ); @@ -42,5 +44,4 @@ protected List getGeometries(Envelope query) { }) .toList(); } - } diff --git a/src/main/java/org/opentripplanner/inspector/vector/DebugClientAreaStopPropertyMapper.java b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java similarity index 74% rename from src/main/java/org/opentripplanner/inspector/vector/DebugClientAreaStopPropertyMapper.java rename to src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java index 1d507140378..d2e1accf483 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/DebugClientAreaStopPropertyMapper.java +++ b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java @@ -1,26 +1,27 @@ -package org.opentripplanner.inspector.vector; +package org.opentripplanner.inspector.vector.stop; import java.util.Collection; import java.util.List; import java.util.Locale; import org.opentripplanner.api.mapping.I18NStringMapper; import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.transit.model.site.StopLocation; import org.opentripplanner.transit.service.TransitService; /** * A {@link PropertyMapper} for the {@link AreaStopsLayerBuilder} for the OTP debug client. */ -public class DebugClientAreaStopPropertyMapper extends PropertyMapper { +public class StopLocationPropertyMapper extends PropertyMapper { private final I18NStringMapper i18NStringMapper; - public DebugClientAreaStopPropertyMapper(Locale locale) { + public StopLocationPropertyMapper(Locale locale) { this.i18NStringMapper = new I18NStringMapper(locale); } public static PropertyMapper create(TransitService ignored, Locale locale) { - return new DebugClientAreaStopPropertyMapper(locale); + return new StopLocationPropertyMapper(locale); } @Override diff --git a/src/test/java/org/opentripplanner/inspector/vector/AreaStopLayerBuilderTest.java b/src/test/java/org/opentripplanner/inspector/vector/stop/AreaStopLayerBuilderTest.java similarity index 86% rename from src/test/java/org/opentripplanner/inspector/vector/AreaStopLayerBuilderTest.java rename to src/test/java/org/opentripplanner/inspector/vector/stop/AreaStopLayerBuilderTest.java index 6f2ca872f21..3fea49ab236 100644 --- a/src/test/java/org/opentripplanner/inspector/vector/AreaStopLayerBuilderTest.java +++ b/src/test/java/org/opentripplanner/inspector/vector/stop/AreaStopLayerBuilderTest.java @@ -1,4 +1,4 @@ -package org.opentripplanner.inspector.vector; +package org.opentripplanner.inspector.vector.stop; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -9,12 +9,11 @@ import org.opentripplanner.framework.geometry.GeometryUtils; import org.opentripplanner.framework.i18n.I18NString; import org.opentripplanner.framework.i18n.NonLocalizedString; +import org.opentripplanner.inspector.vector.KeyValue; 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 AreaStopLayerBuilderTest { @@ -38,7 +37,7 @@ class AreaStopLayerBuilderTest { @Test void map() { - var subject = new DebugClientAreaStopPropertyMapper(Locale.ENGLISH); + var subject = new StopLocationPropertyMapper(Locale.ENGLISH); var properties = subject.map(areaStop); From 033000a2afa7921730bf41a64fb5517b7eaf6a2f Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Wed, 20 Dec 2023 11:20:08 +0100 Subject: [PATCH 04/25] Move styles into separate class --- .../apis/vectortiles/DebugStyleJson.java | 43 +++++++++++++++++++ .../GraphInspectorVectorTileResource.java | 35 +-------------- .../vectortiles/model/LayerStyleBuilder.java | 2 +- .../vectortiles/model/MapboxStyleJson.java | 4 +- 4 files changed, 47 insertions(+), 37 deletions(-) create mode 100644 src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleJson.java diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleJson.java b/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleJson.java new file mode 100644 index 00000000000..75592cbc0cd --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleJson.java @@ -0,0 +1,43 @@ +package org.opentripplanner.apis.vectortiles; + +import java.util.List; +import org.opentripplanner.apis.vectortiles.model.LayerStyleBuilder; +import org.opentripplanner.apis.vectortiles.model.MapboxStyleJson; +import org.opentripplanner.apis.vectortiles.model.TileSource; +import org.opentripplanner.apis.vectortiles.model.TileSource.RasterSource; +import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; + +public class DebugStyleJson { + + private static final RasterSource BACKGROUND_SOURCE = new RasterSource( + "background", + List.of("https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"), + 256 + ); + + static MapboxStyleJson build(String url) { + var vectorSource = new VectorSource("debug", url); + List sources = List.of(BACKGROUND_SOURCE, vectorSource); + return new MapboxStyleJson( + "OTP Debug Tiles", + sources, + List.of( + LayerStyleBuilder + .ofId("background") + .typeRaster() + .source(BACKGROUND_SOURCE) + .minZoom(0) + .maxZoom(22), + LayerStyleBuilder + .ofId("regular-stop") + .typeCircle() + .source(vectorSource) + .sourceLayer("regularStops") + .circleStroke("#140d0e", 1) + .circleColor("#fcf9fa") + .minZoom(13) + .maxZoom(22) + ) + ); + } +} diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java index 9d083bd5e03..6d23e533aad 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java @@ -20,11 +20,7 @@ import javax.annotation.Nonnull; import org.glassfish.grizzly.http.server.Request; import org.opentripplanner.api.model.TileJson; -import org.opentripplanner.apis.vectortiles.model.LayerStyleBuilder; import org.opentripplanner.apis.vectortiles.model.MapboxStyleJson; -import org.opentripplanner.apis.vectortiles.model.TileSource; -import org.opentripplanner.apis.vectortiles.model.TileSource.RasterSource; -import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; import org.opentripplanner.framework.io.HttpUtils; import org.opentripplanner.inspector.vector.LayerBuilder; import org.opentripplanner.inspector.vector.LayerParameters; @@ -123,36 +119,7 @@ public MapboxStyleJson getTileJson(@Context UriInfo uri, @Context HttpHeaders he "/inspector/vectortile/" + allLayers + "/tilejson.json"; - var vectorSource = new VectorSource("debug", url); - var backgroundSource = new RasterSource( - "background", - List.of("https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"), - 256 - ); - List sources = List.of(backgroundSource, vectorSource); - return new MapboxStyleJson( - "OTP Debug Tiles", - sources, - List.of( - LayerStyleBuilder - .ofId("background") - .typeRaster() - .source(backgroundSource) - .minZoom(0) - .maxZoom(22) - .build(), - LayerStyleBuilder - .ofId("regular-stop") - .source(vectorSource) - .sourceLayer("regularStops") - .typeCircle() - .circleStroke("#140d0e", 1) - .circleColor("#fcf9fa") - .minZoom(13) - .maxZoom(22) - .build() - ) - ); + return DebugStyleJson.build(url); } @Nonnull diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java index 759ce7eeb30..d549f2938e0 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java @@ -85,7 +85,7 @@ public LayerStyleBuilder circleStroke(String color, int width) { return this; } - public JsonNode build() { + public JsonNode toJson() { validate(); var copy = new HashMap<>(props); diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java index 6461d697bfc..6214a5aac65 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java @@ -12,10 +12,10 @@ public final class MapboxStyleJson { private final List sources; private final List layers; - public MapboxStyleJson(String name, List sources, List layers) { + public MapboxStyleJson(String name, List sources, List layers) { this.name = name; this.sources = sources; - this.layers = layers; + this.layers = layers.stream().map(LayerStyleBuilder::toJson).toList(); } @JsonSerialize From 57f07ddac6a2c34973b4f591b49ad20bec83e02f Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Thu, 21 Dec 2023 08:30:45 +0100 Subject: [PATCH 05/25] Use style.json from server --- client-next/src/components/MapView/MapView.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/client-next/src/components/MapView/MapView.tsx b/client-next/src/components/MapView/MapView.tsx index 011d9408148..258a925a142 100644 --- a/client-next/src/components/MapView/MapView.tsx +++ b/client-next/src/components/MapView/MapView.tsx @@ -4,7 +4,6 @@ import { TripPattern, TripQuery, TripQueryVariables } from '../../gql/graphql.ts import { NavigationMarkers } from './NavigationMarkers.tsx'; import { LegLines } from './LegLines.tsx'; import { useMapDoubleClick } from './useMapDoubleClick.ts'; -import { mapStyle } from './mapStyle.ts'; import { useState } from 'react'; import { ContextMenuPopup } from './ContextMenuPopup.tsx'; @@ -37,12 +36,21 @@ export function MapView({ // @ts-ignore mapLib={import('maplibre-gl')} // @ts-ignore - mapStyle={mapStyle} + mapStyle="http://localhost:8080/otp/routers/default/inspector/vectortile/style.json" initialViewState={initialViewState} onDblClick={onMapDoubleClick} onContextMenu={(e) => { setShowPopup(e.lngLat); }} + interactiveLayerIds={["regular-stop"]} + onClick={e => { + console.log(e.features); + }} + // put lat/long in URL and pan to it on page reload + hash={true} + // disable pitching and rotating the map + touchPitch={false} + dragRotate={false} > Date: Thu, 21 Dec 2023 22:03:33 +0100 Subject: [PATCH 06/25] Refactor dependencies of map style classes --- ...ebugStyleJson.java => DebugStyleSpec.java} | 16 +++--- .../GraphInspectorVectorTileResource.java | 50 +++++++++---------- .../apis/vectortiles/model/LayerParams.java | 15 ++++++ .../vectortiles/model/LayerStyleBuilder.java | 7 +++ .../apis/vectortiles/model/LayerType.java | 7 +++ .../{MapboxStyleJson.java => StyleSpec.java} | 8 ++- .../apis/vectortiles/model/TileSource.java | 6 +++ .../framework/io/HttpUtils.java | 6 +-- 8 files changed, 77 insertions(+), 38 deletions(-) rename src/main/java/org/opentripplanner/apis/vectortiles/{DebugStyleJson.java => DebugStyleSpec.java} (70%) create mode 100644 src/main/java/org/opentripplanner/apis/vectortiles/model/LayerParams.java create mode 100644 src/main/java/org/opentripplanner/apis/vectortiles/model/LayerType.java rename src/main/java/org/opentripplanner/apis/vectortiles/model/{MapboxStyleJson.java => StyleSpec.java} (77%) diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleJson.java b/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java similarity index 70% rename from src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleJson.java rename to src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java index 75592cbc0cd..9121d671c06 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleJson.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java @@ -2,12 +2,12 @@ import java.util.List; import org.opentripplanner.apis.vectortiles.model.LayerStyleBuilder; -import org.opentripplanner.apis.vectortiles.model.MapboxStyleJson; +import org.opentripplanner.apis.vectortiles.model.StyleSpec; import org.opentripplanner.apis.vectortiles.model.TileSource; import org.opentripplanner.apis.vectortiles.model.TileSource.RasterSource; import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; -public class DebugStyleJson { +public class DebugStyleSpec { private static final RasterSource BACKGROUND_SOURCE = new RasterSource( "background", @@ -15,10 +15,11 @@ public class DebugStyleJson { 256 ); - static MapboxStyleJson build(String url) { - var vectorSource = new VectorSource("debug", url); - List sources = List.of(BACKGROUND_SOURCE, vectorSource); - return new MapboxStyleJson( + public record VectorSourceLayer(VectorSource vectorSource, String vectorLayer) {} + + static StyleSpec build(VectorSource debugSource, VectorSourceLayer regularStops) { + List sources = List.of(BACKGROUND_SOURCE, debugSource); + return new StyleSpec( "OTP Debug Tiles", sources, List.of( @@ -31,8 +32,7 @@ static MapboxStyleJson build(String url) { LayerStyleBuilder .ofId("regular-stop") .typeCircle() - .source(vectorSource) - .sourceLayer("regularStops") + .vectorSourceLayer(regularStops) .circleStroke("#140d0e", 1) .circleColor("#fcf9fa") .minZoom(13) diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java index 6d23e533aad..7e800b5639b 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java @@ -20,7 +20,10 @@ import javax.annotation.Nonnull; import org.glassfish.grizzly.http.server.Request; import org.opentripplanner.api.model.TileJson; -import org.opentripplanner.apis.vectortiles.model.MapboxStyleJson; +import org.opentripplanner.apis.vectortiles.model.LayerParams; +import org.opentripplanner.apis.vectortiles.model.LayerType; +import org.opentripplanner.apis.vectortiles.model.StyleSpec; +import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; import org.opentripplanner.framework.io.HttpUtils; import org.opentripplanner.inspector.vector.LayerBuilder; import org.opentripplanner.inspector.vector.LayerParameters; @@ -38,10 +41,19 @@ @Path("/routers/{ignoreRouterId}/inspector/vectortile") public class GraphInspectorVectorTileResource { + private static final LayerParams REGULAR_STOPS = new LayerParams( + "regularStops", + LayerType.RegularStop + ); + private static final LayerParams AREA_STOPS = new LayerParams("areaStops", LayerType.AreaStop); + private static final LayerParams GEOFENCING_ZONES = new LayerParams( + "geofencingZones", + LayerType.GeofencingZones + ); private static final List> DEBUG_LAYERS = List.of( - new LayerParams("regularStops", LayerType.RegularStop), - new LayerParams("areaStops", LayerType.AreaStop), - new LayerParams("geofencingZones", LayerType.GeofencingZones) + REGULAR_STOPS, + AREA_STOPS, + GEOFENCING_ZONES ); private final OtpServerRequestContext serverContext; @@ -106,20 +118,21 @@ public TileJson getTileJson( @GET @Path("/style.json") @Produces(MediaType.APPLICATION_JSON) - public MapboxStyleJson getTileJson(@Context UriInfo uri, @Context HttpHeaders headers) { + public StyleSpec getTileJson(@Context UriInfo uri, @Context HttpHeaders headers) { var base = HttpUtils.getBaseAddress(uri, headers); final String allLayers = DEBUG_LAYERS .stream() .map(LayerParameters::name) .collect(Collectors.joining(",")); var url = - base + - "/otp/routers/" + - ignoreRouterId + - "/inspector/vectortile/" + - allLayers + - "/tilejson.json"; - return DebugStyleJson.build(url); + "%s/otp/routers/%s/inspector/vectortile/%s/tilejson.json".formatted( + base, + ignoreRouterId, + allLayers + ); + + var vectorSource = new VectorSource("debug", url); + return DebugStyleSpec.build(vectorSource, REGULAR_STOPS.toVectorSourceLayer(vectorSource)); } @Nonnull @@ -148,17 +161,4 @@ private static LayerBuilder createLayerBuilder( case GeofencingZones -> new GeofencingZonesLayerBuilder(context.graph(), layerParameters); }; } - - private enum LayerType { - RegularStop, - AreaStop, - GeofencingZones, - } - - private record LayerParams(String name, LayerType type) implements LayerParameters { - @Override - public String mapper() { - return "DebugClient"; - } - } } diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerParams.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerParams.java new file mode 100644 index 00000000000..2f1e6eb7109 --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerParams.java @@ -0,0 +1,15 @@ +package org.opentripplanner.apis.vectortiles.model; + +import org.opentripplanner.apis.vectortiles.DebugStyleSpec; +import org.opentripplanner.inspector.vector.LayerParameters; + +public record LayerParams(String name, LayerType type) implements LayerParameters { + @Override + public String mapper() { + return "DebugClient"; + } + + public DebugStyleSpec.VectorSourceLayer toVectorSourceLayer(TileSource.VectorSource source) { + return new DebugStyleSpec.VectorSourceLayer(source, name); + } +} diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java index d549f2938e0..0e1006027f2 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java @@ -6,6 +6,7 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Stream; +import org.opentripplanner.apis.vectortiles.DebugStyleSpec.VectorSourceLayer; import org.opentripplanner.framework.json.ObjectMappers; /** @@ -24,6 +25,12 @@ public static LayerStyleBuilder ofId(String id) { return new LayerStyleBuilder(id); } + public LayerStyleBuilder vectorSourceLayer(VectorSourceLayer source) { + source(source.vectorSource()); + sourceLayer(source.vectorLayer()); + return this; + } + public enum LayerType { Circle, Raster, diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerType.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerType.java new file mode 100644 index 00000000000..f4cb7a636fa --- /dev/null +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerType.java @@ -0,0 +1,7 @@ +package org.opentripplanner.apis.vectortiles.model; + +public enum LayerType { + RegularStop, + AreaStop, + GeofencingZones, +} diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/StyleSpec.java similarity index 77% rename from src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java rename to src/main/java/org/opentripplanner/apis/vectortiles/model/StyleSpec.java index 6214a5aac65..090573d467d 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/MapboxStyleJson.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/StyleSpec.java @@ -6,13 +6,17 @@ import java.util.List; import java.util.Map; -public final class MapboxStyleJson { +/** + * Represents a style specification for Maplibre/Mapbox vector tile layers. + * https://maplibre.org/maplibre-style-spec/root/ + */ +public final class StyleSpec { private final String name; private final List sources; private final List layers; - public MapboxStyleJson(String name, List sources, List layers) { + public StyleSpec(String name, List sources, List layers) { this.name = name; this.sources = sources; this.layers = layers.stream().map(LayerStyleBuilder::toJson).toList(); diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java index 2e404d9a1eb..debf3070782 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java @@ -9,6 +9,9 @@ public sealed interface TileSource { String id(); + /** + * Represents a vector tile source. + */ record VectorSource(String id, String url) implements TileSource { @Override public String type() { @@ -16,6 +19,9 @@ public String type() { } } + /** + * Represents a raster-based source for map tiles. + */ record RasterSource(String id, List tiles, int tileSize) implements TileSource { @Override public String type() { diff --git a/src/main/java/org/opentripplanner/framework/io/HttpUtils.java b/src/main/java/org/opentripplanner/framework/io/HttpUtils.java index 3450cf0786c..4981a8ab91b 100644 --- a/src/main/java/org/opentripplanner/framework/io/HttpUtils.java +++ b/src/main/java/org/opentripplanner/framework/io/HttpUtils.java @@ -24,16 +24,16 @@ private HttpUtils() {} public static String getBaseAddress(UriInfo uri, HttpHeaders headers) { String protocol; if (headers.getRequestHeader(HEADER_X_FORWARDED_PROTO) != null) { - protocol = headers.getRequestHeader(HEADER_X_FORWARDED_PROTO).get(0); + protocol = headers.getRequestHeader(HEADER_X_FORWARDED_PROTO).getFirst(); } else { protocol = uri.getRequestUri().getScheme(); } String host; if (headers.getRequestHeader(HEADER_X_FORWARDED_HOST) != null) { - host = headers.getRequestHeader(HEADER_X_FORWARDED_HOST).get(0); + host = headers.getRequestHeader(HEADER_X_FORWARDED_HOST).getFirst(); } else if (headers.getRequestHeader(HEADER_HOST) != null) { - host = headers.getRequestHeader(HEADER_HOST).get(0); + host = headers.getRequestHeader(HEADER_HOST).getFirst(); } else { host = uri.getBaseUri().getHost() + ":" + uri.getBaseUri().getPort(); } From ffd8ae6c80720888f8cff37ff0a772a0a28c2a9c Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Fri, 22 Dec 2023 11:33:55 +0100 Subject: [PATCH 07/25] Add popup data --- .../src/components/MapView/MapView.tsx | 45 +++++++++++++++---- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/client-next/src/components/MapView/MapView.tsx b/client-next/src/components/MapView/MapView.tsx index 258a925a142..9409a0cc68a 100644 --- a/client-next/src/components/MapView/MapView.tsx +++ b/client-next/src/components/MapView/MapView.tsx @@ -1,4 +1,4 @@ -import { LngLat, Map, NavigationControl } from 'react-map-gl'; +import { LngLat, Map, MapboxGeoJSONFeature, NavigationControl, Popup } from 'react-map-gl'; import 'maplibre-gl/dist/maplibre-gl.css'; import { TripPattern, TripQuery, TripQueryVariables } from '../../gql/graphql.ts'; import { NavigationMarkers } from './NavigationMarkers.tsx'; @@ -6,6 +6,7 @@ import { LegLines } from './LegLines.tsx'; import { useMapDoubleClick } from './useMapDoubleClick.ts'; import { useState } from 'react'; import { ContextMenuPopup } from './ContextMenuPopup.tsx'; +import { Table } from 'react-bootstrap'; // TODO: this should be configurable const initialViewState = { @@ -14,6 +15,13 @@ const initialViewState = { zoom: 4, }; +class PopupData { + constructor( + public coordinates: LngLat, + public feature: MapboxGeoJSONFeature, + ) {} +} + export function MapView({ tripQueryVariables, setTripQueryVariables, @@ -28,7 +36,8 @@ export function MapView({ loading: boolean; }) { const onMapDoubleClick = useMapDoubleClick({ tripQueryVariables, setTripQueryVariables }); - const [showPopup, setShowPopup] = useState(null); + const [showContextPopup, setShowContextPopup] = useState(null); + const [showPropsPopup, setShowPropsPopup] = useState(null); return (
@@ -40,11 +49,12 @@ export function MapView({ initialViewState={initialViewState} onDblClick={onMapDoubleClick} onContextMenu={(e) => { - setShowPopup(e.lngLat); + setShowContextPopup(e.lngLat); }} - interactiveLayerIds={["regular-stop"]} - onClick={e => { - console.log(e.features); + interactiveLayerIds={['regular-stop']} + onClick={(e) => { + const props = e.features[0]; + setShowPropsPopup(new PopupData(e.lngLat, props)); }} // put lat/long in URL and pan to it on page reload hash={true} @@ -61,14 +71,31 @@ export function MapView({ {tripQueryResult?.trip.tripPatterns.length && ( )} - {showPopup && ( + {showContextPopup && ( setShowPopup(null)} + coordinates={showContextPopup} + onClose={() => setShowContextPopup(null)} /> )} + {showPropsPopup && ( + setShowPropsPopup(null)} + > + + {Object.entries(showPropsPopup.feature.properties).map(([key, value]) => ( + + + + + ))} +
{key}{value}
+
+ )}
); From da28cf241fc0cd67d634be6a0fe05e05b73a72e5 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Sat, 30 Dec 2023 20:11:32 +0100 Subject: [PATCH 08/25] Remove edge layer builder --- .../vector/edge/EdgeLayerBuilder.java | 40 ------------------- .../vector/edge/EdgePropertyMapper.java | 18 --------- 2 files changed, 58 deletions(-) delete mode 100644 src/main/java/org/opentripplanner/inspector/vector/edge/EdgeLayerBuilder.java delete mode 100644 src/main/java/org/opentripplanner/inspector/vector/edge/EdgePropertyMapper.java diff --git a/src/main/java/org/opentripplanner/inspector/vector/edge/EdgeLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/edge/EdgeLayerBuilder.java deleted file mode 100644 index 3c1bc3436d8..00000000000 --- a/src/main/java/org/opentripplanner/inspector/vector/edge/EdgeLayerBuilder.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.opentripplanner.inspector.vector.edge; - -import java.util.List; -import org.locationtech.jts.geom.Envelope; -import org.locationtech.jts.geom.Geometry; -import org.opentripplanner.framework.geometry.GeometryUtils; -import org.opentripplanner.inspector.vector.LayerBuilder; -import org.opentripplanner.inspector.vector.LayerParameters; -import org.opentripplanner.routing.graph.Graph; -import org.opentripplanner.routing.graph.index.StreetIndex; -import org.opentripplanner.street.model.edge.Edge; -import org.opentripplanner.street.model.vertex.Vertex; -import org.opentripplanner.transit.model.site.AreaStop; - -/** - * A vector tile layer containing all {@link AreaStop}s inside the vector tile bounds. - */ -public class EdgeLayerBuilder extends LayerBuilder { - - private final StreetIndex streetIndex; - - public EdgeLayerBuilder(Graph graph, LayerParameters layerParameters) { - super(new EdgePropertyMapper(), layerParameters.name(), layerParameters.expansionFactor()); - this.streetIndex = graph.getStreetIndex(); - } - - @Override - protected List getGeometries(Envelope query) { - return streetIndex - .getEdgesForEnvelope(query) - .stream() - .filter(edge -> edge.getGeometry() != null) - .map(edge -> { - Geometry geometry = edge.getGeometry().copy(); - geometry.setUserData(edge); - return geometry; - }) - .toList(); - } -} diff --git a/src/main/java/org/opentripplanner/inspector/vector/edge/EdgePropertyMapper.java b/src/main/java/org/opentripplanner/inspector/vector/edge/EdgePropertyMapper.java deleted file mode 100644 index 936c965c9f5..00000000000 --- a/src/main/java/org/opentripplanner/inspector/vector/edge/EdgePropertyMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.opentripplanner.inspector.vector.edge; - -import java.util.Collection; -import java.util.List; -import org.opentripplanner.api.mapping.PropertyMapper; -import org.opentripplanner.inspector.vector.KeyValue; -import org.opentripplanner.street.model.edge.Edge; - -/** - * A {@link PropertyMapper} for the {@link EdgeLayerBuilder} for the OTP debug client. - */ -public class EdgePropertyMapper extends PropertyMapper { - - @Override - protected Collection map(Edge edge) { - return List.of(new KeyValue("java-class", edge.getClass().getSimpleName())); - } -} From 18eb243f84aab078770d66fd2f8cceff74dd47ec Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Sat, 30 Dec 2023 23:31:49 +0100 Subject: [PATCH 09/25] Make styles a but prettier --- .../src/components/MapView/MapView.tsx | 12 +++-- .../apis/vectortiles/DebugStyleSpec.java | 6 ++- .../GraphInspectorVectorTileResource.java | 15 +++--- .../inspector/vector/KeyValue.java | 6 ++- .../vector/stop/AreaStopsLayerBuilder.java | 47 ------------------- ...ayerBuilder.java => StopLayerBuilder.java} | 15 +++--- .../stop/StopLocationPropertyMapper.java | 14 +++--- 7 files changed, 39 insertions(+), 76 deletions(-) delete mode 100644 src/main/java/org/opentripplanner/inspector/vector/stop/AreaStopsLayerBuilder.java rename src/main/java/org/opentripplanner/inspector/vector/stop/{RegularStopsLayerBuilder.java => StopLayerBuilder.java} (73%) diff --git a/client-next/src/components/MapView/MapView.tsx b/client-next/src/components/MapView/MapView.tsx index 9409a0cc68a..a565ae22db9 100644 --- a/client-next/src/components/MapView/MapView.tsx +++ b/client-next/src/components/MapView/MapView.tsx @@ -86,12 +86,14 @@ export function MapView({ closeButton={true} onClose={() => setShowPropsPopup(null)} > - +
{Object.entries(showPropsPopup.feature.properties).map(([key, value]) => ( - - - - + + + + + + ))}
{key}{value}
{key}{value}
diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java b/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java index 9121d671c06..c3dfc3d06f1 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java @@ -7,6 +7,10 @@ import org.opentripplanner.apis.vectortiles.model.TileSource.RasterSource; import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; +/** + * A Mapbox/Mapblibre style specification for rendering debug information about transit and + * street data. + */ public class DebugStyleSpec { private static final RasterSource BACKGROUND_SOURCE = new RasterSource( @@ -33,7 +37,7 @@ static StyleSpec build(VectorSource debugSource, VectorSourceLayer regularStops) .ofId("regular-stop") .typeCircle() .vectorSourceLayer(regularStops) - .circleStroke("#140d0e", 1) + .circleStroke("#140d0e", 2) .circleColor("#fcf9fa") .minZoom(13) .maxZoom(22) diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java index 7e800b5639b..c27d38b260c 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/GraphInspectorVectorTileResource.java @@ -29,8 +29,7 @@ import org.opentripplanner.inspector.vector.LayerParameters; import org.opentripplanner.inspector.vector.VectorTileResponseFactory; import org.opentripplanner.inspector.vector.geofencing.GeofencingZonesLayerBuilder; -import org.opentripplanner.inspector.vector.stop.AreaStopsLayerBuilder; -import org.opentripplanner.inspector.vector.stop.RegularStopsLayerBuilder; +import org.opentripplanner.inspector.vector.stop.StopLayerBuilder; import org.opentripplanner.model.FeedInfo; import org.opentripplanner.standalone.api.OtpServerRequestContext; @@ -152,12 +151,16 @@ private static LayerBuilder createLayerBuilder( OtpServerRequestContext context ) { return switch (layerParameters.type()) { - case RegularStop -> new RegularStopsLayerBuilder( - context.transitService(), + case RegularStop -> new StopLayerBuilder<>( layerParameters, - locale + locale, + e -> context.transitService().findRegularStop(e) + ); + case AreaStop -> new StopLayerBuilder<>( + layerParameters, + locale, + e -> context.transitService().findAreaStops(e) ); - case AreaStop -> new AreaStopsLayerBuilder(context.transitService(), layerParameters, locale); case GeofencingZones -> new GeofencingZonesLayerBuilder(context.graph(), layerParameters); }; } diff --git a/src/main/java/org/opentripplanner/inspector/vector/KeyValue.java b/src/main/java/org/opentripplanner/inspector/vector/KeyValue.java index d57afd3429e..6c8b0f3aa4e 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/KeyValue.java +++ b/src/main/java/org/opentripplanner/inspector/vector/KeyValue.java @@ -1,3 +1,7 @@ package org.opentripplanner.inspector.vector; -public record KeyValue(String key, Object value) {} +public record KeyValue(String key, Object value) { + public static KeyValue kv(String key, Object value) { + return new KeyValue(key, value); + } +} diff --git a/src/main/java/org/opentripplanner/inspector/vector/stop/AreaStopsLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/stop/AreaStopsLayerBuilder.java deleted file mode 100644 index d1a2552e4e2..00000000000 --- a/src/main/java/org/opentripplanner/inspector/vector/stop/AreaStopsLayerBuilder.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.opentripplanner.inspector.vector.stop; - -import java.util.Collection; -import java.util.List; -import java.util.Locale; -import java.util.function.Function; -import org.locationtech.jts.geom.Envelope; -import org.locationtech.jts.geom.Geometry; -import org.opentripplanner.inspector.vector.LayerBuilder; -import org.opentripplanner.inspector.vector.LayerParameters; -import org.opentripplanner.transit.model.site.AreaStop; -import org.opentripplanner.transit.model.site.StopLocation; -import org.opentripplanner.transit.service.TransitService; - -/** - * A vector tile layer containing all {@link AreaStop}s inside the vector tile bounds. - */ -public class AreaStopsLayerBuilder extends LayerBuilder { - - private final Function> findAreaStops; - - public AreaStopsLayerBuilder( - TransitService transitService, - LayerParameters layerParameters, - Locale locale - ) { - super( - new StopLocationPropertyMapper(locale), - layerParameters.name(), - layerParameters.expansionFactor() - ); - this.findAreaStops = transitService::findAreaStops; - } - - @Override - protected List getGeometries(Envelope query) { - return findAreaStops - .apply(query) - .stream() - .map(areaStop -> { - Geometry geometry = areaStop.getGeometry().copy(); - geometry.setUserData(areaStop); - return geometry; - }) - .toList(); - } -} diff --git a/src/main/java/org/opentripplanner/inspector/vector/stop/RegularStopsLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLayerBuilder.java similarity index 73% rename from src/main/java/org/opentripplanner/inspector/vector/stop/RegularStopsLayerBuilder.java rename to src/main/java/org/opentripplanner/inspector/vector/stop/StopLayerBuilder.java index f943e23eb88..40784ab5b3b 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/stop/RegularStopsLayerBuilder.java +++ b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLayerBuilder.java @@ -10,31 +10,30 @@ import org.opentripplanner.inspector.vector.LayerParameters; import org.opentripplanner.transit.model.site.RegularStop; import org.opentripplanner.transit.model.site.StopLocation; -import org.opentripplanner.transit.service.TransitService; /** * A vector tile layer containing all {@link RegularStop}s inside the vector tile bounds. */ -public class RegularStopsLayerBuilder extends LayerBuilder { +public class StopLayerBuilder extends LayerBuilder { - private final Function> findAreaStops; + private final Function> findStops; - public RegularStopsLayerBuilder( - TransitService transitService, + public StopLayerBuilder( LayerParameters layerParameters, - Locale locale + Locale locale, + Function> findStops ) { super( new StopLocationPropertyMapper(locale), layerParameters.name(), layerParameters.expansionFactor() ); - this.findAreaStops = transitService::findRegularStop; + this.findStops = findStops; } @Override protected List getGeometries(Envelope query) { - return findAreaStops + return findStops .apply(query) .stream() .map(stop -> { diff --git a/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java index d2e1accf483..44729bcb407 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java +++ b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java @@ -1,5 +1,7 @@ package org.opentripplanner.inspector.vector.stop; +import static org.opentripplanner.inspector.vector.KeyValue.kv; + import java.util.Collection; import java.util.List; import java.util.Locale; @@ -7,7 +9,6 @@ import org.opentripplanner.api.mapping.PropertyMapper; import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.transit.model.site.StopLocation; -import org.opentripplanner.transit.service.TransitService; /** * A {@link PropertyMapper} for the {@link AreaStopsLayerBuilder} for the OTP debug client. @@ -20,15 +21,12 @@ public StopLocationPropertyMapper(Locale locale) { this.i18NStringMapper = new I18NStringMapper(locale); } - public static PropertyMapper create(TransitService ignored, Locale locale) { - return new StopLocationPropertyMapper(locale); - } - @Override - protected Collection map(StopLocation input) { + protected Collection map(StopLocation stop) { return List.of( - new KeyValue("id", input.getId().toString()), - new KeyValue("name", i18NStringMapper.mapToApi(input.getName())) + kv("name", i18NStringMapper.mapToApi(stop.getName())), + kv("id", stop.getId().toString()), + kv("parentId", stop.isPartOfStation() ? stop.getParentStation().getId().toString() : null) ); } } From 7cfbae80109ecd00c9240ca9c2e803206eae8fd8 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Sun, 31 Dec 2023 00:04:49 +0100 Subject: [PATCH 10/25] Add test for debug style spec --- .../vectortiles/model/LayerStyleBuilder.java | 3 +- .../apis/vectortiles/DebugStyleSpecTest.java | 25 +++++++++++ .../vector/stop/AreaStopLayerBuilderTest.java | 16 ++------ .../test/support/ResourceLoader.java | 11 +++++ .../apis/vectortiles/style.json | 41 +++++++++++++++++++ 5 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 src/test/java/org/opentripplanner/apis/vectortiles/DebugStyleSpecTest.java create mode 100644 src/test/resources/org/opentripplanner/apis/vectortiles/style.json diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java index 0e1006027f2..41144611f92 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerStyleBuilder.java @@ -27,8 +27,7 @@ public static LayerStyleBuilder ofId(String id) { public LayerStyleBuilder vectorSourceLayer(VectorSourceLayer source) { source(source.vectorSource()); - sourceLayer(source.vectorLayer()); - return this; + return sourceLayer(source.vectorLayer()); } public enum LayerType { diff --git a/src/test/java/org/opentripplanner/apis/vectortiles/DebugStyleSpecTest.java b/src/test/java/org/opentripplanner/apis/vectortiles/DebugStyleSpecTest.java new file mode 100644 index 00000000000..4fd9204c2a9 --- /dev/null +++ b/src/test/java/org/opentripplanner/apis/vectortiles/DebugStyleSpecTest.java @@ -0,0 +1,25 @@ +package org.opentripplanner.apis.vectortiles; + +import static org.opentripplanner.test.support.JsonAssertions.assertEqualJson; + +import org.junit.jupiter.api.Test; +import org.opentripplanner.apis.vectortiles.DebugStyleSpec.VectorSourceLayer; +import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; +import org.opentripplanner.framework.json.ObjectMappers; +import org.opentripplanner.test.support.ResourceLoader; + +class DebugStyleSpecTest { + + private final ResourceLoader RES = ResourceLoader.of(this); + + @Test + void spec() { + var vectorSource = new VectorSource("vectorSource", "https://example.com"); + var regularStops = new VectorSourceLayer(vectorSource, "regularStops"); + var spec = DebugStyleSpec.build(vectorSource, regularStops); + + var json = ObjectMappers.ignoringExtraFields().valueToTree(spec).toPrettyString(); + var expectation = RES.fileToString("style.json"); + assertEqualJson(expectation, json); + } +} diff --git a/src/test/java/org/opentripplanner/inspector/vector/stop/AreaStopLayerBuilderTest.java b/src/test/java/org/opentripplanner/inspector/vector/stop/AreaStopLayerBuilderTest.java index 3fea49ab236..231f3ddce59 100644 --- a/src/test/java/org/opentripplanner/inspector/vector/stop/AreaStopLayerBuilderTest.java +++ b/src/test/java/org/opentripplanner/inspector/vector/stop/AreaStopLayerBuilderTest.java @@ -1,12 +1,10 @@ package org.opentripplanner.inspector.vector.stop; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Locale; import org.junit.jupiter.api.Test; -import org.locationtech.jts.geom.Coordinate; -import org.opentripplanner.framework.geometry.GeometryUtils; +import org.opentripplanner._support.geometry.Polygons; import org.opentripplanner.framework.i18n.I18NString; import org.opentripplanner.framework.i18n.NonLocalizedString; import org.opentripplanner.inspector.vector.KeyValue; @@ -17,22 +15,15 @@ class AreaStopLayerBuilderTest { - private static final Coordinate[] COORDINATES = { - new Coordinate(0, 0), - new Coordinate(0, 1), - new Coordinate(1, 1), - new Coordinate(1, 0), - new Coordinate(0, 0), - }; private static final FeedScopedId ID = new FeedScopedId("FEED", "ID"); - private static final I18NString NAME = new NonLocalizedString("Test stop"); + private static final I18NString NAME = I18NString.of("Test stop"); private final StopModelBuilder stopModelBuilder = StopModel.of(); private final AreaStop areaStop = stopModelBuilder .areaStop(ID) .withName(NAME) - .withGeometry(GeometryUtils.getGeometryFactory().createPolygon(COORDINATES)) + .withGeometry(Polygons.BERLIN) .build(); @Test @@ -41,7 +32,6 @@ void map() { var properties = subject.map(areaStop); - assertEquals(2, properties.size()); assertTrue(properties.contains(new KeyValue("id", ID.toString()))); assertTrue(properties.contains(new KeyValue("name", NAME.toString()))); } diff --git a/src/test/java/org/opentripplanner/test/support/ResourceLoader.java b/src/test/java/org/opentripplanner/test/support/ResourceLoader.java index 38fe02a8c74..5eb51cac55a 100644 --- a/src/test/java/org/opentripplanner/test/support/ResourceLoader.java +++ b/src/test/java/org/opentripplanner/test/support/ResourceLoader.java @@ -55,6 +55,17 @@ public File file(String path) { return file; } + /** + * Returns the string content of a file. + */ + public String fileToString(String p) { + try { + return Files.readString(file(p).toPath()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + /** * Return a URL for the given resource. */ diff --git a/src/test/resources/org/opentripplanner/apis/vectortiles/style.json b/src/test/resources/org/opentripplanner/apis/vectortiles/style.json new file mode 100644 index 00000000000..f0ed87090c3 --- /dev/null +++ b/src/test/resources/org/opentripplanner/apis/vectortiles/style.json @@ -0,0 +1,41 @@ +{ + "name": "OTP Debug Tiles", + "sources": { + "background": { + "id": "background", + "tiles": [ + "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png" + ], + "tileSize": 256, + "type": "raster" + }, + "vectorSource": { + "id": "vectorSource", + "url": "https://example.com", + "type": "vector" + } + }, + "layers": [ + { + "id": "background", + "source": "background", + "type": "raster", + "maxzoom": 22, + "minzoom": 0 + }, + { + "maxzoom": 22, + "paint": { + "circle-stroke-width": 2, + "circle-color": "#fcf9fa", + "circle-stroke-color": "#140d0e" + }, + "id": "regular-stop", + "source": "vectorSource", + "source-layer": "regularStops", + "type": "circle", + "minzoom": 13 + } + ], + "version": 8 +} From c7395d8282ea247e4d4a1d808efb740c0a6a6a79 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Sun, 31 Dec 2023 00:13:31 +0100 Subject: [PATCH 11/25] Save a JSON round trip --- .../apis/vectortiles/DebugStyleSpecTest.java | 2 +- .../test/support/JsonAssertions.java | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/opentripplanner/apis/vectortiles/DebugStyleSpecTest.java b/src/test/java/org/opentripplanner/apis/vectortiles/DebugStyleSpecTest.java index 4fd9204c2a9..d685e07a2f2 100644 --- a/src/test/java/org/opentripplanner/apis/vectortiles/DebugStyleSpecTest.java +++ b/src/test/java/org/opentripplanner/apis/vectortiles/DebugStyleSpecTest.java @@ -18,7 +18,7 @@ void spec() { var regularStops = new VectorSourceLayer(vectorSource, "regularStops"); var spec = DebugStyleSpec.build(vectorSource, regularStops); - var json = ObjectMappers.ignoringExtraFields().valueToTree(spec).toPrettyString(); + var json = ObjectMappers.ignoringExtraFields().valueToTree(spec); var expectation = RES.fileToString("style.json"); assertEqualJson(expectation, json); } diff --git a/src/test/java/org/opentripplanner/test/support/JsonAssertions.java b/src/test/java/org/opentripplanner/test/support/JsonAssertions.java index f3942c16f3b..2dab1e96190 100644 --- a/src/test/java/org/opentripplanner/test/support/JsonAssertions.java +++ b/src/test/java/org/opentripplanner/test/support/JsonAssertions.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.opentripplanner.standalone.config.framework.json.JsonSupport; @@ -15,9 +16,19 @@ public class JsonAssertions { */ public static void assertEqualJson(String expected, String actual) { try { - var act = MAPPER.readTree(actual); + assertEqualJson(expected, MAPPER.readTree(actual)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + /** + * @see JsonAssertions#assertEqualJson(String, String) + */ + public static void assertEqualJson(String expected, JsonNode actual) { + try { var exp = MAPPER.readTree(expected); - assertEquals(JsonSupport.prettyPrint(exp), JsonSupport.prettyPrint(act)); + assertEquals(JsonSupport.prettyPrint(exp), JsonSupport.prettyPrint(actual)); } catch (JsonProcessingException e) { throw new RuntimeException(e); } From 934b809480f9f4976f95d7f5d93125a1d7d4e1e9 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 2 Jan 2024 16:59:58 +0100 Subject: [PATCH 12/25] Add attribution, remove client side style --- .../src/components/MapView/mapStyle.ts | 19 ------------------- .../apis/vectortiles/DebugStyleSpec.java | 3 ++- .../apis/vectortiles/model/TileSource.java | 2 +- .../apis/vectortiles/style.json | 1 + 4 files changed, 4 insertions(+), 21 deletions(-) delete mode 100644 client-next/src/components/MapView/mapStyle.ts diff --git a/client-next/src/components/MapView/mapStyle.ts b/client-next/src/components/MapView/mapStyle.ts deleted file mode 100644 index ecaa88c0354..00000000000 --- a/client-next/src/components/MapView/mapStyle.ts +++ /dev/null @@ -1,19 +0,0 @@ -export const mapStyle = { - version: 8, - sources: { - osm: { - type: 'raster', - tiles: ['https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'], - tileSize: 256, - attribution: '© OpenStreetMap Contributors', - maxzoom: 19, - }, - }, - layers: [ - { - id: 'osm', - type: 'raster', - source: 'osm', // This must match the source key above - }, - ], -}; diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java b/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java index c3dfc3d06f1..9a4fe9be123 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java @@ -16,7 +16,8 @@ public class DebugStyleSpec { private static final RasterSource BACKGROUND_SOURCE = new RasterSource( "background", List.of("https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"), - 256 + 256, + "© OpenStreetMap Contributors" ); public record VectorSourceLayer(VectorSource vectorSource, String vectorLayer) {} diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java index debf3070782..d9dbe50f68e 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java @@ -22,7 +22,7 @@ public String type() { /** * Represents a raster-based source for map tiles. */ - record RasterSource(String id, List tiles, int tileSize) implements TileSource { + record RasterSource(String id, List tiles, int tileSize, String attribution) implements TileSource { @Override public String type() { return "raster"; diff --git a/src/test/resources/org/opentripplanner/apis/vectortiles/style.json b/src/test/resources/org/opentripplanner/apis/vectortiles/style.json index f0ed87090c3..6f95471a667 100644 --- a/src/test/resources/org/opentripplanner/apis/vectortiles/style.json +++ b/src/test/resources/org/opentripplanner/apis/vectortiles/style.json @@ -7,6 +7,7 @@ "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png" ], "tileSize": 256, + "attribution" : "© OpenStreetMap Contributors", "type": "raster" }, "vectorSource": { From 826a8429e14afe04ea48dbe8f4e5061d4cb303fd Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 2 Jan 2024 17:09:44 +0100 Subject: [PATCH 13/25] Add documentation, fix frontend code --- client-next/src/components/MapView/MapView.tsx | 10 +++++----- .../apis/vectortiles/model/LayerParams.java | 11 ++++++++--- .../apis/vectortiles/model/StyleSpec.java | 2 ++ .../apis/vectortiles/model/TileSource.java | 8 ++++++-- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/client-next/src/components/MapView/MapView.tsx b/client-next/src/components/MapView/MapView.tsx index a565ae22db9..c3879dd2a6b 100644 --- a/client-next/src/components/MapView/MapView.tsx +++ b/client-next/src/components/MapView/MapView.tsx @@ -87,14 +87,14 @@ export function MapView({ onClose={() => setShowPropsPopup(null)} > - {Object.entries(showPropsPopup.feature.properties).map(([key, value]) => ( - - + + {Object.entries(showPropsPopup.feature.properties).map(([key, value]) => ( + - - ))} + ))} +
{key} {value}
)} diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerParams.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerParams.java index 2f1e6eb7109..7365e8972da 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerParams.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/LayerParams.java @@ -1,6 +1,7 @@ package org.opentripplanner.apis.vectortiles.model; -import org.opentripplanner.apis.vectortiles.DebugStyleSpec; +import org.opentripplanner.apis.vectortiles.DebugStyleSpec.VectorSourceLayer; +import org.opentripplanner.apis.vectortiles.model.TileSource.VectorSource; import org.opentripplanner.inspector.vector.LayerParameters; public record LayerParams(String name, LayerType type) implements LayerParameters { @@ -9,7 +10,11 @@ public String mapper() { return "DebugClient"; } - public DebugStyleSpec.VectorSourceLayer toVectorSourceLayer(TileSource.VectorSource source) { - return new DebugStyleSpec.VectorSourceLayer(source, name); + /** + * Convert these params to a vector source layer so that it can be used in the style for rendering + * in the frontend. + */ + public VectorSourceLayer toVectorSourceLayer(VectorSource source) { + return new VectorSourceLayer(source, name); } } diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/StyleSpec.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/StyleSpec.java index 090573d467d..84e19f25364 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/StyleSpec.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/StyleSpec.java @@ -9,6 +9,8 @@ /** * Represents a style specification for Maplibre/Mapbox vector tile layers. * https://maplibre.org/maplibre-style-spec/root/ + *

+ * Maplibre uses these to render vector maps in the browser. */ public final class StyleSpec { diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java index d9dbe50f68e..e3186cc1d99 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java @@ -3,6 +3,9 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.List; +/** + * Represent a data source where Maplibre can fetch data for rendering directly in the browser. + */ public sealed interface TileSource { @JsonSerialize String type(); @@ -10,7 +13,7 @@ public sealed interface TileSource { String id(); /** - * Represents a vector tile source. + * Represents a vector tile source which is rendered into a map in the browser. */ record VectorSource(String id, String url) implements TileSource { @Override @@ -20,7 +23,8 @@ public String type() { } /** - * Represents a raster-based source for map tiles. + * Represents a raster-based source for map tiles. These are used mainly for background + * map layers with vector data being rendered on top of it. */ record RasterSource(String id, List tiles, int tileSize, String attribution) implements TileSource { @Override From c8642006f32c59f94007bcb532bc2eb51f8f1804 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 2 Jan 2024 21:57:30 +0100 Subject: [PATCH 14/25] Make TS compiler happy --- client-next/src/components/MapView/MapView.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client-next/src/components/MapView/MapView.tsx b/client-next/src/components/MapView/MapView.tsx index c3879dd2a6b..d03c4869067 100644 --- a/client-next/src/components/MapView/MapView.tsx +++ b/client-next/src/components/MapView/MapView.tsx @@ -53,8 +53,10 @@ export function MapView({ }} interactiveLayerIds={['regular-stop']} onClick={(e) => { - const props = e.features[0]; - setShowPropsPopup(new PopupData(e.lngLat, props)); + if (e.features) { + const props = e.features[0]; + setShowPropsPopup(new PopupData(e.lngLat, props)); + } }} // put lat/long in URL and pan to it on page reload hash={true} @@ -79,7 +81,7 @@ export function MapView({ onClose={() => setShowContextPopup(null)} /> )} - {showPropsPopup && ( + {showPropsPopup && showPropsPopup.feature && showPropsPopup.feature.properties && ( Date: Tue, 2 Jan 2024 22:00:55 +0100 Subject: [PATCH 15/25] Convert from class to type --- client-next/src/components/MapView/MapView.tsx | 9 ++------- .../apis/vectortiles/model/TileSource.java | 3 ++- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/client-next/src/components/MapView/MapView.tsx b/client-next/src/components/MapView/MapView.tsx index d03c4869067..9ecc35c27aa 100644 --- a/client-next/src/components/MapView/MapView.tsx +++ b/client-next/src/components/MapView/MapView.tsx @@ -15,12 +15,7 @@ const initialViewState = { zoom: 4, }; -class PopupData { - constructor( - public coordinates: LngLat, - public feature: MapboxGeoJSONFeature, - ) {} -} +type PopupData = { coordinates: LngLat; feature: MapboxGeoJSONFeature }; export function MapView({ tripQueryVariables, @@ -55,7 +50,7 @@ export function MapView({ onClick={(e) => { if (e.features) { const props = e.features[0]; - setShowPropsPopup(new PopupData(e.lngLat, props)); + setShowPropsPopup({ coordinates: e.lngLat, feature: props }); } }} // put lat/long in URL and pan to it on page reload diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java b/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java index e3186cc1d99..06af294a4f0 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/model/TileSource.java @@ -26,7 +26,8 @@ public String type() { * Represents a raster-based source for map tiles. These are used mainly for background * map layers with vector data being rendered on top of it. */ - record RasterSource(String id, List tiles, int tileSize, String attribution) implements TileSource { + record RasterSource(String id, List tiles, int tileSize, String attribution) + implements TileSource { @Override public String type() { return "raster"; From 1cbce1fcd83b0af48f8f9d5cc62c522ce621fbea Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 2 Jan 2024 22:15:40 +0100 Subject: [PATCH 16/25] Use optional chaining --- client-next/src/components/MapView/MapView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client-next/src/components/MapView/MapView.tsx b/client-next/src/components/MapView/MapView.tsx index 9ecc35c27aa..95c898c4a28 100644 --- a/client-next/src/components/MapView/MapView.tsx +++ b/client-next/src/components/MapView/MapView.tsx @@ -76,7 +76,7 @@ export function MapView({ onClose={() => setShowContextPopup(null)} /> )} - {showPropsPopup && showPropsPopup.feature && showPropsPopup.feature.properties && ( + {showPropsPopup?.feature?.properties && ( Date: Tue, 9 Jan 2024 12:31:29 +0100 Subject: [PATCH 17/25] Rename the feature flag DebugClient to DebugUi, remove separate one for the debug tiles --- docs/Configuration.md | 63 +++++++++---------- .../api/configuration/APIEndpoints.java | 6 +- .../framework/application/OTPFeature.java | 23 ++++--- .../standalone/server/GrizzlyServer.java | 2 +- 4 files changed, 50 insertions(+), 44 deletions(-) diff --git a/docs/Configuration.md b/docs/Configuration.md index f1c0af287ab..7a81e68fb4a 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -219,38 +219,37 @@ Here is a list of all features which can be toggled on/off and their default val -| Feature | Description | Enabled by default | Sandbox | -|--------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------:|:-------:| -| `APIBikeRental` | Enable the bike rental endpoint. | ✓️ | | -| `APIServerInfo` | Enable the server info endpoint. | ✓️ | | -| `APIGraphInspectorTile` | Enable the inspector endpoint for graph information for inspection/debugging purpose. | ✓️ | | -| `APIUpdaterStatus` | Enable endpoint for graph updaters status. | ✓️ | | -| `ConsiderPatternsForDirectTransfers` | Enable limiting transfers so that there is only a single transfer to each pattern. | ✓️ | | -| `DebugClient` | Enable the debug web client located at the root of the web server. | ✓️ | | -| `FloatingBike` | Enable floating bike routing. | ✓️ | | -| `GtfsGraphQlApi` | Enable GTFS GraphQL API. | ✓️ | | -| `GtfsGraphQlApiRentalStationFuzzyMatching` | Does vehicleRentalStation query also allow ids that are not feed scoped. | | | -| `MinimumTransferTimeIsDefinitive` | If the minimum transfer time is a lower bound (default) or the definitive time for the transfer. Set this to `true` if you want to set a transfer time lower than what OTP derives from OSM data. | | | -| `OptimizeTransfers` | OTP will inspect all itineraries found and optimize where (which stops) the transfer will happen. Waiting time, priority and guaranteed transfers are taken into account. | ✓️ | | -| `ParallelRouting` | Enable performing parts of the trip planning in parallel. | | | -| `TransferConstraints` | Enforce transfers to happen according to the _transfers.txt_ (GTFS) and Interchanges (NeTEx). Turning this _off_ will increase the routing performance a little. | ✓️ | | -| `TransmodelGraphQlApi` | Enable Transmodel (NeTEx) GraphQL API. | ✓️ | ✓️ | -| `ActuatorAPI` | Endpoint for actuators (service health status). | | ✓️ | -| `AsyncGraphQLFetchers` | Whether the @async annotation in the GraphQL schema should lead to the fetch being executed asynchronously. This allows batch or alias queries to run in parallel at the cost of consuming extra threads. | | | -| `Co2Emissions` | Enable the emissions sandbox module. | | ✓️ | -| `DataOverlay` | Enable usage of data overlay when calculating costs for the street network. | | ✓️ | -| `FaresV2` | Enable import of GTFS-Fares v2 data. | | ✓️ | -| `FlexRouting` | Enable FLEX routing. | | ✓️ | -| `GoogleCloudStorage` | Enable Google Cloud Storage integration. | | ✓️ | -| `RealtimeResolver` | When routing with ignoreRealtimeUpdates=true, add an extra step which populates results with real-time data | | ✓️ | -| `ReportApi` | Enable the report API. | | ✓️ | -| `RestAPIPassInDefaultConfigAsJson` | Enable a default RouteRequest to be passed in as JSON on the REST API - FOR DEBUGGING ONLY! | | | -| `SandboxAPIGeocoder` | Enable the Geocoder API. | | ✓️ | -| `SandboxAPIMapboxVectorTilesApi` | Enable Mapbox vector tiles API. | | ✓️ | -| `SandboxAPIParkAndRideApi` | Enable park-and-ride endpoint. | | ✓️ | -| `SandboxAPITravelTime` | Enable the isochrone/travel time surface API. | | ✓️ | -| `TransferAnalyzer` | Analyze transfers during graph build. | | ✓️ | -| `VehicleToStopHeuristics` | Enable improved heuristic for park-and-ride queries. | | ✓️ | +| Feature | Description | Enabled by default | Sandbox | +|--------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------:|:-------:| +| `APIBikeRental` | Enable the bike rental endpoint. | ✓️ | | +| `APIServerInfo` | Enable the server info endpoint. | ✓️ | | +| `APIUpdaterStatus` | Enable endpoint for graph updaters status. | ✓️ | | +| `ConsiderPatternsForDirectTransfers` | Enable limiting transfers so that there is only a single transfer to each pattern. | ✓️ | | +| `DebugUi` | Enable the debug GraphQL client and web UI and located at the root of the web server as well as the debug map tiles it uses. Be aware that the map tiles are not a stable API and can change without notice. Use the [vector tiles feature if](sandbox/MapboxVectorTilesApi.md) you want a stable map tiles API. | ✓️ | | +| `FloatingBike` | Enable floating bike routing. | ✓️ | | +| `GtfsGraphQlApi` | Enable the [GTFS GraphQL API](apis/GTFS-GraphQL-API.md). | ✓️ | | +| `GtfsGraphQlApiRentalStationFuzzyMatching` | Does vehicleRentalStation query also allow ids that are not feed scoped. | | | +| `MinimumTransferTimeIsDefinitive` | If the minimum transfer time is a lower bound (default) or the definitive time for the transfer. Set this to `true` if you want to set a transfer time lower than what OTP derives from OSM data. | | | +| `OptimizeTransfers` | OTP will inspect all itineraries found and optimize where (which stops) the transfer will happen. Waiting time, priority and guaranteed transfers are taken into account. | ✓️ | | +| `ParallelRouting` | Enable performing parts of the trip planning in parallel. | | | +| `TransferConstraints` | Enforce transfers to happen according to the _transfers.txt_ (GTFS) and Interchanges (NeTEx). Turning this _off_ will increase the routing performance a little. | ✓️ | | +| `TransmodelGraphQlApi` | Enable the [Transmodel (NeTEx) GraphQL API](apis/TransmodelApi.md). | ✓️ | ✓️ | +| `ActuatorAPI` | Endpoint for actuators (service health status). | | ✓️ | +| `AsyncGraphQLFetchers` | Whether the @async annotation in the GraphQL schema should lead to the fetch being executed asynchronously. This allows batch or alias queries to run in parallel at the cost of consuming extra threads. | | | +| `Co2Emissions` | Enable the emissions sandbox module. | | ✓️ | +| `DataOverlay` | Enable usage of data overlay when calculating costs for the street network. | | ✓️ | +| `FaresV2` | Enable import of GTFS-Fares v2 data. | | ✓️ | +| `FlexRouting` | Enable FLEX routing. | | ✓️ | +| `GoogleCloudStorage` | Enable Google Cloud Storage integration. | | ✓️ | +| `RealtimeResolver` | When routing with ignoreRealtimeUpdates=true, add an extra step which populates results with real-time data | | ✓️ | +| `ReportApi` | Enable the report API. | | ✓️ | +| `RestAPIPassInDefaultConfigAsJson` | Enable a default RouteRequest to be passed in as JSON on the REST API - FOR DEBUGGING ONLY! | | | +| `SandboxAPIGeocoder` | Enable the Geocoder API. | | ✓️ | +| `SandboxAPIMapboxVectorTilesApi` | Enable Mapbox vector tiles API. | | ✓️ | +| `SandboxAPIParkAndRideApi` | Enable park-and-ride endpoint. | | ✓️ | +| `SandboxAPITravelTime` | Enable the isochrone/travel time surface API. | | ✓️ | +| `TransferAnalyzer` | Analyze transfers during graph build. | | ✓️ | +| `VehicleToStopHeuristics` | Enable improved heuristic for park-and-ride queries. | | ✓️ | diff --git a/src/main/java/org/opentripplanner/api/configuration/APIEndpoints.java b/src/main/java/org/opentripplanner/api/configuration/APIEndpoints.java index 64bbb2896a2..79556302f04 100644 --- a/src/main/java/org/opentripplanner/api/configuration/APIEndpoints.java +++ b/src/main/java/org/opentripplanner/api/configuration/APIEndpoints.java @@ -1,10 +1,10 @@ package org.opentripplanner.api.configuration; import static org.opentripplanner.framework.application.OTPFeature.APIBikeRental; -import static org.opentripplanner.framework.application.OTPFeature.APIGraphInspectorTile; import static org.opentripplanner.framework.application.OTPFeature.APIServerInfo; import static org.opentripplanner.framework.application.OTPFeature.APIUpdaterStatus; import static org.opentripplanner.framework.application.OTPFeature.ActuatorAPI; +import static org.opentripplanner.framework.application.OTPFeature.DebugUi; import static org.opentripplanner.framework.application.OTPFeature.GtfsGraphQlApi; import static org.opentripplanner.framework.application.OTPFeature.ReportApi; import static org.opentripplanner.framework.application.OTPFeature.SandboxAPIGeocoder; @@ -51,10 +51,10 @@ private APIEndpoints() { // Add feature enabled APIs, these can be enabled by default, some is not. // See the OTPFeature enum for details. addIfEnabled(APIBikeRental, BikeRental.class); - addIfEnabled(APIGraphInspectorTile, GraphInspectorTileResource.class); - addIfEnabled(APIGraphInspectorTile, GraphInspectorVectorTileResource.class); addIfEnabled(APIServerInfo, ServerInfo.class); addIfEnabled(APIUpdaterStatus, UpdaterStatusResource.class); + addIfEnabled(DebugUi, GraphInspectorTileResource.class); + addIfEnabled(DebugUi, GraphInspectorVectorTileResource.class); addIfEnabled(GtfsGraphQlApi, GtfsGraphQLAPI.class); addIfEnabled(TransmodelGraphQlApi, TransmodelAPI.class); diff --git a/src/main/java/org/opentripplanner/framework/application/OTPFeature.java b/src/main/java/org/opentripplanner/framework/application/OTPFeature.java index 05d1284a883..308710ef5a0 100644 --- a/src/main/java/org/opentripplanner/framework/application/OTPFeature.java +++ b/src/main/java/org/opentripplanner/framework/application/OTPFeature.java @@ -16,20 +16,23 @@ public enum OTPFeature { APIBikeRental(true, false, "Enable the bike rental endpoint."), APIServerInfo(true, false, "Enable the server info endpoint."), - APIGraphInspectorTile( - true, - false, - "Enable the inspector endpoint for graph information for inspection/debugging purpose." - ), APIUpdaterStatus(true, false, "Enable endpoint for graph updaters status."), ConsiderPatternsForDirectTransfers( true, false, "Enable limiting transfers so that there is only a single transfer to each pattern." ), - DebugClient(true, false, "Enable the debug web client located at the root of the web server."), + DebugUi( + true, + false, + """ + Enable the debug GraphQL client and web UI and located at the root of the web server as well as the debug map tiles it uses. + Be aware that the map tiles are not a stable API and can change without notice. + Use the [vector tiles feature if](sandbox/MapboxVectorTilesApi.md) you want a stable map tiles API. + """ + ), FloatingBike(true, false, "Enable floating bike routing."), - GtfsGraphQlApi(true, false, "Enable GTFS GraphQL API."), + GtfsGraphQlApi(true, false, "Enable the [GTFS GraphQL API](apis/GTFS-GraphQL-API.md)."), GtfsGraphQlApiRentalStationFuzzyMatching( false, false, @@ -63,7 +66,11 @@ public enum OTPFeature { false, "Enforce transfers to happen according to the _transfers.txt_ (GTFS) and Interchanges (NeTEx). Turning this _off_ will increase the routing performance a little." ), - TransmodelGraphQlApi(true, true, "Enable Transmodel (NeTEx) GraphQL API."), + TransmodelGraphQlApi( + true, + true, + "Enable the [Transmodel (NeTEx) GraphQL API](apis/TransmodelApi.md)." + ), /* Sandbox extension features - Must be turned OFF by default */ diff --git a/src/main/java/org/opentripplanner/standalone/server/GrizzlyServer.java b/src/main/java/org/opentripplanner/standalone/server/GrizzlyServer.java index c422e9c24f3..7dc7c87f735 100644 --- a/src/main/java/org/opentripplanner/standalone/server/GrizzlyServer.java +++ b/src/main/java/org/opentripplanner/standalone/server/GrizzlyServer.java @@ -102,7 +102,7 @@ public void run() { httpServer.getServerConfiguration().addHttpHandler(dynamicHandler, "/otp/"); /* 2. A static content handler to serve the client JS apps etc. from the classpath. */ - if (OTPFeature.DebugClient.isOn()) { + if (OTPFeature.DebugUi.isOn()) { CLStaticHttpHandler staticHandler = new CLStaticHttpHandler( GrizzlyServer.class.getClassLoader(), "/client/" From 4b9889101a59b4cfce3704a7e6e23db8315f7b25 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 9 Jan 2024 12:49:06 +0100 Subject: [PATCH 18/25] Update comment --- .../inspector/vector/stop/StopLayerBuilder.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/inspector/vector/stop/StopLayerBuilder.java b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLayerBuilder.java index 40784ab5b3b..70ce6a58735 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/stop/StopLayerBuilder.java +++ b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLayerBuilder.java @@ -8,11 +8,14 @@ import org.locationtech.jts.geom.Geometry; import org.opentripplanner.inspector.vector.LayerBuilder; import org.opentripplanner.inspector.vector.LayerParameters; +import org.opentripplanner.transit.model.site.AreaStop; import org.opentripplanner.transit.model.site.RegularStop; import org.opentripplanner.transit.model.site.StopLocation; /** - * A vector tile layer containing all {@link RegularStop}s inside the vector tile bounds. + * A vector tile layer for {@link StopLocation}s inside the vector tile bounds. These can be further + * filtered to get only a subset of stop implementations like {@link RegularStop} + * or {@link AreaStop}. */ public class StopLayerBuilder extends LayerBuilder { From 2b65d5702838d92a71a84923fb81afd8eb765a5c Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 9 Jan 2024 13:14:20 +0100 Subject: [PATCH 19/25] Make mapStyle configurable --- client-next/.env | 3 ++- client-next/.env.development | 3 ++- client-next/src/components/MapView/MapView.tsx | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/client-next/.env b/client-next/.env index 003970b4e1f..e8a9667bc23 100644 --- a/client-next/.env +++ b/client-next/.env @@ -1 +1,2 @@ -VITE_API_URL=/otp/routers/default/transmodel/index/graphql \ No newline at end of file +VITE_API_URL=/otp/routers/default/transmodel/index/graphql +VITE_DEBUG_STYLE_URL=/otp/routers/default/inspector/vectortile/style.json diff --git a/client-next/.env.development b/client-next/.env.development index e11b45c4411..b10ac31fdf9 100644 --- a/client-next/.env.development +++ b/client-next/.env.development @@ -1 +1,2 @@ -VITE_API_URL=http://localhost:8080/otp/routers/default/transmodel/index/graphql \ No newline at end of file +VITE_API_URL=http://localhost:8080/otp/routers/default/transmodel/index/graphql +VITE_DEBUG_STYLE_URL=http://localhost:8080/otp/routers/default/inspector/vectortile/style.json \ No newline at end of file diff --git a/client-next/src/components/MapView/MapView.tsx b/client-next/src/components/MapView/MapView.tsx index 95c898c4a28..e401b1756e6 100644 --- a/client-next/src/components/MapView/MapView.tsx +++ b/client-next/src/components/MapView/MapView.tsx @@ -15,6 +15,8 @@ const initialViewState = { zoom: 4, }; +const styleUrl = import.meta.env.VITE_DEBUG_STYLE_URL; + type PopupData = { coordinates: LngLat; feature: MapboxGeoJSONFeature }; export function MapView({ @@ -40,7 +42,7 @@ export function MapView({ // @ts-ignore mapLib={import('maplibre-gl')} // @ts-ignore - mapStyle="http://localhost:8080/otp/routers/default/inspector/vectortile/style.json" + mapStyle={styleUrl} initialViewState={initialViewState} onDblClick={onMapDoubleClick} onContextMenu={(e) => { From 756a2890d67f805111250364d6822962fb0c7ae9 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Tue, 9 Jan 2024 13:16:58 +0100 Subject: [PATCH 20/25] Use proper copyright symbol --- .../org/opentripplanner/apis/vectortiles/DebugStyleSpec.java | 2 +- .../resources/org/opentripplanner/apis/vectortiles/style.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java b/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java index 9a4fe9be123..ff933901cf8 100644 --- a/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java +++ b/src/main/java/org/opentripplanner/apis/vectortiles/DebugStyleSpec.java @@ -17,7 +17,7 @@ public class DebugStyleSpec { "background", List.of("https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"), 256, - "© OpenStreetMap Contributors" + "© OpenStreetMap Contributors" ); public record VectorSourceLayer(VectorSource vectorSource, String vectorLayer) {} diff --git a/src/test/resources/org/opentripplanner/apis/vectortiles/style.json b/src/test/resources/org/opentripplanner/apis/vectortiles/style.json index 6f95471a667..f5bb18f6f6a 100644 --- a/src/test/resources/org/opentripplanner/apis/vectortiles/style.json +++ b/src/test/resources/org/opentripplanner/apis/vectortiles/style.json @@ -7,7 +7,7 @@ "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png" ], "tileSize": 256, - "attribution" : "© OpenStreetMap Contributors", + "attribution" : "© OpenStreetMap Contributors", "type": "raster" }, "vectorSource": { From 5972e5d4260192621c62be4019c63f71f327c005 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Thu, 11 Jan 2024 10:26:37 +0100 Subject: [PATCH 21/25] Resolve merge artifacts --- .../inspector/vector/stop/StopLocationPropertyMapper.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java index 44729bcb407..ab9685dd0f6 100644 --- a/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java +++ b/src/main/java/org/opentripplanner/inspector/vector/stop/StopLocationPropertyMapper.java @@ -5,13 +5,13 @@ import java.util.Collection; import java.util.List; import java.util.Locale; -import org.opentripplanner.api.mapping.I18NStringMapper; -import org.opentripplanner.api.mapping.PropertyMapper; +import org.opentripplanner.apis.support.mapping.PropertyMapper; +import org.opentripplanner.framework.i18n.I18NStringMapper; import org.opentripplanner.inspector.vector.KeyValue; import org.opentripplanner.transit.model.site.StopLocation; /** - * A {@link PropertyMapper} for the {@link AreaStopsLayerBuilder} for the OTP debug client. + * A {@link PropertyMapper} for the {@link StopLocationPropertyMapper} for the OTP debug client. */ public class StopLocationPropertyMapper extends PropertyMapper { From 4fd4325127655df8f0fb7c0ea26a672b961e7e2d Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Thu, 11 Jan 2024 10:27:32 +0100 Subject: [PATCH 22/25] Update docs --- docs/Configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Configuration.md b/docs/Configuration.md index b376b6b91dc..d43ff150926 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -241,7 +241,7 @@ Here is a list of all features which can be toggled on/off and their default val | `FaresV2` | Enable import of GTFS-Fares v2 data. | | ✓️ | | `FlexRouting` | Enable FLEX routing. | | ✓️ | | `GoogleCloudStorage` | Enable Google Cloud Storage integration. | | ✓️ | -| `LegacyRestApi` | Enable legacy REST API. This API will be removed in the future. | ✓️ | ✓️ | +| `LegacyRestApi` | Enable legacy REST API. This API will be removed in the future. | ✓️ | ✓️ | | `RealtimeResolver` | When routing with ignoreRealtimeUpdates=true, add an extra step which populates results with real-time data | | ✓️ | | `ReportApi` | Enable the report API. | | ✓️ | | `RestAPIPassInDefaultConfigAsJson` | Enable a default RouteRequest to be passed in as JSON on the REST API - FOR DEBUGGING ONLY! | | | From c5dc28984a83a968660c2478c2a6b3301fa7a6d4 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Thu, 11 Jan 2024 12:14:00 +0100 Subject: [PATCH 23/25] Apply review feedback --- .../MapView/GeometryPropertyPopup.tsx | 27 ++++++++++++ .../src/components/MapView/MapView.tsx | 43 +++++++++---------- 2 files changed, 48 insertions(+), 22 deletions(-) create mode 100644 client-next/src/components/MapView/GeometryPropertyPopup.tsx diff --git a/client-next/src/components/MapView/GeometryPropertyPopup.tsx b/client-next/src/components/MapView/GeometryPropertyPopup.tsx new file mode 100644 index 00000000000..d2b55689270 --- /dev/null +++ b/client-next/src/components/MapView/GeometryPropertyPopup.tsx @@ -0,0 +1,27 @@ +import { LngLat, Popup } from 'react-map-gl'; +import { Table } from 'react-bootstrap'; + +export function GeometryPropertyPopup({ + coordinates, + properties, + onClose, +}: { + coordinates: LngLat; + properties: { [s: string]: string }; + onClose: () => void; +}) { + return ( + onClose()}> + + + {Object.entries(properties).map(([key, value]) => ( + + + + + ))} + +
{key}{value}
+
+ ); +} diff --git a/client-next/src/components/MapView/MapView.tsx b/client-next/src/components/MapView/MapView.tsx index e401b1756e6..1b17e31cb88 100644 --- a/client-next/src/components/MapView/MapView.tsx +++ b/client-next/src/components/MapView/MapView.tsx @@ -1,4 +1,4 @@ -import { LngLat, Map, MapboxGeoJSONFeature, NavigationControl, Popup } from 'react-map-gl'; +import { LngLat, Map, MapboxGeoJSONFeature, NavigationControl } from 'react-map-gl'; import 'maplibre-gl/dist/maplibre-gl.css'; import { TripPattern, TripQuery, TripQueryVariables } from '../../gql/graphql.ts'; import { NavigationMarkers } from './NavigationMarkers.tsx'; @@ -6,7 +6,7 @@ import { LegLines } from './LegLines.tsx'; import { useMapDoubleClick } from './useMapDoubleClick.ts'; import { useState } from 'react'; import { ContextMenuPopup } from './ContextMenuPopup.tsx'; -import { Table } from 'react-bootstrap'; +import { GeometryPropertyPopup } from './GeometryPropertyPopup.tsx'; // TODO: this should be configurable const initialViewState = { @@ -35,6 +35,20 @@ export function MapView({ const onMapDoubleClick = useMapDoubleClick({ tripQueryVariables, setTripQueryVariables }); const [showContextPopup, setShowContextPopup] = useState(null); const [showPropsPopup, setShowPropsPopup] = useState(null); + const showFeaturePropPopup = ( + e: mapboxgl.MapMouseEvent & { + features?: mapboxgl.MapboxGeoJSONFeature[] | undefined; + }, + setShowPropsPopup: (value: ((prevState: PopupData | null) => PopupData | null) | PopupData | null) => void, + ) => { + if (e.features) { + // if you click on a cluster of map features it's possible that there are multiple + // to select from. we are using the first one instead of presenting a selection UI. + // you can always zoom in closer if you want to make a more specific click. + const feature = e.features[0]; + setShowPropsPopup({ coordinates: e.lngLat, feature: feature }); + } + }; return (

@@ -50,10 +64,7 @@ export function MapView({ }} interactiveLayerIds={['regular-stop']} onClick={(e) => { - if (e.features) { - const props = e.features[0]; - setShowPropsPopup({ coordinates: e.lngLat, feature: props }); - } + showFeaturePropPopup(e, setShowPropsPopup); }} // put lat/long in URL and pan to it on page reload hash={true} @@ -79,23 +90,11 @@ export function MapView({ /> )} {showPropsPopup?.feature?.properties && ( - setShowPropsPopup(null)} - > - - - {Object.entries(showPropsPopup.feature.properties).map(([key, value]) => ( - - - - - ))} - -
{key}{value}
-
+ /> )}
From 24d5929747795ab39bb820683ceb3d51a6fabeea Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Thu, 11 Jan 2024 14:33:38 +0100 Subject: [PATCH 24/25] Remove extra function definition --- client-next/src/components/MapView/MapView.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client-next/src/components/MapView/MapView.tsx b/client-next/src/components/MapView/MapView.tsx index 1b17e31cb88..57e718ff187 100644 --- a/client-next/src/components/MapView/MapView.tsx +++ b/client-next/src/components/MapView/MapView.tsx @@ -39,7 +39,6 @@ export function MapView({ e: mapboxgl.MapMouseEvent & { features?: mapboxgl.MapboxGeoJSONFeature[] | undefined; }, - setShowPropsPopup: (value: ((prevState: PopupData | null) => PopupData | null) | PopupData | null) => void, ) => { if (e.features) { // if you click on a cluster of map features it's possible that there are multiple @@ -64,7 +63,7 @@ export function MapView({ }} interactiveLayerIds={['regular-stop']} onClick={(e) => { - showFeaturePropPopup(e, setShowPropsPopup); + showFeaturePropPopup(e); }} // put lat/long in URL and pan to it on page reload hash={true} From cf5d875fbf4dd003023e4a506ac8a84d0175d8a7 Mon Sep 17 00:00:00 2001 From: Leonard Ehrenfried Date: Thu, 11 Jan 2024 15:50:30 +0100 Subject: [PATCH 25/25] Remove extra method call indirection --- client-next/src/components/MapView/MapView.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client-next/src/components/MapView/MapView.tsx b/client-next/src/components/MapView/MapView.tsx index 57e718ff187..5b6223a5dee 100644 --- a/client-next/src/components/MapView/MapView.tsx +++ b/client-next/src/components/MapView/MapView.tsx @@ -62,9 +62,7 @@ export function MapView({ setShowContextPopup(e.lngLat); }} interactiveLayerIds={['regular-stop']} - onClick={(e) => { - showFeaturePropPopup(e); - }} + onClick={showFeaturePropPopup} // put lat/long in URL and pan to it on page reload hash={true} // disable pitching and rotating the map