Skip to content

feat(fr): extend French signal icons and refine parsing#814

Merged
hiddewie merged 18 commits intohiddewie:masterfrom
noeldev:feature/fr-signals-support
Feb 27, 2026
Merged

feat(fr): extend French signal icons and refine parsing#814
hiddewie merged 18 commits intohiddewie:masterfrom
noeldev:feature/fr-signals-support

Conversation

@noeldev
Copy link
Copy Markdown

@noeldev noeldev commented Feb 13, 2026

  • Added icons for primary signal states: C (Carré), Cv (Carré violet), S (Sémaphore), D (Disque), A (Avertissement), and ID (Indicateurs de directions)
  • Updated French parsing in signals_railway_signals.yaml to always display the most restrictive primary state for each signal
  • Ensures the rendered icon always represents the signal's primary state, independent of the target type

Add new icons representing various aspect states and targets for French signals.
Enhance parsing logic in signals_railway_signals.yaml for more accurate support of French signal definitions.
Refines YAML parsing logic for French light signals and adds new icons to support additional signal configurations.
Comment thread features/signals_railway_signals.yaml Outdated
- { any: [ 'FR:RR', 'FR:RRc' ], value: 'fr/C-RR' }
- { any: [ 'FR:R', 'FR:Rc' ], value: 'fr/C-R' }
- { any: [ 'FR:A', 'FR:Ac' ], value: 'fr/C-A' }
- { any: [ 'FR:VL', 'FR:VLc' ], value: 'fr/C-VL' }
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intended that there is no more matching on the possible states of the signal, in case of A/C/F/H/K shape?

Copy link
Copy Markdown
Author

@noeldev noeldev Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is intentional. Based on the latest information I have, the updated open dataset would provide the available lights for each signal head, but not an exhaustive list of all aspects the head may display. The icon therefore renders the most restrictive possible aspect. This makes the signal type immediately identifiable (C, CV, S, A or D) which is not possible with aspects like A, R, RR or VL.

Copy link
Copy Markdown
Owner

@hiddewie hiddewie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the work on the icons for the signals with the different shapes. This is valuable.

I left some comments about the matching that will not work in its current form (nested matching).

I think it would be useful to split the signals into separate features: one for dwarf and then one per signal shape. And within each feature, match on the states to show the most restrictive signal icon for that shape.

Comment thread features/signals_railway_signals.yaml Outdated
Comment thread features/signals_railway_signals.yaml Outdated
Comment thread features/signals_railway_signals.yaml Outdated
country: FR
icon:
# Check ground installation first
- match: 'railway:signal:location'
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this not normally tagged as either railway:signal:position = in_track (see https://taginfo.openstreetmap.org/keys/railway%3Asignal%3Aposition#values).

Or railway:signal:main:height = dwarf

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type of signal is installed between the tracks, not in-track like a buffer stop light.

I’ve seen railway:signal:position=ground used occasionally. It could work if we assume it implies the usual side of the track (the left side in most of France), but this remains implicit and lacks precision.

Using railway:signal:main:height=dwarf might also be misleading:

  • For FR:CARRE, dwarf refers to an actual dwarf-format head mounted high (typically indoors or under a platform roof).
  • In contrast, an FR:CV installed at ground level typically uses a standard K-type head.

Furthermore, this doesn't describe the light arrangement, which can be horizontal or vertical at ground level, whereas it is always vertical on a mast. Any ideas on how to tag this distinction?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes railway:signal:position=ground seems to be used a few times in the US (https://overpass-turbo.eu/s/2kXw):
image

And railway:signal:location=ground seems only used twice at the moment (https://overpass-turbo.eu/s/2kXx):
image

So railway:signal:position=ground makes more sense to me.

Furthermore, this doesn't describe the light arrangement, which can be horizontal or vertical at ground level, whereas it is always vertical on a mast. Any ideas on how to tag this distinction?

This could be tagged with railway:signal:*:shape, but that tag is also used for the other kind of signal shapes already.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ll switch to railway:signal:position=ground, as it is a logical complement to railway:signal:position=bridge and the other defined positions.

@noeldev
Copy link
Copy Markdown
Author

noeldev commented Feb 17, 2026

I’ve updated the code to remove the nested matching. Please let me know if this approach works.

There could be some issues with this tagging scheme if SNCF Réseau wants to maintain a unique ID per signal, sign, or board. This approach would also not work in cases where a TIV-D of the ordinary type is mixed with either a B-type or C-type TIV-D at the same position. I’ll try to get more information from the company.

@hiddewie
Copy link
Copy Markdown
Owner

I had to make 3 changes to make the pull request build and run:

  • The file Cv_A-Cv was named Cv_A_Cv so it could not be found. I renamed it to Cv_A-Cv like in the YAML
  • The fallback Carré, Carré Violet and Sémaphore features use the same icons. This is totally fine and not your fault, but at the moment the OpenRailwayMap recognises the feature on the map by its icons. So every icon can only be used in a single feature. And because the features are split, the icons have to be duplicated as well. So I duplicated some of them and added -1 to the name. Yes this is a bit stupid and I would like to solve it in general, but I don't know how yet.
  • I added railway:signal:location to the list of tags to import, because it did not exist yet, although I think it is better to use railway:signal:posititon for this instead (see comments above).

I still think it might still be useful to match the main signals on their states for the signals that have their shape tagged, and show the most restrictive non-Carré state if it is tagged. With a fallback to the current Carré if no state is tagged on the signal, like you already have in this pull request. Because even if SNCF does not expose the possible aspects of the signals in their dataset, the OSM mappers can still map it (or it could already be mapped).


For your information, current distribution of main OSM signals in France:

select "railway:signal:main", "railway:signal:main:shape", count(*) c
from signals
where "railway:signal:main" is not null
group by "railway:signal:main", "railway:signal:main:shape"
order by c desc
results
railway:signal:main railway:signal:main:shape c
FR:C null 952
FR:S FR:A 475
FR:CARRE FR:C 419
FR:CARRE FR:H 308
FR:CV FR:A 97
FR:CARRE FR:F 89
FR:S FR:F 86
FR:S null 59
FR:S FR:C 41
FR:CV null 36
FR:CARRE null 31
FR:CV FR:C 24
yes null 23
tram null 17
FR:C FR:C 15
FR:C FR:H 8
CH-FDV:l null 7
FR:GABARIT null 7
FR:CV FR:H 7
FR:GA null 7
FR:CV FR:F 6
FR:CV FR:K 4
FR:C FR:F 4
FR:S FR:H 3
FR:C C 3
FR:S FR:S 2
FR:CARRE FR:A 2
FR:S (FR:A/FR:F) (optional) 2
FR:A null 1
FR:C A 1
FR:CARRE FR:B 1
FR:C FR:A 1
FR:CARRE H 1
DE-ESO:ks null 1
light null 1
BE:GSA null 1
FR:CARRE (FR:C/FR:F/FR:H) (optional and only if railway:signal:main:height=normal) 1
CH-FDV:564 null 1

And with signal states

select "railway:signal:main", "railway:signal:main:shape", "railway:signal:main:states", count(*) c
from signals
where "railway:signal:main" is not null
group by "railway:signal:main", "railway:signal:main:shape", "railway:signal:main:states"
order by c desc
results
railway:signal:main railway:signal:main:shape railway:signal:main:states c
FR:C null null 655
FR:S FR:A {FR:A,FR:S,FR:VL} 348
FR:CARRE FR:C {FR:A,FR:C,FR:S,FR:VL} 246
FR:C null {FR:A,FR:C,FR:VL} 132
FR:CV FR:A {FR:CV,FR:M} 90
FR:CARRE FR:H {FR:A,FR:C,FR:RR,FR:S,FR:VL} 67
FR:S FR:A {FR:A,FR:(A),FR:S,FR:VL} 67
FR:C null {FR:Cv,FR:M} 51
FR:C null {FR:A,FR:C,FR:R,FR:Rc,FR:VL} 40
FR:CARRE FR:C {FR:A,FR:C,FR:M,FR:S,FR:VL} 38
FR:CARRE FR:H {FR:A,FR:C,FR:RR,FR:(RR),FR:S,FR:VL} 36
FR:CARRE FR:C {FR:A,FR:(A),FR:C,FR:S,FR:VL} 32
FR:CARRE FR:F {FR:A,FR:C,FR:R,FR:S,FR:VL} 29
FR:S FR:A {FR:A,FR:S,FR:VL,FR:(VL)} 25
FR:S null {FR:A,FR:S,FR:VL} 25
FR:S FR:C {FR:A,FR:S,FR:VL} 24
FR:CARRE FR:C {FR:C,FR:S,FR:VL} 23
FR:S FR:F {FR:A,FR:R,FR:S,FR:VL} 21
yes null null 21
FR:CARRE FR:H {FR:A,FR:C,FR:(RR),FR:S,FR:VL} 21
FR:C null {FR:C,FR:VL} 19
FR:S FR:F {FR:A,FR:R,FR:(R),FR:S,FR:VL} 19
FR:CV null {FR:CV,FR:M} 18
tram null null 17
FR:C null {FR:A,FR:C,FR:Rc,FR:VL} 17
FR:S FR:A {FR:S,FR:VL} 17
FR:CV null null 17
FR:CARRE null null 16
FR:CARRE FR:H {FR:A,FR:C,FR:R,FR:RR,FR:S,FR:VL} 15
FR:CARRE FR:C {FR:A,FR:C,FR:S,FR:VL,FR:(VL)} 15
FR:C FR:C null 14
FR:CARRE FR:H {FR:A,FR:C,FR:R,FR:(R),FR:RR,FR:(RR),FR:S,FR:VL} 14
FR:CARRE FR:H null 14
FR:S FR:F {FR:A,FR:(A),FR:R,FR:(R),FR:S,FR:VL} 14
FR:CARRE FR:H {FR:A,FR:C,FR:M,FR:RR,FR:S,FR:VL} 13
FR:CARRE FR:H {FR:A,FR:C,FR:RR,FR:S} 11
FR:CV FR:C null 11
FR:S null {FR:A,FR:S,FR:VLc,FR:VLc} 11
FR:S FR:F {FR:A,FR:(R),FR:S,FR:VL} 11
FR:CARRE FR:C {FR:C,FR:S,FR:A,FR:VL} 10
FR:S null null 10
FR:CARRE FR:C {FR:A,FR:C,FR:S} 9
FR:CARRE FR:C null 9
FR:CARRE null {FR:A,FR:C,FR:S,FR:VL} 8
FR:C null {FR:A,FR:C,FR:R,FR:VL} 8
FR:C null {FR:Cv} 8
FR:CARRE FR:H {FR:A,FR:(A),FR:C,FR:RR,FR:(RR),FR:S,FR:VL} 8
FR:CARRE FR:H {FR:A,FR:C,FR:M,FR:R,FR:RR,FR:S,FR:VL} 8
FR:CARRE FR:F {FR:A,FR:C,FR:R,FR:(R),FR:S,FR:VL} 8
FR:GABARIT null null 7
FR:CARRE FR:F {FR:C,FR:S,FR:(S),FR:M,FR:(M),FR:A,FR:(A),FR:R,FR:R+A,FR:R+(A),FR:(R),FR:(R)+A,FR:(R)+(A),FR:VL,FR:(VL)} 7
FR:C FR:H null 7
FR:CV FR:H {FR:A,FR:CV,FR:M,FR:RR} 7
FR:CV FR:A null 7
FR:GA null null 7
FR:CARRE FR:F {FR:A,FR:C,FR:(R),FR:S,FR:VL} 6
FR:S FR:C {FR:A,FR:S,FR:VL,FR:(VL)} 6
FR:CARRE FR:H {FR:A,FR:C,FR:(RR),FR:S} 6
FR:CARRE FR:F {FR:C,FR:S,FR:A,FR:(R)+(A),FR:(A),FR:(R),FR:VL} 6
FR:CARRE FR:F {FR:A,FR:C,FR:RR,FR:(RR),FR:S,FR:VL} 6
FR:CARRE FR:H {FR:A,FR:C,FR:(R),FR:(RR),FR:S,FR:VL} 6
CH-FDV:l null {CH-FDV:524,CH-FDV:542,CH-FDV:545} 5
FR:CARRE FR:H {FR:A,FR:C,FR:R,FR:(RR),FR:S,FR:VL} 5
FR:S FR:A {FR:S,FR:A,FR:VL} 5
FR:CARRE FR:H {FR:C,FR:S,FR:RR+A,FR:RR,FR:A,FR:VL} 4
FR:C null {FR:A,FR:C,FR:VL,FR:VLc} 4
FR:C FR:F null 4
FR:C null {FR:A,FR:C} 4
FR:CARRE FR:H {FR:A,FR:C,FR:(RR),FR:S,FR:VL,FR:(VL)} 4
FR:CARRE FR:F {FR:A,FR:(A),FR:C,FR:S,FR:R,FR:(R),FR:VL} 4
FR:CV FR:K {FR:CV,FR:M,FR:(M)} 4
FR:CARRE FR:C {FR:C,FR:S,FR:A,FR:(A),FR:VL} 4
FR:CARRE FR:H {FR:A,FR:C,FR:M,FR:RR,FR:(RR),FR:S,FR:VL} 4
FR:S null {FR:A,FR:R,FR:Rc,FR:S,FR:VL} 4
FR:CARRE FR:C {FR:A,FR:(A),FR:C:FR:S,FR:VL} 4
FR:CARRE FR:F {FR:A,FR:(A),FR:C,FR:R,FR:(R),FR:S,FR:VL} 4
FR:CV FR:C {FR:CV,FR:S,FR:M,FR:A,FR:(A),FR:VL} 4
FR:C C null 3
FR:C null {FR:A,FR:C,FR:R} 3
FR:CV FR:C {FR:CV,FR:S,FR:M,FR:A,FR:VL} 3
FR:CARRE FR:C {FR:C} 3
FR:CARRE FR:H {FR:C,FR:S,FR:(RR)+A,FR:(RR),FR:A,FR:VL} 3
FR:CARRE FR:C {FR:A,FR:(A),FR:C,FR:FR:S,FR:VL} 3
FR:CARRE FR:H {FR:C,FR:RR,FR:S,FR:VL} 3
FR:S FR:F {FR:A,FR:S,FR:VL} 3
FR:CARRE FR:H {FR:A,FR:C,FR:M,FR:RR,FR:S} 3
FR:S null {FR:S,FR:VL} 3
FR:S FR:C {FR:A,FR:S,FR:VL,FR:X} 3
FR:CARRE FR:H {FR:R,FR:C,FR:RR,FR:(RR),FR:S,FR:VL} 3
FR:S FR:C {FR:A,FR:C,FR:S,FR:VL} 3
FR:S null {FR:A,FR:R,FR:S,FR:VL} 3
FR:CV FR:F null 3
FR:CARRE FR:H {FR:A,FR:(A),FR:R,FR:(R),FR:RR,FR:(RR),FR:S,FR:VL} 2
FR:CARRE FR:H {FR:A,FR:C,FR:R,FR:RR,FR:(RR),FR:S} 2
FR:CARRE FR:C {FR:C,FR:S,FR:A,FR:R,FR:(R),FR:VL} 2
FR:CARRE FR:H {FR:C,FR:S,FR:RR+A,FR:RR,FR:A,FR:(R),FR:VL} 2
FR:CARRE FR:F {FR:C,FR:S,FR:A,FR:R,FR:(R),FR:VL} 2
FR:CARRE FR:H {FR:A,FR:C,FR:R,FR:(R),FR:RR,FR:S,FR:VL} 2
FR:C null {FR:C,FR:S,FR:A,FR:VL} 2
FR:CARRE FR:C {FR:C,FR:S} 2
FR:S FR:S {FR:A,FR:S,FR:VL} 2
FR:CARRE FR:F {FR:A,FR:C,FR:M,FR:R,FR:S,FR:VL} 2
FR:CARRE FR:C {FR:A,FR:C,FR:S,FR:VL,FR:X} 2
FR:CV FR:C {FR:CV,FR:S,FR:A,FR:VL} 2
FR:CARRE FR:H {FR:C,FR:S,FR:(RR)+A,FR:(RR)+(A),FR:(RR),FR:A,FR:(A),FR:VL} 2
FR:CARRE FR:F null 2
FR:CARRE FR:C {FR:C,FR:M} 2
FR:C null {FR:C} 2
FR:CARRE FR:H {FR:A,FR:C,FR:M,FR:(RR),FR:S,FR:VL} 2
FR:C null {FR:C,FR:S,FR:RR,FR:A,FR:R,FR:Rc,VL} 2
FR:CV FR:F {FR:CV,FR:S,FR:M,FR:A,FR:(R)+(A),FR:(A),FR:(R),FR:VL} 2
FR:CARRE FR:H {FR:A,FR:C,FR:S,FR:VL} 2
FR:CARRE FR:H {FR:C,FR:S,FR:RR,FR:RR+A,FR:A,FR:VL} 2
FR:CARRE FR:H {FR:A,FR:C,FR:R,FR:RR,FR:(RR),FR:S,FR:VL} 2
FR:CARRE FR:C {FR:C,FR:S,FR:A,FR:R,FR:VL} 2
FR:CARRE FR:H {FR:A,FR:C,FR:RR,S,FR:VL} 2
FR:CARRE FR:F {FR:A,FR:(A),FR:C,FR:R,FR:S,FR:VL} 2
FR:S FR:A {FR:A,FR:C,FR:S,FR:VL} 2
FR:S FR:A {FR:S,FR:(S),FR:(A),FR:(VL)} 2
FR:CARRE FR:H {FR:C,FR:S,FR:(M),FR:RR+A,FR:R,FR:(R)+(A),FR:(R),FR:A,FR:VL} 2
FR:CARRE FR:H {FR:C,FR:S,FR:(RR)+A,FR:(RR)+(A),FR:(RR),FR:A,FR:(R)+(A),FR:(A),FR:(R),FR:VL} 2
FR:CARRE FR:H {FR:C,FR:S,FR:(RR)+A,FR:(RR),FR:A,FR:(R),FR:VL} 2
FR:S (FR:A/FR:F) (optional) {FR:A,FR:S,FR:VL} 2
FR:S FR:A null 2
FR:CARRE FR:H {FR:C,FR:S,FR:(RR)+A,FR:(RR),FR:A,FR:(A),FR:VL} 2
FR:S FR:F {FR:A,FR:(R),FR:S,FR:VL,FR:(VL)} 2
FR:CARRE FR:C {FR:A,FR:M,FR:C,FR:S,FR:VL} 2
FR:S FR:F null 2
FR:S FR:F {FR:A,FR:R:FR:S,FR:VL} 2
FR:CARRE FR:H {FR:C,FR:S,FR:RR+A,FR:RR+(A),FR:RR,FR:(RR)+A,FR:(RR)+(A),FR:(RR),FR:A,FR:(R)+(A),FR:(A),FR:(R),FR:VL} 1
FR:S FR:F {FR:A,FR:C,FR:R,FR:S,FR:VL} 1
FR:CARRE H {FR:A,FR:C,FR:RR,FR:(RR),FR:S,FR:VL} 1
FR:CARRE FR:B {FR=VL,FR=A,FR=C,FR=S} 1
FR:CARRE FR:F {FR:C,FR:S,FR:A,FR:(R),FR:VL} 1
FR:CARRE FR:H {FR:C,FR:(S),FR:(RR)+A,FR:(RR),FR:A,FR:VL} 1
FR:CARRE (FR:C/FR:F/FR:H) (optional and only if railway:signal:main:height=normal) {FR:A,FR:C,FR:R,FR:(R),FR:S,FR:VL} 1
FR:CARRE FR:H {FR:C,FR:S,FR:A,FR:(R),FR:VL} 1
FR:CARRE null {FR:CV,FR:M} 1
FR:C null {FR:C,FR:R,FR:Rc} 1
FR:S FR:C {FR:S,FR:VL} 1
FR:CARRE FR:A {FR:A,FR:C,FR:S,FR:VL} 1
FR:S FR:A {FR:A,FR:C,FR:S} 1
FR:CARRE FR:F {FR:C,FR:S,FR:A,FR:R,FR:VL} 1
FR:CARRE null {FR:C,FR:S,FR:VL} 1
FR:CARRE FR:H {FR:A,FR:C,FR:R,FR:RR,FR:S} 1
FR:S null {FR:A,FR:(A),FR:S,FR:VL} 1
FR:CV null {FR:Cv,FR:M} 1
FR:S FR:F {FR:S,FR!A,FR:R,FR:(R)+(A),FR:(A),FR:(R),FR:VL} 1
FR:C FR:C {FR:A,FR:C,FR:S,FR:VL} 1
FR:CARRE FR:H {FR:A,FR:C,FR:RR,S} 1
FR:CARRE FR:H {FR:A,FR:(A),FR:C,FR:RR,FR:(RR),FR:S} 1
FR:S null {FR:S,FR:VL,FR:VLc} 1
FR:CARRE FR:F {FR:A,FR:(A),FR:R,FR:(R),FR:S,FR:VL} 1
FR:CARRE FR:H {FR:A,FR:C,FR:R,FR:S,FR:VL} 1
FR:CV FR:F {FR:A,FR:CV,FR:R,FR:S,FR:VL} 1
CH-FDV:l null null 1
FR:CARRE FR:F {FR:C,FR:S,FR:A,FR:(A),FR:VL} 1
FR:S FR:A {FR:A,FR:(A),FR:S,FR:VL,FR:X} 1
FR:C FR:A null 1
FR:CARRE FR:H {FR:C,FR:S,FR:RR+A,FR:RR,FR:A,FR:(A),FR:VL} 1
FR:CARRE FR:H {FR:A,FR:(A),FR:C,FR:R,FR:(R),FR:RR,FR:S} 1
FR:CARRE FR:C {FR:A,FR:C,FR:M,FR:RR,FR:S,FR:VL} 1
FR:S FR:F {FR:A,FR:(A),FR:C,FR:R,FR:S,FR:VL} 1
FR:CARRE FR:C {FR:VL,FR:A,FR:S,FR:C} 1
FR:CARRE FR:H {FR:C,FR:S,FR:RR,FR:RR+A,FR:RR+(A),FR:(RR),FR:(RR)+A,FR:(RR)+(A),FR:A,FR:(A),FR:VL} 1
FR:CARRE FR:C {FR:C,FR:A,FR:VL} 1
FR:S FR:F {FR:A,FR:S,FR:R,FR:(R),FR:VL,FR:(VL)} 1
FR:CARRE FR:H {FR:C,FR:S,FR:RR+A,FR:RR+(A),FR:RR} 1
FR:S FR:C {FR:A,FR:CV,FR:S,FR:VL,FR:X} 1
FR:CARRE null {FR:A,FR:C,FR:RR,FR:(RR),FR:S,FR:VL} 1
FR:S FR:A {FR:S,FR:A,FR:(A),FR:VL} 1
FR:C FR:H {FR:A,FR:C,FR:(R),FR:(RR),FR:S,FR:VL} 1
FR:CARRE FR:H {FR:A,FR:RR,FR:S} 1
FR:CARRE FR:H {FR:C,FR:S,FR:RR,FR:RR+A,FR:RR+(A),FR:A,FR:R,FR:(A),FR:VL} 1
FR:CARRE FR:H {FR:A,FR:(A),FR:C,FR:(RR),FR:S,FR:VL} 1
FR:S FR:A {FR:A,FR:R,FR:S,FR:VL} 1
FR:S FR:F {FR:S,FR:A,FR:(A),FR:VL} 1
FR:CV FR:C {FR:A,FR:CV,FR:M,FR:VL} 1
FR:CARRE FR:H {FR:A,FR:C,FR:(R),FR:(RR),FR:S} 1
FR:S FR:C {FR:C,FR:(S),FR:A,FR:VL} 1
FR:CARRE null {FR:R,FR:C,FR:RR,FR:S,FR:VL} 1
FR:CARRE FR:F {FR:A,FR:(A),FR:C,FR:(R),FR:S,FR:VL} 1
FR:CARRE FR:C {FR:A,FR:S,FR:VL} 1
FR:CARRE FR:H {FR:C,FR:S,FR:RR+A,FR:RR+(A),FR:RR,FR:(RR)+A,FR:(RR)+(A),FR:(RR)} 1
FR:CARRE null {FR:A,FR:C,FR:M,FR:S,FR:VL} 1
FR:CARRE FR:C {FR:A,FR:C,FR:RR,FR:S,FR:VL} 1
FR:CARRE FR:H {FR:A,FR:(A),FR:C,FR:R,FR:(R),FR:RR,FR:(RR),FR:S,FR:VL} 1
FR:CARRE FR:F {FR:A,FR:C,FR:RR,FR:S,FR:VL} 1
FR:CARRE FR:H {FR:A,FR:M,FR:RR,FR:S} 1
FR:S FR:F {FR:A,FR:R:FR:(R),FR:S,FR:VL,FR:X} 1
FR:CARRE FR:A {FR:A,FR:C,FR:S} 1
FR:S FR:C {FR:A,FR:(R),FR:S,FR:VL} 1
FR:CARRE FR:F {FR:C,FR:R,FR:S,FR:VL} 1
FR:CARRE FR:C {FR:A,FR:C,FR:FR:S,FR:VL} 1
FR:CARRE FR:H {FR:C,FR:S,FR:RR,FR:RR+A} 1
FR:S FR:F {FR:S,FR:A,FR:(A),FR:(R)+(A),FR:(R),FR:VL} 1
light null null 1
FR:CARRE FR:H {FR:A,FR:C,FR:S,FR:RR,FR:(RR),FR:VL} 1
FR:S FR:H {FR:A,FR:CV,FR:S,FR:VL,FR:X} 1
FR:CV FR:C {FR:A,FR:CV,FR:S,FR:VL} 1
FR:CARRE FR:F {FR:A,FR:C,FR:R,FR:S} 1
FR:CARRE FR:H {FR:C,FR:S,FR:(M),FR:RR+A,FR:RR+(A),FR:RR,FR:(RR)+A,FR:(RR)+(A),FR:(RR),FR:A,FR:VL} 1
CH-FDV:564 null null 1
FR:S FR:H {FR:A,FR:C,FR:(R),FR:R,FR:(RR),FR:S,FR:VL} 1
FR:S FR:F {FR:A,FR:(A),FR:R,FR:S,FR:(S),FR:VL} 1
FR:CARRE FR:H {FR:A,FR:RR,FR:S,FR:VL} 1
FR:C null {FR:C,FR:R,FR:Rc,FR:VL} 1
FR:S FR:A {FR:A,FR:(A),FR:FR:S,FR:VL} 1
FR:S FR:F {FR:A,FR:(A),FR:R,FR:(R),FR:S} 1
FR:S null {FR:A,FR:R,FR:S,FRc:VL} 1
BE:GSA null null 1
FR:CARRE FR:C {FR:A,FR:C,FR:(RR),FR:S,FR:VL} 1
FR:C null {FR:A,FR:C,FR:R,FR:Rc} 1
FR:CARRE FR:F {FR:C,FR:A,FR:(R),FR:VL} 1
FR:C A null 1
FR:S FR:A {"* (→ States, separated by ",)} 1
FR:CARRE FR:H {FR:C,FR:S,FR:(S),FR:RR,FR:RR+A,FR:RR+(A),FR:(RR),FR:(RR)+A,FR:(RR)+(A),FR:A,FR:(A),FR:R,FR:R+A,FR:R+(A),FR:(R),FR:(R)+A,FR:(R)+(A),FR:VL,FR:(VL)} 1
FR:CARRE FR:H {FR:C,FR:S,FR:RR+A,FR:RR+(A),FR:RR,FR:A,FR:(R)+(A),FR:(A),FR:(R),FR:VL} 1
FR:CARRE FR:H {FR:VL,FR:A,FR:S,FR:C,FR:(A),FR} 1
FR:CARRE FR:C {FR:C,FR:M,FR:S,FR:(S),FR:VL} 1
FR:S FR:A {FR:A,FR:FR:S,FR:VL} 1
FR:C null {FR:Ac,FR:C,FR:R,FR:Rc,FR:VL} 1
FR:CV FR:C {FR:A,FR:CV,FR:M,FR:(M),FR:S,FR:VL} 1
FR:CARRE FR:C {FR:C,FR:S,FR:VL,FR:(VL)} 1
FR:CARRE FR:F {FR:A,FR:(A),FR:C,FR:(R),FR:FR:S,FR:VL} 1
FR:S FR:H {FR:A,FR:RR,FR:RRc,FR:S,FR:VLc} 1
FR:S FR:F {FR:S,FR!A,FR:R,FR:(A),FR:VL} 1
FR:CARRE FR:H {FR:C,FR:M,FR:R,FR:(RR)} 1
FR:S FR:F {FR:A,FR:(A),FR:R,FR:S,FR:VL} 1
FR:A null {FR:A,FR:VL} 1
FR:CARRE FR:C {FR:A,FR:C,S,FR:VL} 1
FR:CARRE FR:F {FR:A,FR:C,FR:RR,FR:(RR),FR:S} 1
FR:C null {FR:CV,FR:M} 1
CH-FDV:l null {CH-FDV:524,CH-FDV:530,CH-FDV:542,CH-FDV:545} 1
FR:CARRE null {FR:A,FR:C,FR:RR,FR:S,FR:VL} 1
FR:CARRE FR:H {FR:C,FR:S,FR:(RR),FR:(RR)+A,FR:(R)+(A),FR:RR,FR:RR+A,FR:(R)} 1
yes null {FR:C,FR:VL,FR:RR} 1
FR:CARRE null {FR:A,FR:(A),FR:C,FR:R,FR:RR,FR:S,FR:VL} 1
FR:CARRE FR:C {FR:A,FR:(A),FR:C,FR:S,FR:VL,FR:(VL)} 1
FR:CARRE FR:H {FR:A,FR:C,FR:RR,FR:(RR),FR:S} 1
FR:CARRE FR:H {FR:R,FR:C,FR:S,FR:R,FR:(R),FR:RR,FR:(RR),FR:VL} 1
FR:CARRE FR:H {FR:C,FR:RR,FR:(RR),FR:S,FR:VL} 1
FR:S FR:C {FR:C,FR:S,FR:VL} 1
FR:CARRE FR:H {FR:A,FR:(A),FR:C,FR:(RR),FR:S} 1
FR:CV FR:C {FR:CV,FR:M} 1
yes null {FR:S,FR:VL} 1
FR:CARRE FR:H {FR:A,FR:C,FR:(R),FR:S,FR:VL} 1
DE-ESO:ks null null 1
FR:S FR:F {FR:S,FR:A,FR:R,FR:VL} 1

@hiddewie
Copy link
Copy Markdown
Owner

Great, thank you!

Some more testing after some small adjustments.

(http://localhost:8000/#view=18.93/48.8989388/2.3549344&style=signals):
image

(http://localhost:8000/#view=16.32/48.897786/2.391659&style=signals):
image

@hiddewie hiddewie enabled auto-merge (squash) February 27, 2026 23:47
@hiddewie hiddewie merged commit fa178fb into hiddewie:master Feb 27, 2026
2 checks passed
@noeldev
Copy link
Copy Markdown
Author

noeldev commented Feb 27, 2026

Thank you for the review and the fixes. The rendering gets interesting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants