Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(isochrones): use correct edge filter for snapping #1568

Merged
merged 1 commit into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ RELEASING:
- Upgrade org.geotools.gt-epsg-hsql to version 29.1. ([#1479](https://github.com/GIScience/openrouteservice/issues/1479))
- various style and low level code problems ([#1489](https://github.com/GIScience/openrouteservice/pull/1489))
- Fix the max visited nodes bug for fast-isochrones ([#1538](https://github.com/GIScience/openrouteservice/pull/1538))
- fix isochrones snapping ([#1568](https://github.com/GIScience/openrouteservice/pull/1568))

## [7.1.0] - 2023-06-13
### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,29 @@

import com.carrotsearch.hppc.IntObjectMap;
import com.graphhopper.GraphHopper;
import com.graphhopper.routing.SPTEntry;
import com.graphhopper.routing.ev.Subnetwork;
import com.graphhopper.routing.querygraph.QueryGraph;
import com.graphhopper.routing.util.DefaultSnapFilter;
import com.graphhopper.routing.util.EdgeFilter;
import com.graphhopper.routing.util.FlagEncoder;
import com.graphhopper.routing.util.TraversalMode;
import com.graphhopper.routing.weighting.FastestWeighting;
import com.graphhopper.routing.weighting.ShortestWeighting;
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.storage.GraphHopperStorage;
import com.graphhopper.routing.SPTEntry;
import com.graphhopper.storage.index.Snap;
import com.graphhopper.util.shapes.GHPoint3D;
import org.locationtech.jts.geom.Coordinate;
import org.heigit.ors.common.TravelRangeType;
import org.heigit.ors.exceptions.InternalServerException;
import org.heigit.ors.routing.RouteSearchContext;
import org.heigit.ors.routing.algorithms.DijkstraCostCondition;
import org.heigit.ors.routing.algorithms.TDDijkstraCostCondition;
import org.heigit.ors.routing.graphhopper.extensions.AccessibilityMap;
import org.heigit.ors.routing.graphhopper.extensions.ORSEdgeFilterFactory;
import org.heigit.ors.routing.graphhopper.extensions.weighting.DistanceWeighting;
import org.heigit.ors.routing.traffic.TrafficSpeedCalculator;
import org.heigit.ors.util.ProfileTools;
import org.locationtech.jts.geom.Coordinate;

import java.time.ZonedDateTime;
import java.util.ArrayList;
Expand All @@ -47,10 +50,12 @@ private GraphEdgeMapFinder() {
public static AccessibilityMap findEdgeMap(RouteSearchContext searchCntx, IsochroneSearchParameters parameters) throws Exception {
GraphHopper gh = searchCntx.getGraphHopper();
FlagEncoder encoder = searchCntx.getEncoder();
Weighting weighting = createWeighting(parameters, encoder);
String profileName = ProfileTools.makeProfileName(encoder.toString(), weighting.getName(), false);
GraphHopperStorage graph = gh.getGraphHopperStorage();

ORSEdgeFilterFactory edgeFilterFactory = new ORSEdgeFilterFactory();
EdgeFilter edgeFilter = edgeFilterFactory.createEdgeFilter(searchCntx.getProperties(), encoder, graph);
EdgeFilter defaultSnapFilter = new DefaultSnapFilter(weighting, graph.getEncodingManager().getBooleanEncodedValue(Subnetwork.key(profileName)));
ORSEdgeFilterFactory edgeFilterFactory = new ORSEdgeFilterFactory();
EdgeFilter edgeFilter = edgeFilterFactory.createEdgeFilter(searchCntx.getProperties(), encoder, graph, defaultSnapFilter);

Coordinate loc = parameters.getLocation();
Snap res = gh.getLocationIndex().findClosest(loc.y, loc.x, edgeFilter);
Expand All @@ -64,7 +69,6 @@ public static AccessibilityMap findEdgeMap(RouteSearchContext searchCntx, Isochr

if (fromId == -1)
throw new InternalServerException(IsochronesErrorCodes.UNKNOWN, "The closest node is null.");
Weighting weighting = createWeighting(parameters, encoder);

if (parameters.isTimeDependent()) {
return calculateTimeDependentAccessibilityMap(parameters, encoder, graph, edgeFilter, queryGraph, snappedPosition, fromId, weighting);
Expand Down Expand Up @@ -114,6 +118,6 @@ private static AccessibilityMap calculateTimeDependentAccessibilityMap(Isochrone

private static Weighting createWeighting(IsochroneSearchParameters parameters, FlagEncoder encoder) {
return parameters.getRangeType() == TravelRangeType.TIME ? new FastestWeighting(encoder)
: new DistanceWeighting(encoder);
: new ShortestWeighting(encoder);
}
}
Original file line number Diff line number Diff line change
@@ -1,58 +0,0 @@
/* This file is part of Openrouteservice.
*
* Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.

* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.

* You should have received a copy of the GNU Lesser General Public License along with this library;
* if not, see <https://www.gnu.org/licenses/>.
*/
package org.heigit.ors.routing.graphhopper.extensions.weighting;

import com.graphhopper.routing.util.FlagEncoder;
import com.graphhopper.routing.weighting.AbstractWeighting;
import com.graphhopper.util.EdgeIteratorState;

public class DistanceWeighting extends AbstractWeighting {
public DistanceWeighting(FlagEncoder encoder) {
super(encoder);
}

@Override
public double calcEdgeWeight(EdgeIteratorState edge, boolean reverse) {
double speed = flagEncoder.getAverageSpeedEnc().getDecimal(reverse, edge.getFlags());
if (speed == 0)
return Double.POSITIVE_INFINITY;

return edge.getDistance();
}

@Override
public double getMinWeight(double distance) {
return 0;
}

@Override
public String getName() {
return "distance";
}

@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final DistanceWeighting other = (DistanceWeighting) obj;
return toString().equals(other.toString());
}

@Override
public int hashCode() {
return ("DistanceWeighting" + this).hashCode();
}
}
103 changes: 103 additions & 0 deletions ors-engine/src/main/java/org/heigit/ors/util/ProfileTools.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package org.heigit.ors.util;

import com.graphhopper.util.PMap;
import org.heigit.ors.routing.RoutingProfileType;
import org.heigit.ors.routing.WeightingMethod;
import org.heigit.ors.routing.graphhopper.extensions.util.ORSParameters;

public class ProfileTools {
public static final String VAL_RECOMMENDED = "recommended";
private static final String KEY_WEIGHTING = "weighting";
private static final String KEY_WEIGHTING_METHOD = "weighting_method";
public static final String KEY_CH_DISABLE = "ch.disable";
public static final String KEY_LM_DISABLE = "lm.disable";
public static final String KEY_CORE_DISABLE = "core.disable";
public static final String KEY_PREPARE_CORE_WEIGHTINGS = "prepare.core.weightings";
public static final String KEY_PREPARE_FASTISOCHRONE_WEIGHTINGS = "prepare.fastisochrone.weightings";
public static final String KEY_METHODS_CH = "methods.ch";
public static final String KEY_ENABLED = "enabled";
public static final String KEY_THREADS = "threads";
public static final String KEY_WEIGHTINGS = "weightings";
public static final String KEY_LMSETS = "lmsets";
public static final String KEY_MAXCELLNODES = "maxcellnodes";
public static final String KEY_METHODS_LM = "methods.lm";
public static final String KEY_LANDMARKS = "landmarks";
public static final String KEY_METHODS_CORE = "methods.core";
public static final String KEY_DISABLING_ALLOWED = "disabling_allowed";
public static final String KEY_ACTIVE_LANDMARKS = "active_landmarks";
public static final String KEY_TOTAL_POP = "total_pop";
public static final String KEY_TOTAL_AREA_KM = "total_area_km";
public static final int KEY_FLEX_STATIC = 0;
public static final int KEY_FLEX_PREPROCESSED = 1;
public static final int KEY_FLEX_FULLY = 2;
public static final String KEY_CUSTOM_WEIGHTINGS = "custom_weightings";
public static final String VAL_SHORTEST = "shortest";
public static final String VAL_FASTEST = "fastest";

public static String makeProfileName(String vehicleName, String weightingName, boolean hasTurnCosts) {
String profileName = vehicleName + "_" + weightingName;
if (hasTurnCosts)
profileName += "_with_turn_costs";
return profileName;
}

/**
* Set the weightingMethod for the request based on input weighting.
*
* @param map Hints map for setting up the request
* @param requestWeighting Originally requested weighting
* @param profileType Necessary for HGV
*/
public static void setWeightingMethod(PMap map, int requestWeighting, int profileType, boolean hasTimeDependentSpeed) {
//Defaults
String weightingMethod = VAL_RECOMMENDED;

if (requestWeighting == WeightingMethod.SHORTEST)
weightingMethod = VAL_SHORTEST;

//For a requested recommended weighting, use recommended for bike, walking and hgv. Use fastest for car.
if (requestWeighting == WeightingMethod.RECOMMENDED || requestWeighting == WeightingMethod.FASTEST) {
if (profileType == RoutingProfileType.DRIVING_CAR) {
weightingMethod = VAL_FASTEST;
}
if (RoutingProfileType.isHeavyVehicle(profileType) || RoutingProfileType.isCycling(profileType) || RoutingProfileType.isWalking(profileType)) {
weightingMethod = VAL_RECOMMENDED;
}
}

map.putObject(KEY_WEIGHTING_METHOD, weightingMethod);

if (hasTimeDependentSpeed)
map.putObject(ORSParameters.Weighting.TIME_DEPENDENT_SPEED_OR_ACCESS, true);
}

/**
* Set the weighting for the request based on input weighting.
*
* @param map Hints map for setting up the request
* @param requestWeighting Originally requested weighting
* @param profileType Necessary for HGV
*/
public static void setWeighting(PMap map, int requestWeighting, int profileType, boolean hasTimeDependentSpeed) {
//Defaults
String weighting = VAL_RECOMMENDED;

if (requestWeighting == WeightingMethod.SHORTEST)
weighting = VAL_SHORTEST;

//For a requested recommended weighting, use recommended for bike, walking and hgv. Use fastest for car.
if (requestWeighting == WeightingMethod.RECOMMENDED || requestWeighting == WeightingMethod.FASTEST) {
if (profileType == RoutingProfileType.DRIVING_CAR) {
weighting = VAL_FASTEST;
}
if (RoutingProfileType.isHeavyVehicle(profileType) || RoutingProfileType.isCycling(profileType) || RoutingProfileType.isWalking(profileType)) {
weighting = VAL_RECOMMENDED;
}
}

map.putObject(KEY_WEIGHTING, weighting);

if (hasTimeDependentSpeed)
map.putObject(ORSParameters.Weighting.TIME_DEPENDENT_SPEED_OR_ACCESS, true);
}
}
Loading