GIScience / openrouteservice

🌍 The open source route planner api with plenty of features.
https://openrouteservice.org
GNU General Public License v3.0
1.43k stars 390 forks source link

Improve track grade parsing #1774

Open aoles opened 6 months ago

aoles commented 6 months ago

Problem description

When parsing combined OSM tag values of tracktype currently only values listed with ; are taken into account but not ranges listed with -. However, according to taginfo there is an order of magnitude more occurrences of the latter ones than the former ones.

# query data from taginfo
url <- "https://taginfo.openstreetmap.org/api/4/key/values?key=tracktype&filter=ways&sortname=count&sortorder=desc&qtype=value"
res <- jsonlite::fromJSON(url)$data

# number of combined range-type values
with(res, count[grepl("-", value) & grepl("grade", value)] |> sum())
#> [1] 3493

# number of combined semicolon-separated values
with(res, count[grepl(";", value) & grepl("grade", value)] |> sum())
#> [1] 296

Created on 2024-04-05 with reprex v2.0.2

Other common easy to address tagging mistakes

# query data from taginfo
url <- "https://taginfo.openstreetmap.org/api/4/key/values?key=tracktype&filter=ways&sortname=count&sortorder=desc&qtype=value"
res <- jsonlite::fromJSON(url)$data

# single-number values such as `tracktype=5`
with(res, count[grepl("^[1-5]$", value)]  |> sum())
#> [1] 125

# higher grades 
res[with(res, which(grepl("^grade[6-9]+$", value))),1:2]
#>     value count
#> 8  grade6   200
#> 10 grade7    71
#> 38 grade8     4

Created on 2024-04-05 with reprex v2.0.2

Current code for parsing tracktype values

https://github.com/GIScience/openrouteservice/blob/78ec9adf6bc9214417fa3eca7d35c76ea9a1d4a8/ors-engine/src/main/java/org/heigit/ors/routing/graphhopper/extensions/flagencoders/VehicleFlagEncoder.java#L420-L457

Proposed solution

Include parsing of grade range values provided with -.

    protected int getTrackGradeLevel(String grade) {
        if (grade == null) 
            return 0; 
        switch (grade) {
            // official values
            case "grade1":
                return 1;
            case "grade2":
                return 2;
            case "grade3":
                return 3;
            case "grade4":
                return 4;
            case "grade5":
                return 5;
            // attempt to extract meaningful values from common tagging mistakes
            case "grade6":
            case "grade7":
            case "grade8":
                return 6;
            default:
                // call specialized parsing function:
                //    split on ";" or "-"
                //    remove "grade" and trim whitespaces
                //    parse as integer and take maximum over these values and 6
                //
                //    bonus: parse single-number values such as `tracktype=5`
        }
        return 0;
    }