Extended runway validator rules
See JOSM #22822 - runway heading validator
The ref=* values should follow the general rule:
[digit:1-3][designator]/[digit:1-3][designator]
Mentioned/described in:
- https://www.faa.gov/documentLibrary/media/Advisory_Circular/AMR_Data_Dictionary_2022_10_14.pdf
- https://www.faa.gov/documentLibrary/media/advisory_circular/150-5200-35/150_5200_35.pdf
- https://aviation.stackexchange.com/questions/71863/why-is-it-runway-1-instead-of-01-in-america
Possible designators are:
- L left
- C center
- R right
- W water sealane or waterway
- S STOL runway
- G glider runway
- U ultralight runway
meta { title: "Extended runway rules"; version: "1_2023-04-02"; description: "Extending core runway validation rules. Currently validating ref values and offering autofix for runways drawn as an area."; author: "gaben"; link: "https://josm.openstreetmap.de/wiki/Rules/Runways"; min-josm-version: "11424"; /* due to territory selectors */ baselanguage: "en"; } /* raising error only if {first designator >= the second designator} */ way[aeroway=runway][ref =~ /^([0-9]{1,3}[LCRWSGU]? ?[-,;\/\\] ?[0-9]{1,3}[LCRWSGU]?)$/][to_int(get(regexp_match("^([0-9]+)[LCRWSGU]? ?[-,;\\/] ?([0-9]+)[LCRWSGU]?$", tag("ref")), 1)) >= to_int(get(regexp_match("^([0-9]+)[LCRWSGU]? ?[-,;\\/] ?([0-9]+)[LCRWSGU]?$", tag("ref")), 2))] { group: tr("runway reference"); set runwayDesignatorOrderIssue; /*assertMatch: "way aeroway=runway ref=02-01"; assertMatch: "way aeroway=runway ref=\"2- 1\""; assertMatch: "way aeroway=runway ref=\"2 - 1\""; assertMatch: "way aeroway=runway ref=36/18"; assertMatch: "way aeroway=runway ref=36W-17W"; assertMatch: "way aeroway=runway ref=01/01";*/ /* assertMatch: "way aeroway=runway ref=\"36\18\""; not working, even raises a GUI exception :( */ assertNoMatch: "way aeroway=runway ref=17W-36W"; assertNoMatch: "way aeroway=runway ref=01- 02"; assertNoMatch: "way aeroway=runway ref=03G/12G"; assertNoMatch: "way aeroway=runway ref=01-19"; assertNoMatch: "way aeroway=runway ref=3/21"; assertNoMatch: "way aeroway=runway ref=09L/27R"; } /* raising error only if {second designator - first designator != 18} [global version] */ way[aeroway=runway][ref =~ /^([0-9]{1,2}[LCRWSGU]? ?[-,;\/\\] ?[0-9]{1,2}[LCRWSGU]?)$/][to_int(get(regexp_match("^([0-9]+)[LCRWSGU]? ?[-,;\\/] ?([0-9]+)[LCRWSGU]?$", tag("ref")), 2)) - to_int(get(regexp_match("^([0-9]+)[LCRWSGU]? ?[-,;\\/] ?([0-9]+)[LCRWSGU]?$", tag("ref")), 1)) != 18]!.runwayDesignatorOrderIssue { group: tr("runway reference"); set global180RuleIssue; throwError: tr("numbers not following the 180 degree rule (global version)"); assertMatch: "way aeroway=runway ref=\"01 -02R\""; assertMatch: "way aeroway=runway ref=17W-36W"; assertMatch: "way aeroway=runway ref=\"01/ 02\""; assertMatch: "way aeroway=runway ref=03G/12G"; assertNoMatch: "way aeroway=runway ref=01-19"; assertNoMatch: "way aeroway=runway ref=\"3 / 21\""; assertNoMatch: "way aeroway=runway ref=09L/27R"; } /* raising error only if {second designator - first designator != 180} [American version] */ way[aeroway=runway][ref =~ /^([0-9]{1,3}[LCRWSGU]? ?[-,;\/\\] ?[0-9]{3}[LCRWSGU]?)$/][to_int(get(regexp_match("^([0-9]+)[LCRWSGU]? ?[-,;\\/] ?([0-9]+)[LCRWSGU]?$", tag("ref")), 2)) - to_int(get(regexp_match("^([0-9]+)[LCRWSGU]? ?[-,;\\/] ?([0-9]+)[LCRWSGU]?$", tag("ref")), 1)) != 180]!.runwayDesignatorOrderIssue { group: tr("runway reference"); set american180RuleIssue; throwError: tr("numbers not following the 180 degree rule (American version)"); assertMatch: "way aeroway=runway ref=170W-360W"; assertMatch: "way aeroway=runway ref=\"10/ 100\""; assertMatch: "way aeroway=runway ref=30G/120G"; assertNoMatch: "way aeroway=runway ref=10-190"; assertNoMatch: "way aeroway=runway ref=\"30 / 210\""; assertNoMatch: "way aeroway=runway ref=09L/27R"; } /* offer heading separator fix */ way[aeroway=runway][ref =~ /^([0-9]{1,3}[LCRWSGU]? [-,;\/\\][0-9]{1,3}[LCRWSGU]?)$/]!.runwayDesignatorOrderIssue!.global180RuleIssue!.american180RuleIssue, way[aeroway=runway][ref =~ /^([0-9]{1,3}[LCRWSGU]?[-,;\/\\] [0-9]{1,3}[LCRWSGU]?)$/]!.runwayDesignatorOrderIssue!.global180RuleIssue!.american180RuleIssue, way[aeroway=runway][ref =~ /^([0-9]{1,3}[LCRWSGU]? [-,;\/\\] [0-9]{1,3}[LCRWSGU]?)$/]!.runwayDesignatorOrderIssue!.global180RuleIssue!.american180RuleIssue { group: tr("runway reference"); assertMatch: "way aeroway=runway ref=\"09L /27R\""; assertMatch: "way aeroway=runway ref=\"09L/ 27R\""; assertNoMatch: "way aeroway=runway ref=09L/27R"; throwWarning: tr("values can be prettified, separator"); fixAdd: concat("ref=", eval(get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 1) > get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 2)) ? get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 2) : get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 1) , "/", eval(get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 1) > get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 2)) ? get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 1) : get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 2)); } /* offer heading order fix */ way[aeroway=runway].runwayDesignatorOrderIssue!.global180RuleIssue!.american180RuleIssue { group: tr("runway reference"); throwError: tr("designators should be in increasing order"); fixAdd: concat("ref=", eval(get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 1) > get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 2)) ? get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 2) : get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 1) , "/", eval(get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 1) > get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 2)) ? get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 1) : get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 2)); } /* offer heading leading zero fix (except USA, Mexico) */ way[aeroway=runway][outside("US,MX")][ref =~ /^([0-9]{1}[LCRWSGU]? ?[-,;\/\\] ?[0-9]{1,3}[LCRWSGU]?)$/]!.runwayDesignatorOrderIssue!.global180RuleIssue!.american180RuleIssue { group: tr("runway reference"); assertMatch: "way aeroway=runway ref=9L/27R"; assertNoMatch: "way aeroway=runway ref=09L/27R"; throwWarning: tr("values can be prettified, leading zero"); fixAdd: concat("ref=0", get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 1), "/", get(regexp_match("^([0-9]+[LCRWSGU]?) ?[-,;\\/] ?([0-9]+[LCRWSGU]?)$", tag("ref")), 2)); } /*** NOW SOMETHING DIFFERENT - restrict runways to unclosed ways and offer autofix to area:aeroway. See https://wiki.openstreetmap.org/wiki/Tag:aeroway%3Drunway#How_to_map */ way:closed[aeroway=runway] { throwWarning: tr("{0} on a closed way. Should be used on an unclosed way.", "{1.tag}"); suggestAlternative: "area:aeroway=runway"; fixAdd: "area:aeroway=runway"; fixRemove: "aeroway"; fixRemove: "area"; }
Last modified
18 months ago
Last modified on 2023-04-02T20:43:48+02:00
Note:
See TracWiki
for help on using the wiki.