Modify

#22822 closed enhancement (fixed)

Add runway heading (ref) validator

Reported by: gaben Owned by: gaben
Priority: normal Milestone:
Component: External rule Version:
Keywords: runway heading ref Cc:

Description

Tag:aeroway=runways have reference numbers and the numbers contain the heading of the ways determined by the magnetic azimuth in that place.

OSM wiki is saying:

The two designators of a runway will always differ by 18 (180 degrees) and can have one letter appended (L, C, or R)

L = left
C = center
R = right

in addition:
S = STOL runway
G = glider runway
W = water sealane or waterway and
U = ultralight runway

See also https://en.wikipedia.org/wiki/Runway#Naming

and https://www.faa.gov/documentLibrary/media/advisory_circular/150-5200-35/150_5200_35.pdf

Attachments (1)

runway.validator.mapcss (6.1 KB ) - added by gaben 21 months ago.
result

Download all attachments as: .zip

Change History (17)

comment:1 by gaben, 21 months ago

Component: Core validatorExternal rule
Owner: changed from team to gaben

An external rule may be a better fit, as the current OSM planet has only ~2000 problematic ways (~3% error rate).

comment:2 by gaben, 21 months ago

I wrote a Java version and the following MapCSS rule produces the same output on OSM planet, although more strict (~200 ways) than the original.

/* #22822 - runway heading validator */
way[aeroway=runway][ref][ref =~ /^([0-9]{1,3}[LCRWSGU]? ?- ?[0-9]{1,3}[LCRWSGU]?)$/][eval(to_int(get(regexp_match(".*?([0-9]+).*", get(split("-", tag("ref")), 1)), 1)) >= to_int(get(regexp_match(".*?([0-9]+).*", get(split("-", tag("ref")), 0)), 1)))][eval(to_int(get(regexp_match(".*?([0-9]+).*", get(split("-", tag("ref")), 1)), 1)) - to_int(get(regexp_match(".*?([0-9]+).*", get(split("-", tag("ref")), 0)), 1))) != 18],
way[aeroway=runway][ref][ref =~ /^([0-9]{1,3}[LCRWSGU]? ?- ?[0-9]{1,3}[LCRWSGU]?)$/][eval(to_int(get(regexp_match(".*?([0-9]+).*", get(split("-", tag("ref")), 0)), 1)) >= to_int(get(regexp_match(".*?([0-9]+).*", get(split("-", tag("ref")), 1)), 1)))][eval(to_int(get(regexp_match(".*?([0-9]+).*", get(split("-", tag("ref")), 0)), 1)) - to_int(get(regexp_match(".*?([0-9]+).*", get(split("-", tag("ref")), 1)), 1))) != 18],
way[aeroway=runway][ref][ref =~ /^([0-9]{1,3}[LCRWSGU]? ?\/ ?[0-9]{1,3}[LCRWSGU]?)$/][eval(to_int(get(regexp_match(".*?([0-9]+).*", get(split("/", tag("ref")), 1)), 1)) >= to_int(get(regexp_match(".*?([0-9]+).*", get(split("/", tag("ref")), 0)), 1)))][eval(to_int(get(regexp_match(".*?([0-9]+).*", get(split("/", tag("ref")), 1)), 1)) - to_int(get(regexp_match(".*?([0-9]+).*", get(split("/", tag("ref")), 0)), 1))) != 18],
way[aeroway=runway][ref][ref =~ /^([0-9]{1,3}[LCRWSGU]? ?\/ ?[0-9]{1,3}[LCRWSGU]?)$/][eval(to_int(get(regexp_match(".*?([0-9]+).*", get(split("/", tag("ref")), 0)), 1)) >= to_int(get(regexp_match(".*?([0-9]+).*", get(split("/", tag("ref")), 1)), 1)))][eval(to_int(get(regexp_match(".*?([0-9]+).*", get(split("/", tag("ref")), 0)), 1)) - to_int(get(regexp_match(".*?([0-9]+).*", get(split("/", tag("ref")), 1)), 1))) != 18] {
  throwError: tr("Runway reference numbers don''t follow the 180 degree rule");
  assertMatch: "way aeroway=runway ref=01-02";
  assertMatch: "way aeroway=runway ref=17W-36W";
  assertMatch: "way aeroway=runway ref=36W-17W";
  assertMatch: "way aeroway=runway ref=01/01";
  assertNoMatch: "way aeroway=runway ref=01-19";
  assertNoMatch: "way aeroway=runway ref=36/18";
  assertNoMatch: "way aeroway=runway ref=3/21";
  assertNoMatch: "way aeroway=runway ref=09L/27R";
}
Last edited 21 months ago by gaben (previous) (diff)

comment:3 by skyper, 21 months ago

According to Tag:aeroway=runway the smallest designator should be listed first, e.g. ref=36/18 is wrong and should be ref=18/36.

comment:4 by gaben, 21 months ago

Yes, it is wrong. The above rule only checks for the difference. I can add another one with a different, clear message for cases where the first number is used as a bigger designator.

(I'm going to edit the previous comment with the result.)

comment:5 by skyper, 21 months ago

Maybe, it is better to split the rule as the wrong separator and the wrong order (bigger designator in front) might work with an auto-fix if the rest is ok.

comment:6 by gaben, 21 months ago

Thanks, good point.

While writing the new rule, I noticed a weird thing:

way[aeroway=runway][ref =~ /^[0-9]- ?[0-9]$/] {
  throwError: tr("Runway reference - designators should be in increasing order");
  assertMatch: "way aeroway=runway ref=2- 1";
}

Spaces for some reason don't want to work in regexes, @skyper do you have an idea what I'm messing up?

comment:7 by skyper, 21 months ago

Try [ ]? or remove empty spaces in advance.

Edit: There is some escape symbol for assertMatch but I forgot which one and have no time to look it up, atm. Sorry.

Last edited 21 months ago by skyper (previous) (diff)

comment:8 by gaben, 21 months ago

I'd like to filter by valid values first, so I need spaces. Unfortunately the following doesn't work either :(

way[aeroway=runway][ref =~ /^([0-9]-[ ]?[0-9])$/] {
  throwError: tr("Runway reference - designators should be in increasing order");
  assertMatch: "way aeroway=runway ref=1- 2";
}

comment:9 by Famlam, 21 months ago

Try "way aeroway=runway ref=\"1- 2\""; for your assert. That way, it understands the space is part of the tag value.

Last edited 21 months ago by Famlam (previous) (diff)

in reply to:  8 comment:10 by skyper, 21 months ago

Replying to Famlam:

Try "way aeroway=runway ref=\"1- 2\""; for your assert. That way, it understands the space is part of the tag value.

Thanks, that's what I was looking for.

Replying to gaben:

I'd like to filter by valid values first, so I need spaces. Unfortunately the following doesn't work either :(

way[aeroway=runway][ref =~ /^([0-9]-[ ]?[0-9])$/] {
  throwError: tr("Runway reference - designators should be in increasing order");
  assertMatch: "way aeroway=runway ref=1- 2";
}

I have tested the expression in JOSM search and it works. Was it only a problem with the white space in the value in the assert?

in reply to:  5 comment:11 by gaben, 21 months ago

Yay, thanks! Now the assertions working fine.

Replying to skyper:

Maybe, it is better to split the rule as the wrong separator and the wrong order (bigger designator in front) might work with an auto-fix if the rest is ok.

I'm not so familiar with MapCSS, how can I auto correct a value with MapCSS, e.g.

  • ref=15-33 to ref=15/33 or
  • ref=18 /36 to ref=18/36?

I already wrote the Java validator, just in case :)

comment:12 by skyper, 21 months ago

Looks like MapCSSTagChecker could benefit from more detailed descriptions. Looking through existing rules (trunk/resources/data/validator/), especially numeric.mapcss in your case, might help.
Basically, I comes down to overwriting the tag with fixAdd: using eval expressions. Be aware of the java docs for MapCSS functions and regular expressions.

For the two easy examples the replace function should work, e.g.:

fixAdd: concat("ref=", replace(replace(tag("ref"), "-", "/")), " ", "");
Last edited 21 months ago by gaben (previous) (diff)

by gaben, 21 months ago

Attachment: runway.validator.mapcss added

result

comment:13 by gaben, 21 months ago

I plan to add the uploaded rule to the Rules, probably next week.

comment:14 by Famlam, 21 months ago

Those rules look monstrous, nice :D

Maybe in the final release version please comment out the asserts of the first check (with add this line to pass tests... I think it's a bug) or it'll spam my console output continuously :).

p.s.: it seems it's unnecessary to call eval(...), it also works without

Last edited 21 months ago by Famlam (previous) (diff)

in reply to:  14 comment:15 by gaben, 21 months ago

Replying to Famlam:

Those rules look monstrous, nice :D

They are the least understandable "code" I ever wrote, I'm proud of them :D

Maybe in the final release version please comment out the asserts of the first check (with add this line to pass tests... I think it's a bug) or it'll spam my console output continuously :).

I'm currently trying to figure out why. It seems the throwError and assertMatch goes hand in hand. Without throwError the assertMatch is not working.

p.s.: it seems it's unnecessary to call eval(...), it also works without

Thanks, I'll check it.

comment:16 by gaben, 20 months ago

Resolution: fixed
Status: newclosed

Hey there!

The new runway rule has been created and is currently being processed. It's available among the rules in the Rules/Runways section.

If you have any feedback or ideas for improvement, please let me know :)

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain gaben.
as The resolution will be set.
The resolution will be deleted. Next status will be 'reopened'.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.