Controlling drawing characteristics of non-dynamic layers using interface IDynamicCacheLayerManager


Layers that don’t implement the interface IDynamicLayer are regarded as non-dynamic layers. The dynamic display uses a tiles schema cache and upon request, rasterizes the layer as it generates its cache. This document discusses how to control the drawing characteristics of non-dynamic layers through the use of the IDynamicCacheManager Interface.

Non-dynamic layers in dynamic display

Layers that don’t implement the interface IDynamicLayer are regarded as non-dynamic layers. The dynamic display uses a tiles schema cache and upon request, rasterizes the layer as it generates its cache.

The tiling schema

The tiles schema is based on a discrete set of levels of details (LOD), meaning that tiles pertaining to a certain LOD in the cache corresponds to a certain map scale. At a given map scale, the dynamic display will determine the most suitable LOD of tiles and use these tiles in order to render the layer in the map.
Once a non-dynamic layer gets created by the dynamic display, according to the map’s projection horizon, the first LOD is being computed. The first LOD is the bounding square that bounds the projection horizon. From there, on each consecutive LOD, each tile is divided into four quarters. The information about each LOD is stored by the dynamic display and is used to determine the LOD to use along with each map scale.
Calculating the first LOD
Level of details tiles schema

Loader thread

Each non-dynamic layer has a background thread which is in charge of handling requests for tiles. As the thread gets created, the given layer is being handed to it. As the map switches into dynamic mode, the dynamic display sets requests for tiles according to the given map extent and map scale. The loader thread process these requests and either fetch the tiles from disk or generate the tiles on the spot, in the case where these tiles do not already exists.

How non-dynamic layers draw in dynamic mode

As the map switches into dynamic mode, the dynamic display, according to the given map scale, determines the best LOD to be used and sets requests for tiles onto the loader thread. At some point, these requests will be processed and tiles will be returned back to the map. The dynamic display then scale these tiles further in order to match the map’s scale and render them as requested.
Due to the existence of the background loader thread, the drawing model of the non-dynamic layers is asynchronous, meaning that once a request for a tile is set, there is no way to know when the actual tile is ready to be rendered. For that reason, the dynamic display uses several techniques in order to give the user maximum responsiveness as well as enhanced drawing user experience. These include the use of coarse grained textures which are used as the requested tiles are being processed.

The IDynamicCacheLayerManager Interface

All drawing characteristics of a non-dynamic layer can be controlled by interface IDynamicCacheLayerManager.

Using interface IDynamicCacheLayerManager in order to control the drawing characteristics

AlwaysDrawCoarsestLevel

Determines whether to use a coarse texture in case that there is no other data to draw. This might happen when a layer is required to draw tile information which pertains to a certain map scale. In such case, if by the time that the dynamic display is supposed to draw that tile, its texture is not ready, the dynamic display will use a default texture instead. As soon as the requested texture for the given tile will be ready, it will be used instead of the default texture.
The default texture is calculated according to the layer’s area of interest (it covers the entire layer and therefore can be used anywhere there is missing information):
The following diagram shows an example of how the default texture is being calculated:

Calculating the coarsest level

By default, this property is set according to the type of the layer. Any layer except point and polyline feature layers (including CAD, SDC and coverages) sets this property to true.
For some types of layers it is difficult to determine the appropriate default value, since it eventually may not contain polygonal vector data. For an instance, internet layers such as ArcGIS Server or ArcIMS can actually serve images of vector data (such as highways, railways, rivers etc.). Since there is no way to figure the type of the information served by these layers beforehand, the default is to set AlwaysDrawCoarsestLevel to true. This can lead to less effective drawing effects. So by changing AlwaysDrawCoarsestLevel to false you can modify the default behavior.
The following images show the effect of having AlwaysDrawCoarsestLevel set to true with road layer on top of a satellite image right after switching to dynamic mode and then after setting AlwaysDrawCoarsestLevel to false. Note the blurriness in the ‘before’ image:
Before setting AlwaysDrawCoarsestLevel to true:

After setting AlwaysDrawCoarsestLevel to false:

DetailsThreshold

The DetailsThreshold is the threshold to determine the level of detail to use. The cache for non-dynamic layers is composed of discrete levels of details. Each level of detail corresponds to a specific map scale. In order to draw the cached tiles in the map, the dynamic display has to choose an appropriate level of detail and resample it further in order to scale it to the current map scale (which might be slightly different from the one that corresponds to the given level of detail). For that reason, most given map scales will fall within two levels of detail of the cache. Choosing the coarsest level of detail (the one whose scale is smaller than the map scale) may result in a blurry display because of the stretching effect. Alternatively, choosing the more detailed level of detail may lead to too many tiles that are needed to be drawn in the display and eventually degrade performance. For that reason, the dynamic display is calculating a ‘normalized distance’ which is the normalized value of the scale difference between the maps’ current scale to the coarse level of detail scale divided by the difference between the coarse level of detail scale and the more detailed level of detail scale.

The threshold determines the normalized value by which the coarse level of detail will be preferred to, over the more detailed one.
For instance, a threshold value set to 0.85 means that as long as the scale difference between the map and the coarse LOD is below 85% of the difference between the scale of the coarse LOD and the finer LOD, the coarse LOD will be chosen over the more detailed one.
In order to favor the more detailed LOD, you should decrease the threshold.

MaxCacheScale

The maximum scale by which tiles are to be generated. Setting this value to a value other than 0, sets the maximum scale in which tiles can be generated. This property is very useful with raster layers that have a specified resolution (cell-size) and it is clear that beyond a certain map scale, there is no point in generating additional tiles.

ProgressiveDrawingLevels

Number of coarse level data to draw while the current LOD tiles are being processed.
In order to give the user a better visual experience, the dynamic display can use several levels of coarse textures to be rendered while it waits for the background thread to finish processing the data for the current map scale (and therefore the appropriate level of detail). The user can control the number of coarse textures by setting properties ProgressiveDrawingLevels and ProgressiveFetchingLevels, where ProgressiveDrawingLevels sets the number of level of details the dynamic display will search in memory to get a coarse texture. Property ProgressiveFetchingLevels sets the number of levels of details for which the dynamic display will set requests to actually fetch data on the background thread in case where this data was not found in memory.
In case where the number set to ProgressiveDrawingLevels is smaller than the value set to ProgressiveFetchingLevels, it would limit ProgressiveFetchingLevels to the number set to ProgressiveDrawingLevels.
By default, for layers that use a default texture (AlwaysDrawCoarsestLevel is set to true), the value for ProgressiveDrawingLevels is set to 31, meaning that in a case where there is a missing texture, the dynamic display will search for a coarse texture starting from the level of detail above the calculated one and will continue searching all the way until the level of detail that defines the default texture for the layer.
For layers that do not use a default texture (point and line feature classes), ProgressiveDrawingLevels value is set to one, meaning that in case where the texture for the requested level of detail is not ready it will only search up one level in memory in order to find a coarse texture.

ProgressiveFetchingLevels

Number of coarse level data to draw while the current LOD tiles are being processed.
In order to give the user a better visual experience, the dynamic display can use several levels of coarse textures to be rendered while it waits for the background thread to finish processing the data for the current map scale (and therefore the appropriate level of detail). The user can control the number of coarse textures by setting properties ProgressiveDrawingLevels and ProgressiveFetchingLevels, where ProgressiveDrawingLevels sets the number of level of details the dynamic display will search in memory to get a coarse texture. Property ProgressiveFetchingLevels sets the number of levels of details for which the dynamic display will set requests to actually fetch data on the background thread in case where this data was not found in memory.
Property StrictOnDemandMode forces the dynamic display to set tiles requests only for the current map scale and logically sets ProgressiveFetchingLevels to zero.
By default, all layers are set to work using StrictOnDemandMode = true in order to give for best total drawing speed.
When setting this property to false, especially with raster layers, the user experience is much better, although the total drawing time is about 30% longer.

Being overridden by ProgressiveDrawingLevels and StrictOnDemandMode

StrictOnDemandMode

When set to true, restrict the dynamic display from setting requests for tiles other than tiles for the current calculated level of detail (with the exception of the coarse level tile when it is required).
In order to give the user a better visual experience, the dynamic display can use several levels of coarse textures to be rendered while it waits for the background thread to finish processing the data for the current map scale (and therefore the appropriate level of detail). The user can control the number of coarse textures by setting properties ProgressiveDrawingLevels and ProgressiveFetchingLevels, where ProgressiveDrawingLevels sets the number of level of details the dynamic display will search in memory to get a coarse texture. Property ProgressiveFetchingLevels sets the number of levels of details for which the dynamic display will set requests to actually fetch data on the background thread in case where this data was not found in memory. So setting StrictOnDemandMode forces the dynamic display to set tiles requests only for the current map scale and logically sets ProgressiveFetchingLevels to zero.
By default, all layers are set to work using StrictOnDemandMode = true in order to give for best total drawing speed.
When setting this property to false, especially with raster layers, the user experience is much better, although the total drawing time is about 30% longer.

ConsolidatedGroupLayer

By default, the dynamic display creates a separate cache for each individual layer in the map. At runtime, each cache is translated into textures when it comes to displaying the cache in dynamic mode. This means that when displayed, each layer is rendered as a sequence of adjacent textures in the form of seamless tiles. Each of these textures eventually takes a certain amount of memory on the graphics card.
In order to minimize the amount of texture memory used by the dynamic display, by default, any layers that pertain to a composite layer (which also includes a group layers) are being consolidated into one cache and therefore regardless of the number of layers contained in the composite layer, there will only be one cache to manage and one set of textures for the entire group layer.
This solution, also adds a huge improvements in term of performance and resource conservation has some limitations:
If a user reorders layers or turns layers visibility on or off inside the group layer, than the dynamic display will be forced to rebuild the cache each time that such action happens. For some users that uses group layers in order to bundle layers together, this may not be the preferred behavior and therefore by setting ConsolidatedGroupLayer to false they can force the dynamic display to handle of the group layers’ sub-layers separately. This will enable uses to turn any of the sub-layers visibility on and off and reorder layers without regenerating of the cache.
In case that the parent group layer has a sub-layer that is a group layer by itself, it is consolidated by default (just like any other group layer in the map).