Custom model rule to keep routes inside origin country

Hi everyone,

I’m currently working with GraphHopper 9.1 and I have a question about restricting routes to stay within the same country.

Is there any configuration I can use to prioritize routes that keep both origin and destination inside the same country, without crossing borders? For example, if both points are in Brazil, I’d like the route to remain in Brazil instead of taking a shorter path through Paraguay.

I already tried adding a custom_model rule like:

{
“priority”: [
{ “if”: “country != BRA”, “multiply_by”: 0.0 }
]
}

But I got the error: 'country' not available, which I understand happens because country is not enabled as an encoded value during the import.

My questions are:

  • Is enabling graph.encoded_values: country and reimporting the map the recommended way to achieve this?
  • Or is there another configuration (maybe using areas) that would allow me to restrict routes to stay within the origin country?

Thanks in advance for the help!

I would imagine that having the country encoded value available would be the best option here, definitely. It is not enabled by default, so you need to add that to the list of encoded values in the config before importing.

I suppose you can check the points in your app’s backend/frontend before asking GH for the route? If yes, then I can see how you can make this work.

1 Like

Is enabling graph.encoded_values: country and reimporting the map the recommended way to achieve this?

Yes.

You can make this happen too with an area as you describe without a reimport. But if the profile has CH enabled you need to reimport anyway.

Now to your specific use case of disabling general border crossing (e.g. if you want to make it working in multiple countries but don’t want to allow border crossing). Then this is not that easy in any released version. You can create an “buffered line” area that only restricts border crossing but this is probably ugly to create, especially if large countries or multiple countries are involved. Although there are tools that should make it easier (gdal?).

But you can try this branch:

and enable turn costs for the profile and then you can use the following statement in priority:

{ “if”: “country != prev_country”, “multiply_by”: 0.0 }

I suppose you can check the points in your app’s backend/frontend before asking GH for the route? If yes, then I can see how you can make this work.

Unfortunately this won’t always work as the route can still go outside of the country. See this route where start and destination are in the same country.

2 Likes

Thanks a lot for the explanation, karussell. Just one last question: if I enable graph.encoded_values: country during the import, would it be possible to only apply something like country != ‘BRA’ in specific cases?

Basically I would send that clause only when needed, so it wouldn’t affect all routes. Do you think this would work without impacting the global behavior when I don’t pass this condition?

By the way, just to clarify: when you mention the ‘buffered line’ approach, is that basically like creating restriction zones that are stored globally in the map data? In other words, would the buffered line always apply, similar to a permanent restriction, instead of being something I could enable only for specific requests.

Sure, this can work. You could also detect which country the starting point is in and then add this restriction automatically per request. Unfortunately with this approach you won’t be able to use CH. But if you have customized requests anyway this might work well and you could boost the performance a bit with LM.

In other words, would the buffered line always apply, similar to a permanent restriction, instead of being something I could enable only for specific requests.

Yes, the advantage would be that you could use CH to create a (second) profile that does not allow crossing the border.

1 Like

Just to confirm, after enabling graph.encoded_values: country, I could use a condition like this to make sure the origin and destination are in the same country and penalize the route if it crosses into another country, right?

{
“priority”: [
{ “if”: “country != prev_country”, “multiply_by”: 0.0 }
]
}

Thanks again!