Skip to content

Commit

Permalink
Merge branch 'lts-experiment' into lts-plus-locked-schedules
Browse files Browse the repository at this point in the history
  • Loading branch information
ansoncfit committed Jan 11, 2024
2 parents 9a476f7 + 7896ab1 commit 3654f09
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.conveyal.analysis.datasource.DataSourceException;
import com.conveyal.file.FileStorageFormat;
import com.conveyal.file.FileStorageKey;
import com.conveyal.r5.rastercost.ElevationLoader;
import com.conveyal.r5.shapefile.ShapefileMatcher;
import com.conveyal.r5.transit.TransportNetwork;
import com.conveyal.r5.transit.TransportNetworkCache;
Expand All @@ -24,8 +23,6 @@
*/
public class ShapefileLts extends Modification {

public String ltsDataSource;

/**
* ID of the linear shapefile DataSource containing bicycle LTS to be matched to streets.
* We must assume its type because the workers don't have access to the DataStore metadata.
Expand All @@ -35,6 +32,8 @@ public class ShapefileLts extends Modification {
/** The name of the numeric attribute within the ltsDataSource containing LTS values from 1-4. */
public String ltsAttribute = "lts";

public double matchLimitMeters = 3.0;

private FileStorageKey fileStorageKey;

private File localFile;
Expand All @@ -61,7 +60,7 @@ public boolean apply (TransportNetwork network) {
network.streetLayer.edgeStore.flags = new TIntArrayList(network.streetLayer.edgeStore.flags);
ShapefileMatcher shapefileMatcher = new ShapefileMatcher(network.streetLayer);
try {
shapefileMatcher.match(localFile.getAbsolutePath(), ltsAttribute);
shapefileMatcher.match(localFile.getAbsolutePath(), ltsAttribute, matchLimitMeters);
} catch (Exception e) {
addError(ExceptionUtils.shortAndLongString(e));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public abstract class KryoNetworkSerializer {
* the serialization format itself does not change. This will ensure newer workers will not load cached older files.
* We considered using an ISO date string as the version but that could get confusing when seen in filenames.
*/
public static final String NETWORK_FORMAT_VERSION = "nv2";
public static final String NETWORK_FORMAT_VERSION = "7689347c";

public static final byte[] HEADER = "R5NETWORK".getBytes();

Expand Down
31 changes: 21 additions & 10 deletions src/main/java/com/conveyal/r5/shapefile/ShapefileMatcher.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.conveyal.r5.shapefile;

import com.conveyal.r5.common.SphericalDistanceLibrary;
import com.conveyal.r5.streets.EdgeStore;
import com.conveyal.r5.streets.StreetLayer;
import com.conveyal.r5.util.LambdaCounter;
import com.conveyal.r5.util.ShapefileReader;
import org.locationtech.jts.algorithm.distance.DiscreteHausdorffDistance;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.MultiLineString;
import org.locationtech.jts.index.strtree.STRtree;
import org.locationtech.jts.operation.distance.DistanceOp;
import org.opengis.feature.simple.SimpleFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -18,7 +21,6 @@
import java.util.List;
import java.util.stream.IntStream;

import static com.conveyal.r5.streets.EdgeStore.intToLts;
import static com.conveyal.r5.streets.EdgeStore.EdgeFlag.BIKE_LTS_EXPLICIT;

/**
Expand Down Expand Up @@ -59,6 +61,8 @@ public class ShapefileMatcher {
private StreetLayer streets;
private int ltsAttributeIndex = -1;

private double matchLimitMeters;

public ShapefileMatcher (StreetLayer streets) {
this.streets = streets;
}
Expand All @@ -72,12 +76,15 @@ public ShapefileMatcher (StreetLayer streets) {
* OSM_INFERRED, OSM_EXPLICIT, SHAPEFILE_MATCH etc. This could also apply to things like speeds and slopes.
* The values could be retained only for the duration of network building unless we have a reason to keep them.
*/
public void match (String shapefileName, String attributeName) {
public void match (String shapefileName, String attributeName, double matchLimitMeters) {
try {
indexFeatures(shapefileName, attributeName);
} catch (Throwable t) {
throw new RuntimeException("Could not load and index shapefile.", t);
}

this.matchLimitMeters = matchLimitMeters;

LOG.info("Matching edges and setting bike LTS flags...");
// Even single-threaded this is pretty fast for small extracts, but it's readily paralellized.
final LambdaCounter edgePairCounter =
Expand Down Expand Up @@ -107,19 +114,23 @@ public void match (String shapefileName, String attributeName) {
streets.edgeStore.nEdgePairs() - edgePairCounter.getCount());
}

// Match metric is currently Hausdorff distance, eventually replace with something that accounts for overlap length.
// For features within the given matchLimitMeters, choose the closest based on Hausdorff distance.
// This could eventually be replaced with something that accounts for overlap length.
private SimpleFeature findBestMatch (LineString edgeGeometry) {
SimpleFeature bestFeature = null;
double bestDistance = Double.POSITIVE_INFINITY;
List<SimpleFeature> features = featureIndex.query(edgeGeometry.getEnvelopeInternal());
for (SimpleFeature feature : features) {
// Note that we're using unprojected coordinates so x distance is exaggerated realtive to y.
DiscreteHausdorffDistance dhd = new DiscreteHausdorffDistance(extractLineString(feature), edgeGeometry);
double distance = dhd.distance();
// distance = overlap(extractLineString(feature), edgeGeometry);
if (bestDistance > distance) {
bestDistance = distance;
bestFeature = feature;
Coordinate[] nearestPoints = new DistanceOp(extractLineString(feature), edgeGeometry).nearestPoints();
if (SphericalDistanceLibrary.fastDistance(nearestPoints[0], nearestPoints[1]) < matchLimitMeters) {
// Note that we're using unprojected coordinates so x distance is exaggerated relative to y.
DiscreteHausdorffDistance dhd = new DiscreteHausdorffDistance(extractLineString(feature), edgeGeometry);
double distance = dhd.distance();
// distance = overlap(extractLineString(feature), edgeGeometry);
if (bestDistance > distance) {
bestDistance = distance;
bestFeature = feature;
}
}
}
return bestFeature;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class ShapefileMatcherMain {
public static void main (String[] args) throws Throwable {
StreetLayer streetLayer = loadStreetLayer();
ShapefileMatcher shapefileMatcher = new ShapefileMatcher(streetLayer);
shapefileMatcher.match(SHAPE_FILE, SHAPE_FILE_ATTRIBUTE);
shapefileMatcher.match(SHAPE_FILE, SHAPE_FILE_ATTRIBUTE, 2.0);
}

private static StreetLayer loadStreetLayer () {
Expand Down

0 comments on commit 3654f09

Please sign in to comment.