Skip to content

Commit

Permalink
Merge branch 'master' into consolidateZones
Browse files Browse the repository at this point in the history
  • Loading branch information
nkuehnel authored Apr 25, 2024
2 parents d8ca922 + fa0e141 commit 72c98f2
Show file tree
Hide file tree
Showing 44 changed files with 727 additions and 277 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package org.matsim.application.options;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.geotools.data.FeatureReader;
import org.geotools.data.FileDataStoreFactorySpi;
import org.geotools.data.*;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.geopkg.GeoPkgDataStoreFactory;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.index.strtree.AbstractNode;
Expand Down Expand Up @@ -34,10 +35,7 @@
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.function.Predicate;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
Expand All @@ -62,6 +60,9 @@ public final class ShpOptions {
@CommandLine.Option(names = "--shp-crs", description = "Overwrite coordinate system of the shape file")
private String shpCrs;

@CommandLine.Option(names = "--shp-layer", description = "Layer to use (for .gpgk files). Defaults to first layer.", required = false)
private String shpLayer;

@CommandLine.Option(names = "--shp-charset", description = "Charset used to read the shape file", defaultValue = "ISO-8859-1")
private Charset shpCharset;

Expand All @@ -86,19 +87,41 @@ public ShpOptions(String shp, @Nullable String shpCrs, @Nullable Charset shpChar
this.shpCharset = shpCharset;
}

private ShpOptions(String shp, String shpCrs, String shpLayer, Charset shpCharset) {
this.shp = shp;
this.shpCrs = shpCrs;
this.shpLayer = shpLayer;
this.shpCharset = shpCharset;
}

/**
* Create shp options with a specific layer. (Usually for gpkg files).
*/
public static ShpOptions ofLayer(String shp, @Nullable String shpLayer) {
return new ShpOptions(shp, null, shpLayer, null);
}

/**
* Opens datastore to a shape-file.
*/
public static ShapefileDataStore openDataStore(String shp) throws IOException {
public static DataStore openDataStore(String shp) throws IOException {

FileDataStoreFactorySpi factory = new ShapefileDataStoreFactory();

URL url = IOUtils.resolveFileOrResource(shp);

ShapefileDataStore ds;
DataStore ds;
if (shp.endsWith(".shp"))
ds = (ShapefileDataStore) factory.createDataStore(url);
else if (shp.endsWith(".zip")) {
ds = factory.createDataStore(url);
else if (shp.endsWith(".gpkg")) {
ds = DataStoreFinder.getDataStore(Map.of(
GeoPkgDataStoreFactory.DBTYPE.key, "geopkg",
GeoPkgDataStoreFactory.DATABASE.key, shp,
GeoPkgDataStoreFactory.READ_ONLY.key, true
));
} else if (shp.endsWith(".dbf") || shp.endsWith(".shx")) {
throw new IllegalArgumentException("Shape file must be .shp, but was: " + shp);
} else if (shp.endsWith(".zip")) {

// Zip files will only work with local files
URI uri;
Expand All @@ -119,12 +142,12 @@ else if (shp.endsWith(".zip")) {
throw new IllegalArgumentException("Could not create URI for zip file: " + url, e);
}

ds = (ShapefileDataStore) factory.createDataStore(uri.toURL());
ds = factory.createDataStore(uri.toURL());
} else {
throw new IllegalArgumentException("Shape file must either be .zip or .shp, but was: " + shp);
}

return ds;
return Objects.requireNonNull(ds, "Could not create data store.");
}

/**
Expand Down Expand Up @@ -158,11 +181,15 @@ public List<SimpleFeature> readFeatures() {
throw new IllegalStateException("Shape file path not specified");

try {
ShapefileDataStore ds = openDataStore(shp);
if (shpCharset != null)
ds.setCharset(shpCharset);
DataStore ds = openDataStore(shp);
if (shpCharset != null && ds instanceof ShapefileDataStore shpDs)
shpDs.setCharset(shpCharset);

return GeoFileReader.getSimpleFeatures(ds);
if (ds instanceof FileDataStore fds) {
return GeoFileReader.getSimpleFeatures(fds);
}

return GeoFileReader.getSimpleFeatures(ds, getLayer(ds));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Expand All @@ -179,7 +206,7 @@ public Geometry getGeometry() {
}

if (features.size() == 1) {
return (Geometry) features.iterator().next().getDefaultGeometry();
return (Geometry) features.iterator().next().getDefaultGeometry();
}

GeometryFactory factory = ((Geometry) features.iterator().next().getDefaultGeometry()).getFactory();
Expand Down Expand Up @@ -212,7 +239,7 @@ public Index createIndex(String queryCRS, String attr, Predicate<SimpleFeature>
throw new IllegalArgumentException("Query crs must not be null!");

try {
ShapefileDataStore ds = openDataStoreAndSetCRS();
DataStore ds = openDataStoreAndSetCRS();
CoordinateTransformation ct;
if (queryCRS.equals(SAME_CRS))
ct = new IdentityTransformation();
Expand Down Expand Up @@ -254,8 +281,8 @@ private String detectCRS() {

if (shpCrs == null) {
try {
ShapefileDataStore ds = openDataStore(shp);
CoordinateReferenceSystem crs = ds.getSchema().getCoordinateReferenceSystem();
DataStore ds = openDataStore(shp);
CoordinateReferenceSystem crs = ds.getSchema(getLayer(ds)).getCoordinateReferenceSystem();
ds.dispose();
shpCrs = "EPSG:" + CRS.lookupEpsgCode(crs, true);
log.info("Using detected crs for {}: {}", shp, shpCrs);
Expand All @@ -271,12 +298,12 @@ private String detectCRS() {
/**
* Open the shape file for processing and set the crs if not already specified.
*/
private ShapefileDataStore openDataStoreAndSetCRS() throws IOException {
ShapefileDataStore ds = openDataStore(shp);
private DataStore openDataStoreAndSetCRS() throws IOException {
DataStore ds = openDataStore(shp);

if (shpCrs == null) {
try {
CoordinateReferenceSystem crs = ds.getSchema().getCoordinateReferenceSystem();
CoordinateReferenceSystem crs = ds.getSchema(getLayer(ds)).getCoordinateReferenceSystem();
shpCrs = "EPSG:" + CRS.lookupEpsgCode(crs, true);
log.info("Using detected crs for {}: {}", shp, shpCrs);
} catch (FactoryException | NullPointerException e) {
Expand All @@ -287,6 +314,21 @@ private ShapefileDataStore openDataStoreAndSetCRS() throws IOException {
return ds;
}

/**
* Get the selected layer or throw exception if not found.
*/
private String getLayer(DataStore ds) throws IOException {
String[] typeNames = ds.getTypeNames();
if (shpLayer != null) {
if (!ArrayUtils.contains(typeNames, shpLayer))
throw new IllegalArgumentException("Layer " + shpLayer + " not found in shape file.");

return shpLayer;
}

return typeNames[0];
}

/**
* Create an inverse coordinate transformation from the shape file crs. Tries to autodetect the crs of the shape file.
*/
Expand All @@ -309,11 +351,18 @@ public final class Index {
* @param ct coordinate transform from query to target crs
* @param attr attribute for the result of {@link #query(Coord)}
*/
Index(CoordinateTransformation ct, ShapefileDataStore ds, String attr, @Nullable Predicate<SimpleFeature> filter) throws IOException {
if (shpCharset != null)
ds.setCharset(shpCharset);
Index(CoordinateTransformation ct, DataStore ds, String attr, @Nullable Predicate<SimpleFeature> filter) throws IOException {
if (shpCharset != null && ds instanceof ShapefileDataStore shpDs)
shpDs.setCharset(shpCharset);

FeatureReader<SimpleFeatureType, SimpleFeature> it;
DefaultTransaction transaction = new DefaultTransaction();
if (ds instanceof FileDataStore fds) {
it = fds.getFeatureReader();
} else {
it = ds.getFeatureReader(new Query(getLayer(ds)), transaction);
}

FeatureReader<SimpleFeatureType, SimpleFeature> it = ds.getFeatureReader();
while (it.hasNext()) {
SimpleFeature ft = it.next();

Expand All @@ -332,6 +381,7 @@ public final class Index {

index.build();

transaction.close();
it.close();
ds.dispose();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.matsim.application.prepare;

import it.unimi.dsi.fastutil.objects.Object2DoubleMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;

/**
* Predictor interface for arbitrary numeric values.
*/
public interface Predictor {


/**
* Predict value from given features.
*/
double predict(Object2DoubleMap<String> features, Object2ObjectMap<String, String> categories);

/**
* Predict values with adjusted model params.
*/
default double predict(Object2DoubleMap<String> features, Object2ObjectMap<String, String> categories, double[] params) {
throw new UnsupportedOperationException("Not implemented");
}


/**
* Return data that is used for internal prediction function (normalization already applied).
*/
default double[] getData(Object2DoubleMap<String> features, Object2ObjectMap<String, String> categories) {
throw new UnsupportedOperationException("Not implemented");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void readZip() {
Path input = Path.of(utils.getClassInputDirectory()
.replace("ShpOptionsTest", "CreateLandUseShpTest")
.replace("options", "prepare"))
.resolve("andorra-latest-free.shp.zip");
.resolve("andorra-latest-free.shp.zip");

Assumptions.assumeTrue(Files.exists(input));

Expand All @@ -38,7 +38,7 @@ void readZip() {
List<SimpleFeature> ft = shp.readFeatures();

assertThat(ft)
.isNotEmpty();
.isNotEmpty();

}

Expand Down Expand Up @@ -73,7 +73,7 @@ void all() {
Path input = Path.of(utils.getClassInputDirectory()
.replace("ShpOptionsTest", "CreateLandUseShpTest")
.replace("options", "prepare"))
.resolve("andorra-latest-free.shp.zip");
.resolve("andorra-latest-free.shp.zip");

Assumptions.assumeTrue(Files.exists(input));

Expand All @@ -84,8 +84,8 @@ void all() {
List<SimpleFeature> ft = index.getAllFeatures();

assertThat(ft)
.hasSize(4906)
.hasSize(Set.copyOf(ft).size());
.hasSize(4906)
.hasSize(Set.copyOf(ft).size());

assertThat(shp.readFeatures())
.hasSameElementsAs(ft);
Expand All @@ -96,17 +96,36 @@ void all() {
void testGetGeometry() {

Path input = Path.of(utils.getClassInputDirectory()
.replace("ShpOptionsTest", "CreateLandUseShpTest")
.replace("options", "prepare"))
.resolve("andorra-latest-free.shp.zip");
.replace("ShpOptionsTest", "CreateLandUseShpTest")
.replace("options", "prepare"))
.resolve("andorra-latest-free.shp.zip");

Assumptions.assumeTrue(Files.exists(input));

ShpOptions shp = new ShpOptions(input, null, null);
Geometry geometry = shp.getGeometry() ;
Geometry geometry = shp.getGeometry();

assertThat(geometry.getArea())
.isCloseTo(1.9847543618489646E-4, Offset.offset(1e-8));

}

@Test
void gpkg() {

Path path = Path.of(utils.getPackageInputDirectory(), "example.gpkg");

ShpOptions shp = ShpOptions.ofLayer(path.toString(), null);

List<SimpleFeature> features = shp.readFeatures();

assertThat(features)
.hasSize(3);

ShpOptions.Index index = shp.createIndex("_");

assertThat(index.size())
.isEqualTo(3);

}
}
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ public ParkCSVehicles(QSim qSim,
this.mainModes = qsim.getScenario().getConfig().qsim().getMainModes();

for (String mode : mainModes) {
modeVehicleTypes.put(mode, VehicleUtils.getDefaultVehicleType());
modeVehicleTypes.put(mode, VehicleUtils.createDefaultVehicleType());
}
this.carsharingSupply = carsharingSupply;
modeVehicleTypes.put("twoway", VehicleUtils.getDefaultVehicleType());
modeVehicleTypes.put("freefloating", VehicleUtils.getDefaultVehicleType());
modeVehicleTypes.put("twoway", VehicleUtils.createDefaultVehicleType());
modeVehicleTypes.put("freefloating", VehicleUtils.createDefaultVehicleType());

modeVehicleTypes.put("oneway", VehicleUtils.getDefaultVehicleType());
modeVehicleTypes.put("oneway", VehicleUtils.createDefaultVehicleType());


}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public FleetModule(String mode, URL fleetSpecificationUrl, boolean updateVehicle
this.fleetSpecificationUrl = fleetSpecificationUrl;
this.updateVehicleStartLinkToLastLink = updateVehicleStartLinkToLastLink;

vehicleType = VehicleUtils.getDefaultVehicleType();
vehicleType = VehicleUtils.createDefaultVehicleType();
}

public FleetModule(String mode, URL fleetSpecificationUrl, VehicleType vehicleType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public void insertAgentsIntoMobsim() {
// qSim.createAndParkVehicleOnLink(qSimVehicleFactory.createVehicle(Id.create(id, Vehicle.class),
// VehicleUtils.getDefaultVehicleType()), startLinkId);

final Vehicle vehicle = qSimVehicleFactory.createVehicle( Id.create( id, Vehicle.class ), VehicleUtils.getDefaultVehicleType() ) ;
final Vehicle vehicle = qSimVehicleFactory.createVehicle( Id.create( id, Vehicle.class ), VehicleUtils.createDefaultVehicleType() ) ;
QVehicle qVehicle = new QVehicleImpl( vehicle ) ; // yyyyyy should use factory. kai, nov'18
qSim.addParkedVehicle( qVehicle, startLinkId );

Expand Down
Loading

0 comments on commit 72c98f2

Please sign in to comment.