MapStructure Optimizations

From FlightGear wiki
Jump to navigation Jump to search
This article is a stub. You can help the wiki by expanding it.

Allocating selectable ranges into groups

visibility ranges can be mapped to Canvas groups, with visible symbols being promoted/demoted between groups as required to reduce the degree of property I/O [1]

The scale option is implemented differently, and is worth more detailed discussion. There are two scales at work here:

  1. The Range, which is used to determine what is searched for
  2. The Screen Range, which is effectively a resolution figure and closer to what we think of as scaling.

The Airport dialog uses a fixed Range, and a variable Screen Range. This is because if we just use the Range, as we zoom in the airport center may fall outside the range, but the runways/taxiways/parking should still be visible. In contrast, the map-canvas currently uses a fixed ScreenRange of 200, and the zoom-in/out function changes the Range value.[2]

When we refactored the NavDisplay, we were running into some heavy layers with -potentially- tons of symbols. Especially FIX, but possibly also parking or POI.

This is when we began using a caching scheme. However, even with the caching scheme in place, there is a noticeable delay when switching between ranges - and that is mainly because of the way the code is currently structured. While it is a fairly sophisticated scheme already, it could be much smarter without adding much in terms of complexity. The point being that we generally know about the "range of valid ranges" - as in having a list of ranges that can be toggled. For example, referring to the 777 cockpit and the range selector there:

777-200-ND-Controls.png

Now, on the devel list, Stuart mentioned already the difference between range and screen-range. However, there's actually more to it. Two more ranges:

  • selectable ranges (knobs)
  • visible range (possibly constrained by a FOV,i.e. two bearing lines)
Screenshot showing the Canvas NavDisplay with visibility ranges used for setting up dedicated Layer-specific Canvas groups

What this means is that we can be much smarter, and much more efficient, when updating the map - because we don't need to remove symbols, we may only need to "hide" them - because they may not be visible in the currently selected range, but they may be visible if one of the other selectable ranges is chosen. The point being, we can stop removing symbols like crazy when toggling between ranges and simply hide stuff that is outside our current visibility volume due to the currently chosen range and/or map mode. Thus, what we were originally talking about is treating each selectable range as a "visibility volume" that gets its own Canvas group:

/canvas/by-index/0/group/map/group/name=640nm-range

/canvas/by-index/0/group/map/group/name=320nm-range

/canvas/by-index/0/group/map/group/name=160nm-range

/canvas/by-index/0/group/map/group/name=80nm-range

/canvas/by-index/0/group/map/group/name=40nm-range

/canvas/by-index/0/group/map/group/name=20nm-range

/canvas/by-index/0/group/map/group/name=10nm-range

Symbols would be added according to their distance to the viewpoint.

that way, we don't need to toggle individual symbols on/off (hide/show), but can simply hide all layers outside the current visibility range (further away). In turn, that means that the invocation of the .onRemoved() method would no longer remove any symbols directly, but rather invoke their .hide() method and move them to the appropriate Canvas group representing the matching range.

As you can probably see, from an algorithmic/performance standpoint, this would be very much superior compared to what we're currerntly doing - especially when dealing with heavy layers (think FIX) and extreme ranges (i.e. 160/320, 640 nm) Basically, we would be dealing with one Canvas group per selectable range and then allocate/de-allocate Canvas elements using a pool of elements, where the invocation of the onAdded() and onRemoved() methods merely promotes/demotes elements between different canvas groups representing visibility ranges, so that the overall allocation overhead would also be reduced. Thus, like Thorsten and Richard said, the amount of property I/O could be greatly reduced, so that even a Nasal space solution may provide sufficient performance.[3]

Clipping invisible searchCmd results

Since property I/O is known to be the major culprit when it comes to Canvas performance, it makes sense to optimize anything that can help reduce the amount of property accesses (reads/writes). SearchCmd() as such is just a function that returns a vector of search results, for each vector element, the layer-specific symbol controller will be invokved to instantiate/animate and update the corresponding element.

Since we're -so far- only doing range-based filtering, this means we're also adding elements, and thus properties, that may not even be visible - e.g. due to the currently selected map mode and/or the FOV.

Thus, it would make sense to do additional clipping/filtering at the searchCmd() level by allowing constraints to be specified to exclude/filter entries that are not visible.

Related

References