diff --git a/src/main/java/org/opentripplanner/api/model/TripPlan.java b/src/main/java/org/opentripplanner/api/model/TripPlan.java index e460f1ff918..70dc4b4ab2c 100644 --- a/src/main/java/org/opentripplanner/api/model/TripPlan.java +++ b/src/main/java/org/opentripplanner/api/model/TripPlan.java @@ -16,10 +16,13 @@ the License, or (at your option) any later version. import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; import javax.xml.bind.annotation.XmlElementWrapper; import com.fasterxml.jackson.annotation.JsonProperty; +import org.opentripplanner.api.model.alertpatch.LocalizedAlert; +import org.opentripplanner.routing.alertpatch.Alert; /** * A TripPlan is a set of ways to get from point A to point B at time T. @@ -40,6 +43,8 @@ public class TripPlan { @JsonProperty(value="itineraries") public List itinerary = new ArrayList(); + public List alerts; + public TripPlan() { } public TripPlan(Place from, Place to, Date date) { @@ -51,4 +56,12 @@ public TripPlan(Place from, Place to, Date date) { public void addItinerary(Itinerary itinerary) { this.itinerary.add(itinerary); } + + public void addAlert(Alert alert, Locale locale) { + if (alerts == null) { + alerts = new ArrayList<>(); + } + LocalizedAlert la = new LocalizedAlert(alert, locale); + alerts.add(la); + } } diff --git a/src/main/java/org/opentripplanner/api/resource/GraphPathToTripPlanConverter.java b/src/main/java/org/opentripplanner/api/resource/GraphPathToTripPlanConverter.java index 21126dd52ec..7e6fe79b679 100644 --- a/src/main/java/org/opentripplanner/api/resource/GraphPathToTripPlanConverter.java +++ b/src/main/java/org/opentripplanner/api/resource/GraphPathToTripPlanConverter.java @@ -124,6 +124,11 @@ public static TripPlan generatePlan(List paths, RoutingRequest reques lastLeg.to.orig = plan.to.orig; } } + + if (request.rctx.graph.outOfAreaNotesService != null) { + addOutOfAreaWarnings(plan, request, requestedLocale); + } + request.rctx.debugOutput.finishedRendering(); return plan; } @@ -1157,4 +1162,10 @@ private static List> encodeElevationProfile(Edge edge, double distanc return out; } + private static void addOutOfAreaWarnings(TripPlan plan, RoutingRequest request, Locale locale) { + for (Alert alert : request.rctx.graph.outOfAreaNotesService.getAlerts(request)) { + plan.addAlert(alert, locale); + } + } + } diff --git a/src/main/java/org/opentripplanner/graph_builder/GraphBuilder.java b/src/main/java/org/opentripplanner/graph_builder/GraphBuilder.java index e82b014b494..a2aa37053d7 100644 --- a/src/main/java/org/opentripplanner/graph_builder/GraphBuilder.java +++ b/src/main/java/org/opentripplanner/graph_builder/GraphBuilder.java @@ -20,6 +20,7 @@ the License, or (at your option) any later version. import org.opentripplanner.graph_builder.module.EmbedConfig; import org.opentripplanner.graph_builder.module.FlexDirectTransferGenerator; import org.opentripplanner.graph_builder.module.GtfsModule; +import org.opentripplanner.graph_builder.module.OutOfAreaModule; import org.opentripplanner.graph_builder.module.PruneFloatingIslands; import org.opentripplanner.graph_builder.module.StreetLinkerModule; import org.opentripplanner.graph_builder.module.TransitToTaggedStopsModule; @@ -188,6 +189,7 @@ public static GraphBuilder forDirectory(CommandLineParameters params, File dir) JsonNode builderConfig = null; JsonNode routerConfig = null; File demFile = null; + File boundaryFile = null; LOG.info("Searching for graph builder input files in {}", dir); if ( ! dir.isDirectory() && dir.canRead()) { LOG.error("'{}' is not a readable directory.", dir); @@ -218,6 +220,10 @@ public static GraphBuilder forDirectory(CommandLineParameters params, File dir) LOG.info("Skipping DEM file {}", file); } break; + case GEOJSON: + LOG.info("Found geojson area file {}", file); + boundaryFile = file; + break; case OTHER: LOG.warn("Skipping unrecognized file '{}'", file); } @@ -320,6 +326,10 @@ public static GraphBuilder forDirectory(CommandLineParameters params, File dir) if (builderParams.htmlAnnotations) { graphBuilder.addModule(new AnnotationsToHTML(params.build, builderParams.maxHtmlAnnotationsPerFile)); } + if (boundaryFile != null) { + graphBuilder.addModule(new OutOfAreaModule(boundaryFile, builderParams.fromPlaceOutOfAreaMessage, + builderParams.toPlaceOutOfAreaMessage)); + } graphBuilder.serializeGraph = ( ! params.inMemory ) || params.preFlight; return graphBuilder; } @@ -330,7 +340,7 @@ public static GraphBuilder forDirectory(CommandLineParameters params, File dir) * types are present. This helps point out when config files have been misnamed (builder-config vs. build-config). */ private static enum InputFileType { - GTFS, OSM, DEM, CONFIG, GRAPH, OTHER; + GTFS, OSM, DEM, CONFIG, GRAPH, GEOJSON, OTHER; public static InputFileType forFile(File file) { String name = file.getName(); if (name.endsWith(".zip")) { @@ -346,6 +356,7 @@ public static InputFileType forFile(File file) { if (name.endsWith(".osm.xml")) return OSM; if (name.endsWith(".tif") || name.endsWith(".tiff")) return DEM; // Digital elevation model (elevation raster) if (name.equals("Graph.obj")) return GRAPH; + if (name.endsWith(".geojson")) return GEOJSON; if (name.equals(GraphBuilder.BUILDER_CONFIG_FILENAME) || name.equals(Router.ROUTER_CONFIG_FILENAME)) { return CONFIG; } diff --git a/src/main/java/org/opentripplanner/graph_builder/module/OutOfAreaModule.java b/src/main/java/org/opentripplanner/graph_builder/module/OutOfAreaModule.java new file mode 100644 index 00000000000..d278f9e235e --- /dev/null +++ b/src/main/java/org/opentripplanner/graph_builder/module/OutOfAreaModule.java @@ -0,0 +1,58 @@ +/* This program is free software: you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ +package org.opentripplanner.graph_builder.module; + +import com.conveyal.geojson.GeoJsonModule; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.vividsolutions.jts.geom.Geometry; +import org.opentripplanner.graph_builder.services.GraphBuilderModule; +import org.opentripplanner.routing.graph.Graph; +import org.opentripplanner.routing.services.notes.OutOfAreaNotesService; + +import java.io.File;; +import java.io.IOException; +import java.util.HashMap; + +public class OutOfAreaModule implements GraphBuilderModule { + + private File geojsonFile; + + private String startMessage, endMessage; + + public OutOfAreaModule(File geojsonFile, String startMessage, String endMessage) { + this.geojsonFile = geojsonFile; + this.startMessage = startMessage; + this.endMessage = endMessage; + } + + @Override + public void buildGraph(Graph graph, HashMap, Object> extra) { + Geometry area; + try { + area = new ObjectMapper().registerModule(new GeoJsonModule()) + .readValue(geojsonFile, Geometry.class); + } catch(IOException e) { + e.printStackTrace(); + return; + } + OutOfAreaNotesService svc = new OutOfAreaNotesService(); + svc.setArea(area); + svc.setStartLocationMessage(startMessage); + svc.setEndLocationMessage(endMessage); + graph.outOfAreaNotesService = svc; + } + + @Override + public void checkInputs() { + } +} diff --git a/src/main/java/org/opentripplanner/routing/graph/Graph.java b/src/main/java/org/opentripplanner/routing/graph/Graph.java index 49198e10402..8994037ba69 100644 --- a/src/main/java/org/opentripplanner/routing/graph/Graph.java +++ b/src/main/java/org/opentripplanner/routing/graph/Graph.java @@ -49,6 +49,7 @@ the License, or (at your option) any later version. import org.opentripplanner.routing.impl.DefaultStreetVertexIndexFactory; import org.opentripplanner.routing.services.StreetVertexIndexFactory; import org.opentripplanner.routing.services.StreetVertexIndexService; +import org.opentripplanner.routing.services.notes.OutOfAreaNotesService; import org.opentripplanner.routing.services.notes.StreetNotesService; import org.opentripplanner.routing.trippattern.Deduplicator; import org.opentripplanner.routing.vertextype.PatternArriveVertex; @@ -116,6 +117,8 @@ public class Graph implements Serializable { private transient SampleFactory sampleFactory; + public OutOfAreaNotesService outOfAreaNotesService; + public final Deduplicator deduplicator = new Deduplicator(); /** diff --git a/src/main/java/org/opentripplanner/routing/services/notes/OutOfAreaNotesService.java b/src/main/java/org/opentripplanner/routing/services/notes/OutOfAreaNotesService.java new file mode 100644 index 00000000000..91ed8c7f4eb --- /dev/null +++ b/src/main/java/org/opentripplanner/routing/services/notes/OutOfAreaNotesService.java @@ -0,0 +1,59 @@ +/* This program is free software: you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ +package org.opentripplanner.routing.services.notes; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Point; +import org.opentripplanner.common.geometry.GeometryUtils; +import org.opentripplanner.routing.alertpatch.Alert; +import org.opentripplanner.routing.core.RoutingRequest; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; + +public class OutOfAreaNotesService implements Serializable { + + private static final long serialVersionUID = 1; + + private Geometry area; + + private String startLocationMessage; + + private String endLocationMessage; + + public void setArea(Geometry area) { + this.area = area; + } + + public void setStartLocationMessage(String startLocationMessage) { + this.startLocationMessage = startLocationMessage; + } + + public void setEndLocationMessage(String endLocationMessage) { + this.endLocationMessage = endLocationMessage; + } + + public Collection getAlerts(RoutingRequest request) { + Point fromPoint = GeometryUtils.getGeometryFactory().createPoint(request.rctx.fromVertex.getCoordinate()); + Point toPoint = GeometryUtils.getGeometryFactory().createPoint(request.rctx.toVertex.getCoordinate()); + Collection alerts = new ArrayList<>(); + if (!area.contains(fromPoint)) { + alerts.add(Alert.createSimpleAlerts(startLocationMessage)); + } + if (!area.contains(toPoint)) { + alerts.add(Alert.createSimpleAlerts(endLocationMessage)); + } + return alerts; + } +} diff --git a/src/main/java/org/opentripplanner/standalone/GraphBuilderParameters.java b/src/main/java/org/opentripplanner/standalone/GraphBuilderParameters.java index b652311b0c8..5f6a572ec7b 100644 --- a/src/main/java/org/opentripplanner/standalone/GraphBuilderParameters.java +++ b/src/main/java/org/opentripplanner/standalone/GraphBuilderParameters.java @@ -148,6 +148,16 @@ public class GraphBuilderParameters { */ public final boolean createFlexTransfers; + /** + * Message for from-place out of area + */ + public final String fromPlaceOutOfAreaMessage; + + /** + * Message for from-place out of area + */ + public final String toPlaceOutOfAreaMessage; + /** * Set all parameters from the given Jackson JSON tree, applying defaults. * Supplying MissingNode.getInstance() will cause all the defaults to be applied. @@ -181,6 +191,8 @@ public GraphBuilderParameters(JsonNode config) { banDiscouragedWalking = config.path("banDiscouragedWalking").asBoolean(false); banDiscouragedBiking = config.path("banDiscouragedBiking").asBoolean(false); createFlexTransfers = config.path("createFlexTransfers").asBoolean(false); + fromPlaceOutOfAreaMessage = config.path("fromPlaceOutOfAreaMessage").asText("From place out of area."); + toPlaceOutOfAreaMessage = config.path("toPlaceOutOfAreaMessage").asText("To place out of area"); } }