C'est un petit article ancien, mais j'ai lu "Comment obtenir les données de base des stations et des routes - Qiita" et j'ai appris qu'il existe des données CSV des routes. C'était. Créons une carte du métro de Tokyo en utilisant le fichier CSV dans "Station data.jp" présenté dans cet article. La version de Java utilisée est la 14. Utilisez yEd --Graph Editor pour afficher le graphique. Tout le code source peut être trouvé ici [https://gist.github.com/saka1029/7d08fef8744a508b29e1c8206510f21e).
Téléchargez les données d'itinéraire, les données de la station et les données de la station connectée à partir de Ma Page | Téléchargement gratuit de données de station "Station Data.jp".
Vous devez créer un compte gratuit pour télécharger.
Créez un programme commun qui lit un fichier CSV et le convertit en List <List <String >>
.
static final Charset CHARSET = StandardCharsets.UTF_8;
static final Path DIRECTORY = Paths.get("data", "eki");
static final Path LINE_CSV = DIRECTORY.resolve("line20200619free.csv");
static final Path STATION_CSV = DIRECTORY.resolve("station20200619free.csv");
static final Path JOIN_CSV = DIRECTORY.resolve("join20200619.csv");
static final Path GML = DIRECTORY.resolve("metro.gml");
static List<List<String>> readCSV(Path file) throws IOException {
return Files.readAllLines(file, CHARSET).stream()
.map(line -> List.of(line.split(",")))
.collect(toList());
}
Chaque élément n'est pas entouré de guillemets, il peut donc être facilement lu.
Tout d'abord, lisez les données d'itinéraire. Puisque nous allons créer une carte du métro de Tokyo, seuls ceux dont les noms de ligne commencent par "Tokyo Metro" ou "Toei" seront extraits.
//Ligne de métro de Tokyo
List<List<String>> lines = readCSV(LINE_CSV).stream()
.filter(line -> line.get(2).startsWith("Métro de Tokyo") || line.get(2).startsWith("Toei"))
.collect(toList());
Ensuite, les données de la station sont lues, mais une liste de codes d'itinéraire est créée afin d'extraire uniquement ceux qui correspondent aux codes d'itinéraire des données d'itinéraire lues précédemment. (Aurait dû être défini au lieu de List)
//Liste des codes de lignes de métro de Tokyo
List<String> lineCodes = lines.stream()
.map(line -> line.get(0))
.collect(toList());
Seules les stations avec les codes d'itinéraire dans cette liste seront extraites.
//Station de métro de Tokyo
List<List<String>> stations = readCSV(STATION_CSV).stream()
.filter(station -> lineCodes.contains(station.get(5)))
.collect(toList());
Enfin, lisez les données de la station de connexion. Encore une fois, seuls ceux liés au code de ligne du métro de Tokyo sont extraits.
//Connexion à la station de métro de Tokyo
List<List<String>> joins = readCSV(JOIN_CSV).stream()
.filter(line -> lineCodes.contains(line.get(0)))
.collect(toList());
Créez un graphique à partir des données lues. Les graphiques sont lus à l'aide de yEd --Graph Editor, créez donc des données texte au format GML (Graphic Modeling Language).
//Créer un graphique
try (PrintWriter w = new PrintWriter(Files.newBufferedWriter(GML))) {
w.println("graph [");
for (List<String> s : stations) {
w.println(" node [");
w.println(" id " + s.get(0)); //Code de la station
w.println(" label \"" + s.get(2) + "\""); //Nom de la station
w.println(" ]");
}
for (List<String> j : joins) {
w.println(" edge [");
w.println(" source " + j.get(1)); //Code station de connexion 1
w.println(" target " + j.get(2)); //Code de station de connexion 2
w.println(" ]");
}
w.println("]");
}
Créez une station en tant que nœud et une station de connexion en tant que bord.
Lisez avec yEd et formatez comme suit.
Ensuite, le graphique ressemble à ceci. 13 itinéraires ont été créés séparément. Vous pouvez voir que le coin supérieur gauche est la ligne Oedo car elle comprend la ligne circulaire et la ligne Marunouchi qui comprend la ligne secondaire Honancho car elle est en forme de Y à côté.
Cependant, ce n'est pas une carte d'itinéraire. La raison en est que la même station est enregistrée séparément pour chaque ligne.
Les codes de station sont agrégés par ceux qui ont le même nom de station. Le résultat est une carte de la liste, la clé étant le nom de la station et la valeur étant la liste des codes de station avec ce nom de station. Par exemple, Shinjuku = [2800218, 9930128, 9930401]
.
//Code de station groupé par nom de station(ex.Shinjuku=[2800218, 9930128, 9930401])
Map<String, List<String>> stationNameMap = stations.stream()
.collect(groupingBy(e -> e.get(2),
mapping(e -> e.get(0), toList())));
Afin de combiner les codes représentant Shinjuku en un seul, nous allons créer une carte pour convertir le code de station en code de station représentatif. Le code de station qui apparaît en haut de la liste des codes de station est le code de station représentatif. Dans le cas de Shinjuku, ce sera «2800218 = 2800218, 9930128 = 2800218, 9930401 = 2800218».
//Carte du code de station au code de station représentatif(ex. 2800218=2800218, 9930128=2800218, 9930401=2800218)
Map<String, String> stationCodeMap = stationNameMap.values().stream()
.flatMap(codes -> codes.stream().map(code -> Map.entry(code, codes.get(0))))
.collect(toMap(Entry::getKey, Entry::getValue));
Créez un graphique qui résume les mêmes noms de stations.
//Créer un graphique
try (PrintWriter w = new PrintWriter(Files.newBufferedWriter(GML))) {
w.println("graph [");
for (Entry<String, List<String>> e : stationNameMap.entrySet()) { //Utilise des données agrégées par nom de station
w.println(" node [");
w.println(" id " + e.getValue().get(0)); //Code de la station représentative
w.println(" label \"" + e.getKey() + "\""); //Nom de la station
w.println(" ]");
}
for (List<String> j : joins) {
w.println(" edge [");
w.println(" source " + stationCodeMap.get(j.get(1))); //Convertir en code de station représentatif
w.println(" target " + stationCodeMap.get(j.get(2))); //Convertir en code de station représentatif
w.println(" ]");
}
w.println("]");
}
Quand je le lis avec yEd et le formate, cela ressemble à ceci.
Cela ressemble à une carte d'itinéraire, mais il y a deux Ichigaya.
Si vous regardez attentivement, vous pouvez voir qu'il y a deux stations Ichigaya en raison de la différence entre "ke" et "ga". Si vous recherchez Ichigaya Station sur Wikipedia, C'est écrit.
Les stations de métro JR East et Tokyo sont appelées «Ichigaya» et les stations de métro Toei sont appelées «Ichigaya».
Dans le graphique
Comme c'est le cas, vous pouvez voir que la station data.jp exprime avec précision cette différence. Pour absorber cette différence, modifiez la lecture des données de station décrites ci-dessus comme suit.
//Station de métro de Tokyo
List<List<String>> stations = readCSV(STATION_CSV).stream()
.filter(station -> lineCodes.contains(station.get(5)))
.map(station -> station.stream()
.map(item -> item.replace('Mois', 'Ke')).collect(toList())) // 市Mois谷と市Ke谷を統一
.collect(toList());
Ici, j'ai décidé de l'unifier au style du métro de Tokyo.
La forme finale du graphique ressemble à ceci.
«Otemachi» est près du centre, mais si vous regardez de près, vous trouverez «Nishifunabashi» à l'extrémité gauche, «Ogikubo» à l'extrémité droite, «Nishimagome» à l'extrémité supérieure et «Nishitakashimadaira» à l'extrémité inférieure. On a l'impression que l'est et l'ouest et le nord et le sud sont inversés. Cela est inévitable car le graphique ne donne que des informations géométriques de phase, mais comme les données de la station comprennent également des informations sur la latitude et la longitude de la station, créez une carte d'itinéraire géographiquement précise. Pourront. Le nœud GML a également un attribut de couleur, vous pouvez donc coder en couleur chaque route. yEd est disponible dans une variété de mises en page, il est donc intéressant de les expérimenter. La plupart des programmes que j'ai créés cette fois utilisent l'API Stream. Je l'ai trouvé très pratique car la plupart d'entre eux peuvent être décrits de manière concise avec "une doublure".
Recommended Posts