J'ai créé mon propre site d'informations sur les transferts (European Continental Railway) en utilisant OpenTripPlanner (OTP) comme moteur de recherche d'itinéraire, mais uniquement avec OTP comme moteur de recherche d'itinéraire. Il semble qu'il n'y ait pas beaucoup d'informations japonaises sur la façon de l'utiliser (bien qu'il n'y ait pas beaucoup d'informations sur l'anglais ...), donc je l'ai résumé sous forme d'article. De plus, étant donné que seules les données horaires sont enregistrées sans enregistrer les données cartographiques, veuillez les utiliser comme référence pour une telle utilisation.
OpenTripPlanner est une application de recherche d'itinéraire intégrée open source. Il est possible de prendre des données OpenStreetMap et GTFS (décrit plus loin) et d'effectuer une recherche d'itinéraire, y compris la marche et les véhicules, ce que l'on appelle le guidage de transfert.
GTFS est un format pour les itinéraires de transport en commun et les informations d'exploitation créé par Google. En un mot, ce sont des données sur les horaires, et ces dernières années, les installations de transport du monde entier ont publié les données sous forme de données ouvertes.
Avant la guerre (vers 1939), quand il n'y avait pas encore de jets, il semble qu'un seul billet pouvait voyager du Japon vers l'Europe en train et en bateau. Nous créons un site de loisir particulièrement inutile et qui peut fournir des informations sur les transferts de train à ces heures. Les données sur les grandes lignes ferroviaires de Tokyo à Londres et Paris (Japon → Corée → ex-Mandchourie → ex-Union soviétique → Pologne → Allemagne → Belgique → Royaume-Uni / France) sont enregistrées en collectant les horaires des chemins de fer du monde entier.
Pour la méthode de lancement d'OTP en tant qu'application Web normale, reportez-vous à d'autres articles, mais cette fois je me concentrerai sur ce qui suit.
--Utilisez OTP comme une bibliothèque Java au lieu d'une application
L'environnement de la version suivante est supposé.
--JDK 1.8 ou supérieur
Créez un projet Maven et ajoutez les informations suivantes au fichier pom.xml. J'ajoute un référentiel car OTP fait référence à différents OSS: OneBusAway et GeoTools.
pom.xml
<repositories>
<repository>
<id>onebusaway-releases</id>
<name>Onebusaway Releases Repo</name>
<url>http://nexus.onebusaway.org/content/repositories/releases/</url>
</repository>
<repository>
<id>osgeo</id>
<name>OSGeo Release Repository</name>
<url>https://repo.osgeo.org/repository/release/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.opentripplanner</groupId>
<artifactId>otp</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>
OTP stocke les routes et les itinéraires de transport et les données d'horaires dans un objet appelé Graph. Cependant, vous devez lire les données GTFS compressées et créer un objet GtfsBundle avant de créer un objet Graph. Étant donné que OTP peut lire plusieurs fichiers GTFS, il est nécessaire de donner à chaque fichier un ID unique. (La partie où feedId est défini)
python
GtfsBundle gtfsBundle = new GtfsBundle(file);
gtfsBundle.setTransfersTxtDefinesStationPaths(true);
GtfsFeedId feedId = new GtfsFeedId.Builder().id("id").build();
gtfsBundle.setFeedId(feedId);
Après avoir fusionné le GtfsBundle créé en une seule liste (gtfsBundles), enregistrez-le dans l'objet Graph.
python
GtfsModule gtfsModule = new GtfsModule(gtfsBundles);
Graph graph = new Graph();
gtfsModule.buildGraph(graph, null);
graph.summarizeBuilderAnnotations();
graph.index(new DefaultStreetVertexIndexFactory());
Tout d'abord, un objet RoutingRequest qui définit des conditions de recherche telles que le lieu de départ, le lieu d'arrivée et l'heure de départ (ou d'arrivée) est généré. Puisqu'il s'agit à l'origine d'une application de recherche d'itinéraire qui utilise des données cartographiques, il est nécessaire de spécifier les coordonnées même à la station.
python
RoutingRequest routingRequest = new RoutingRequest();
routingRequest.setNumItineraries(3); //Nombre de candidats pour les résultats de recherche
//Définir l'heure de référence pour la recherche
LocalDateTime ldt = LocalDateTime.parse("1939-08-01T13:00");
routingRequest.dateTime = ldt.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
routingRequest.setArriveBy(false); //La valeur par défaut est de spécifier l'heure de départ, mais si True, vous pouvez spécifier l'heure d'arrivée.
//Latitude de départ et d'arrivée/Spécifié par la longitude
routingRequest.from = new GenericLocation(35.3369, 139.44699); //Gare de Tsujido
routingRequest.to = new GenericLocation(35.17096, 136.88232); //Gare de Nagoya
routingRequest.ignoreRealtimeUpdates = true; //Ignorer les informations GTFS en temps réel
routingRequest.reverseOptimizing = true; //Recherchez dans la direction opposée des résultats de recherche et recherchez la dernière heure de départ
//Paramètre pour rechercher uniquement avec des données GTFS
routingRequest.setModes(new TraverseModeSet(TraverseMode.TRANSIT));
routingRequest.onlyTransitTrips = true;
//Définir l'objet graphique
routingRequest.setRoutingContext(graph);
Recherche à l'aide de l'objet RoutingReques et de l'objet Graph.
python
Router router = new Router("OTP", graph);
List<GraphPath> paths = new GraphPathFinder(router).getPaths(routingRequest);
TripPlan tripPlan = GraphPathToTripPlanConverter.generatePlan(paths, routingRequest);
Le résultat de la recherche est stocké dans l'objet TripPlan. L'objet Itinerary candidat du résultat de la recherche est stocké dans la Liste obtenue par la propriété d'itinéraire de TripPlan. L'objet Leg de l'information d'itinéraire est stocké dans la liste obtenue par la propriété leg de Itinerary dans l'ordre de transfert.
Août 1939 en utilisant les données GTFS (données horaires de la ligne Tokaido en décembre 1939, il y a environ 80 ans) sur mon site European Continental Railway Explorons l'itinéraire de la gare de Tsujido à la gare de Nagoya à 13h00 le 1er. Le résultat est le suivant. Si vous manquez le train à 13h08 (soit dit en passant, le train régulier à destination de Yonehara), il semble que vous arriverez à Nagoya plus tôt si vous revenez à Yokohama et Ofuna et prenez le train express limité Sakura Shimonoseki et express Osaka. Vous pouvez consulter les horaires de chaque gare en 1939 en cliquant sur le nom de la gare sur chaque plan d'itinéraire dans European Continental Railway. (Gare de Tsujido, Gare de Yokohama, Gare d'Ofuna)
13:08 Départ- 18:28 arrivée(320 minutes)
>Tsujido 13:08 départ-Numazu 14:46 arrivées
>Numazu 15:04 départs-Nagoya 18:28 arrivées
13:18 Départ- 19:00 arrivée(342 minutes)
>Tsujido 13:18 coups-Yokohama 13:50 arrivées
>Yokohama 13:58 départs-Nagoya 19:00 arrivée
14:08 Départ- 19:38 arrivée(330 minutes)
>Tsujido 14:08 départ-Ofuna 14:20 arrivées
>Ofuna 14:26 coups-Nagoya 19:38 arrivées
Le texte complet de cette source ressemble à ceci.
OtpTest.java
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.opentripplanner.api.model.TripPlan;
import org.opentripplanner.api.resource.GraphPathToTripPlanConverter;
import org.opentripplanner.common.model.GenericLocation;
import org.opentripplanner.graph_builder.model.GtfsBundle;
import org.opentripplanner.graph_builder.module.GtfsFeedId;
import org.opentripplanner.graph_builder.module.GtfsModule;
import org.opentripplanner.model.FeedScopedId;
import org.opentripplanner.model.Route;
import org.opentripplanner.model.Stop;
import org.opentripplanner.model.Trip;
import org.opentripplanner.routing.core.RoutingRequest;
import org.opentripplanner.routing.core.TraverseMode;
import org.opentripplanner.routing.core.TraverseModeSet;
import org.opentripplanner.routing.edgetype.TripPattern;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.routing.graph.GraphIndex;
import org.opentripplanner.routing.impl.DefaultStreetVertexIndexFactory;
import org.opentripplanner.routing.impl.GraphPathFinder;
import org.opentripplanner.routing.spt.GraphPath;
import org.opentripplanner.standalone.Router;
public class OtpTest {
public static void main(String[] args) {
//Chemin du dossier de sauvegarde du fichier GTFS
String in = "";
//Lire tous les fichiers ZIP du dossier sous forme de fichiers GTFS
List<GtfsBundle> gtfsBundles = null;
try (final Stream<Path> pathStream = Files.list(Paths.get(in))) {
gtfsBundles = pathStream.map(Path::toFile).filter(file -> file.getName().toLowerCase().endsWith(".zip"))
.map(file -> {
GtfsBundle gtfsBundle = new GtfsBundle(file);
gtfsBundle.setTransfersTxtDefinesStationPaths(true);
//Puisqu'il est nécessaire de donner à chaque fichier GTFS un ID unique, utilisez le nom de fichier comme ID.
String id = file.getName().substring(0, file.getName().length() - 4);
gtfsBundle.setFeedId(new GtfsFeedId.Builder().id(id).build());
return gtfsBundle;
}).collect(Collectors.toList());
} catch (final IOException e) {
throw new RuntimeException(e);
}
//Traitement pour enregistrer le fichier GTFS lu dans l'objet Graph
GtfsModule gtfsModule = new GtfsModule(gtfsBundles);
Graph graph = new Graph();
gtfsModule.buildGraph(graph, null);
graph.summarizeBuilderAnnotations();
graph.index(new DefaultStreetVertexIndexFactory());
//Le graphique peut également être sérialisé et enregistré
// graph.save(file);
//Paramètres des conditions de recherche
RoutingRequest routingRequest = new RoutingRequest();
routingRequest.setNumItineraries(3); //Nombre de candidats pour les résultats de recherche
//Définir l'heure de référence pour la recherche
LocalDateTime ldt = LocalDateTime.parse("1939-08-01T13:00");
routingRequest.dateTime = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant()).getTime() / 1000;
routingRequest.setArriveBy(false); //La valeur par défaut est de spécifier l'heure de départ, mais si True, vous pouvez spécifier l'heure d'arrivée.
//Latitude de départ et d'arrivée/Spécifié comme doux
routingRequest.from = new GenericLocation(35.3369, 139.44699); //Gare de Tsujido
routingRequest.to = new GenericLocation(35.17096, 136.88232); //Gare de Nagoya
routingRequest.ignoreRealtimeUpdates = true; //Ignorer les informations GTFS en temps réel
routingRequest.reverseOptimizing = true; //Recherchez dans la direction opposée des résultats de recherche et recherchez la dernière heure de départ
//Paramètre pour rechercher uniquement avec des données GTFS
routingRequest.setModes(new TraverseModeSet(TraverseMode.TRANSIT));
routingRequest.onlyTransitTrips = true;
//Définir l'objet graphique
routingRequest.setRoutingContext(graph);
//Traitement de la recherche
Router router = new Router("OTP", graph);
List<GraphPath> paths = new GraphPathFinder(router).getPaths(routingRequest);
TripPlan tripPlan = GraphPathToTripPlanConverter.generatePlan(paths, routingRequest);
//Afficher les résultats de la recherche
tripPlan.itinerary.forEach(p -> {
//Informations récapitulatives pour chaque candidat d'itinéraire
System.out.println(String.format("%d:%02j départ- %d:%02j arrivée(%d minutes)",
p.startTime.get(Calendar.HOUR_OF_DAY), p.startTime.get(Calendar.MINUTE),
p.endTime.get(Calendar.HOUR_OF_DAY), p.endTime.get(Calendar.MINUTE),
(p.duration / 60)));
p.legs.forEach(l -> {
//Informations sur chaque train de l'itinéraire
System.out.println(String.format("> %s %d:%02j départ- %s %d:%02j arrivée",
l.from.name, l.startTime.get(Calendar.HOUR_OF_DAY), l.startTime.get(Calendar.MINUTE),
l.to.name, l.endTime.get(Calendar.HOUR_OF_DAY), l.endTime.get(Calendar.MINUTE)));
});
});
}
}
De plus, à partir de l'objet Leg, si les informations de dessin de l'itinéraire sont stockées dans GTFS forms.txt, elles peuvent être obtenues sous la forme d'une chaîne de caractères codée GEO avec l.legGeometry.getPoints ()
.