How to create preferred areas? (Opposite of avoid areas)

Hello,
My team is currently trying to achieve the opposite of avoid areas. We have a list of polygons which we’d like the routing algorithm to prefer. We understand this could be achieved by decreasing the weight of edges within the polygon, conversely to how the avoid areas method increases their weight. We’ve contributed code to accept this as an additional JSON parameter, but we’re not sure how to communicate this to GraphHopper, and apply a lower weight. We’ve tried following the code that the avoid areas uses, but it’s a little confusing. Any help would be appreciated. We would be prepared to modify both ORS and Graphhopper to get this to work. Thanks!

Hello,

thank you for proposing to contribute to ORS. There are basically two ways to achieve avoid areas. The ORS way employs the AvoidAreasEdgeFilter (ORS code base), which makes a binary include-or-exclude decision about each edge in method accept. I believe for your use case it is better to adapt the Graphhopper (GH) way of BlockAreasWeighting (GH code base), which adapts the weight of the edges and, therfore, realizes a softer decision. This weighting has not be used in ORS so far. In order to enable it, you should adapt the class ORSWeightingFactory (ORS code base). The new API parameter could be passed to the weighting factory through the hints map.

You will also have to ensure that ORS choses a routing algorithm, which is compatible with weight changes, otherwise the routes might be wrong. I guess, the easiest way to achieve this is to adapt method requiresFullyDynamicWeights in class RouteSearchParameters (ORS code base).

Best regards

Hello Sascha,

Thank you for your message, it’s very much appreciated. I did investigate your first suggestion, the AvoidAreasEdgeFilter class. You’re right in saying this likely wasn’t the optimal solution, as it instead made it so that only edges inside the polygon were valid, and ones outside the area were forbidden, which obviously led to a lot of incalculable routes. I suppose this is technically the exactly opposite of ‘avoiding areas’.

So I looked into your second suggestion of looking at BlockAreasWeighting. I’ve learned that the latest standalone version of GraphHopper has quite a different implementation of this class than the version of GraphHopper that ORS relies on. I’ve identified where in the ORSWeightingFactory I need to add this, but I’m having trouble with the actual implementation. I created a PreferEdgesWeighting class which mimics the AvoidEdgesWeighting class, but reduces the weight rather than increasing it (simply by flipping it from + to -. This hasn’t really worked. I think I’ve got the wrong idea. Could you provide some details on where I should be looking? Your help would be immensely appreciated as this is a blocker for our current sprint.

Many thanks,
Sam

Hello Sam,

if I understood your use case right, I believe, the AvoidEdgesWeighting is not exactly what you want because it is based on edge-ids instead of areas. Here is the relevant part of the BlockAreasWeighting I proposed:

    public double calcEdgeWeight(EdgeIteratorState edgeState, boolean reverse) {
        if (blockArea.intersects(edgeState))
            return Double.POSITIVE_INFINITY;

        return superWeighting.calcEdgeWeight(edgeState, reverse);
    }

In your PreferAreasWeighting, I would adapt the calcEdgeWeight as follows:

    public double calcEdgeWeight(EdgeIteratorState edgeState, boolean reverse) {
        double weight = superWeighting.calcEdgeWeight(edgeState, reverse); 
        if (blockArea.intersects(edgeState))
            return weight * areaPreferenceFactor;

        return weight;
    }

Where the areaPreferenceFactor comes from depends on the exact requirements of your use case.

Best reagrds,