Skip to content

Commit 80fa272

Browse files
tkchouakiTarek Chouakisebhoerl
authored
feat: export network routes to geopackage (#235)
* feat: ExportNetworkRoutesToGeopackage * refr: renamed exported network routes gpkg in TestSimulationPipeline --------- Co-authored-by: Tarek Chouaki <tarek.chouaki@irt-systemx.fr> Co-authored-by: Sebastian Hörl <sebastian.horl@irt-systemx.fr>
1 parent d179e3c commit 80fa272

2 files changed

Lines changed: 160 additions & 5 deletions

File tree

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package org.eqasim.core.tools;
2+
3+
import org.eqasim.core.misc.ClassUtils;
4+
import org.eqasim.core.simulation.EqasimConfigurator;
5+
import org.geotools.feature.DefaultFeatureCollection;
6+
import org.geotools.feature.simple.SimpleFeatureBuilder;
7+
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
8+
import org.geotools.geopkg.FeatureEntry;
9+
import org.geotools.geopkg.GeoPackage;
10+
import org.locationtech.jts.geom.Coordinate;
11+
import org.locationtech.jts.geom.GeometryFactory;
12+
import org.locationtech.jts.geom.LineString;
13+
import org.matsim.api.core.v01.Id;
14+
import org.matsim.api.core.v01.Scenario;
15+
import org.matsim.api.core.v01.network.Link;
16+
import org.matsim.api.core.v01.network.Network;
17+
import org.matsim.api.core.v01.population.Leg;
18+
import org.matsim.api.core.v01.population.Person;
19+
import org.matsim.api.core.v01.population.Route;
20+
import org.matsim.core.config.CommandLine;
21+
import org.matsim.core.config.ConfigUtils;
22+
import org.matsim.core.network.io.MatsimNetworkReader;
23+
import org.matsim.core.population.io.PopulationReader;
24+
import org.matsim.core.population.routes.NetworkRoute;
25+
import org.matsim.core.router.TripStructureUtils;
26+
import org.matsim.core.scenario.ScenarioUtils;
27+
import org.matsim.core.utils.geometry.geotools.MGC;
28+
import org.opengis.feature.simple.SimpleFeature;
29+
import org.opengis.feature.simple.SimpleFeatureType;
30+
import org.opengis.referencing.crs.CoordinateReferenceSystem;
31+
32+
import java.io.File;
33+
import java.io.IOException;
34+
import java.util.*;
35+
import java.util.stream.Collectors;
36+
37+
public class ExportNetworkRoutesToGeopackage {
38+
39+
40+
private static Collection<SimpleFeature> extractFeaturesFromPerson(Person person, Network network, SimpleFeatureBuilder featureBuilder, GeometryFactory geometryFactory, Set<String> mainModes, Set<String> legModes) {
41+
List<SimpleFeature> features = new ArrayList<>();
42+
List<TripStructureUtils.Trip> trips = TripStructureUtils.getTrips(person.getSelectedPlan());
43+
for(int tripIndex=0; tripIndex<trips.size(); tripIndex++) {
44+
TripStructureUtils.Trip trip = trips.get(tripIndex);
45+
List<Leg> tripLegs = trip.getLegsOnly();
46+
if(tripLegs.size() == 0) {
47+
continue;
48+
}
49+
if(mainModes.size() > 0 && !mainModes.contains(tripLegs.get(0).getRoutingMode())) {
50+
continue;
51+
}
52+
for(int legIndex=0; legIndex<tripLegs.size(); legIndex++) {
53+
Leg leg = tripLegs.get(legIndex);
54+
if(legModes.size() > 0 && !legModes.contains(leg.getMode())) {
55+
continue;
56+
}
57+
Route route = leg.getRoute();
58+
if(!(route instanceof NetworkRoute networkRoute)) {
59+
continue;
60+
}
61+
List<Id<Link>> linkIds = networkRoute.getLinkIds();
62+
if(linkIds.size() == 0) {
63+
continue;
64+
}
65+
Coordinate[] coordinates = new Coordinate[linkIds.size() + 1];
66+
67+
68+
for(int linkIndex=0; linkIndex<linkIds.size(); linkIndex++) {
69+
Link link = network.getLinks().get(linkIds.get(linkIndex));
70+
71+
if (linkIndex == 0) {
72+
coordinates[linkIndex] = new Coordinate(link.getFromNode().getCoord().getX(),
73+
link.getFromNode().getCoord().getY());
74+
}
75+
76+
coordinates[linkIndex + 1] = new Coordinate(link.getToNode().getCoord().getX(),
77+
link.getToNode().getCoord().getY());
78+
}
79+
80+
featureBuilder.add(person.getId().toString());
81+
featureBuilder.add(tripIndex);
82+
featureBuilder.add(leg.getRoutingMode());
83+
featureBuilder.add(legIndex);
84+
featureBuilder.add(leg.getMode());
85+
86+
87+
88+
featureBuilder.add(geometryFactory.createLineString(coordinates));
89+
features.add(featureBuilder.buildFeature(null));
90+
}
91+
}
92+
return features;
93+
}
94+
95+
public static void main(String[] args) throws CommandLine.ConfigurationException, IOException {
96+
CommandLine commandLine = new CommandLine.Builder(args)
97+
.requireOptions("network-path", "plans-path", "output-path", "crs")
98+
.allowOptions("configurator-class")
99+
.allowOptions("main-modes", "leg-modes")
100+
.build();
101+
102+
String networkPath = commandLine.getOptionStrict("network-path");
103+
String populationPath = commandLine.getOptionStrict("plans-path");
104+
File outputPath = new File(commandLine.getOptionStrict("output-path"));
105+
CoordinateReferenceSystem crs = MGC.getCRS(commandLine.getOptionStrict("crs"));
106+
Set<String> mainModes = commandLine.hasOption("main-modes") ? Arrays.stream(commandLine.getOptionStrict("main-modes").split(",")).map(String::trim).collect(Collectors.toSet()) : new HashSet<>();
107+
Set<String> legModes = commandLine.hasOption("leg-modes") ? Arrays.stream(commandLine.getOptionStrict("leg-modes").split(",")).map(String::trim).collect(Collectors.toSet()) : new HashSet<>();
108+
109+
EqasimConfigurator configurator = commandLine.hasOption("configurator-class") ? ClassUtils.getInstanceOfClassExtendingOtherClass(commandLine.getOptionStrict("configurator"), EqasimConfigurator.class) : new EqasimConfigurator();
110+
111+
Scenario scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig());
112+
configurator.configureScenario(scenario);
113+
new PopulationReader(scenario).readFile(populationPath);
114+
new MatsimNetworkReader(scenario.getNetwork()).readFile(networkPath);
115+
configurator.adjustScenario(scenario);
116+
117+
118+
SimpleFeatureTypeBuilder featureTypeBuilder = new SimpleFeatureTypeBuilder();
119+
120+
featureTypeBuilder.setName("network");
121+
featureTypeBuilder.setCRS(crs);
122+
featureTypeBuilder.setDefaultGeometry("geometry");
123+
124+
featureTypeBuilder.add("person_id", String.class);
125+
featureTypeBuilder.add("trip_index", Integer.class);
126+
featureTypeBuilder.add("trip_mode", String.class);
127+
featureTypeBuilder.add("leg_index", Integer.class);
128+
featureTypeBuilder.add("leg_mode", String.class);
129+
featureTypeBuilder.add("geometry", LineString.class);
130+
131+
SimpleFeatureType featureType = featureTypeBuilder.buildFeatureType();
132+
133+
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType);
134+
GeometryFactory geometryFactory = new GeometryFactory();
135+
136+
DefaultFeatureCollection featureCollection = new DefaultFeatureCollection();
137+
138+
scenario.getPopulation().getPersons().values().stream().flatMap(person -> extractFeaturesFromPerson(person, scenario.getNetwork(), featureBuilder, geometryFactory, mainModes, legModes).stream()).forEach(featureCollection::add);
139+
140+
if(outputPath.exists()) {
141+
outputPath.delete();
142+
}
143+
144+
GeoPackage outputPackage = new GeoPackage(outputPath);
145+
outputPackage.init();
146+
147+
FeatureEntry featureEntry = new FeatureEntry();
148+
outputPackage.add(featureEntry, featureCollection);
149+
150+
outputPackage.close();
151+
}
152+
}

core/src/test/java/org/eqasim/TestSimulationPipeline.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,7 @@
3232
import org.eqasim.core.simulation.modes.transit_with_abstract_access.utils.CreateAbstractAccessItemsForTransitLines;
3333
import org.eqasim.core.standalone_mode_choice.RunStandaloneModeChoice;
3434
import org.eqasim.core.standalone_mode_choice.StandaloneModeChoiceConfigurator;
35-
import org.eqasim.core.tools.ExportActivitiesToShapefile;
36-
import org.eqasim.core.tools.ExportNetworkToShapefile;
37-
import org.eqasim.core.tools.ExportPopulationToCSV;
38-
import org.eqasim.core.tools.ExportTransitLinesToShapefile;
39-
import org.eqasim.core.tools.ExportTransitStopsToShapefile;
35+
import org.eqasim.core.tools.*;
4036
import org.junit.After;
4137
import org.junit.Before;
4238
import org.junit.Test;
@@ -197,6 +193,13 @@ private void runExports() throws Exception {
197193
"--plans-path", "melun_test/input/population.xml.gz",
198194
"--output-path", "melun_test/exports/persons.csv"
199195
});
196+
197+
ExportNetworkRoutesToGeopackage.main(new String[]{
198+
"--plans-path", "melun_test/output/output_plans.xml.gz",
199+
"--network-path", "melun_test/input/network.xml.gz",
200+
"--output-path", "melun_test/exports/network_routes.gpkg",
201+
"--crs", "EPSG:2154"
202+
});
200203
}
201204

202205
private void runCutter() throws Exception {

0 commit comments

Comments
 (0)