Rendering dynamic map content


The Dynamic Display renders the Standard Layers and Standard Graphics in the background, and has an ability to render Dynamic Map Content with the use of Dynamic Layers and Dynamic Map Drawings. This document discusses the use of symbols, glyphs, drawing methods, compound makers, array markers and the different drawing phases, immediate versus compiled drawing phases.
The Dynamic Display is an active Display, which means it has its own heart bit in which it is actively checks the display status, and causes the display to be redrawn or repainted when needed.
The Dynamic Display renders the Standard Layers and Standard Graphics in the background, and has an ability to render Dynamic Map Content with the use of Dynamic Layers and Dynamic Map Drawings. The “Standard Layers and Standard Graphics” will be referred here as “Standard Layers”.
There are two ways to render Dynamic Map Content:
  1. Dynamic Layer – having a Custom Layer implement IDynamicLayer, and draw dynamic content from the callback method IDynamicLayer.DrawDynamicLayer. These kind of layers will show as any standard layer in the map’s layer list and in the TOC, and therefore will be able to be reordered between any other layers. This is useful for a dynamic content that needs to be grouped together and treated as a layer, for example tracks that can be reordered and\or de-cluttered using a TOC or the layer’s API.
  2. Dynamic Map Drawing – listening to the IDynamicMapEvents BeforeDynamicDraw and AfterDynamicDraw events, and draw dynamic content in those events. This dynamic content will be drawn before or after all of the map’s layers, respectively, and will not be visible in the map’s layers list and in the TOC. This is useful for content that is not identified as a layer, for example a compass or navigation data that needs to be rendered on top of all of the map’s layers.
The IDynamicLayer.DrawDynamicLayer method and the IDynamicMapEvents BeforeDynamicDraw and AfterDynamicDraw events, will be referred here as “Dynamic Draw Callbacks”.
Drawing Dynamic Content is done by using the Dynamic Display API and\or OpenGL API. Before invoking the Dynamic Draw Callbacks, the Dynamic Map is setting up an active OpenGL rendering context, as well as passing in a reference to an active DynamicDisplay with the method\event invocation. Therefore, in the Dynamic Draw Callbacks (method\event-handlers) context, the DynamicDisplay API as well as the OpenGL API can be utilized in order to draw any Dynamic Content.

Dynamic Symbols

The Dynamic Display object has four active Dynamic Symbols at all times:
  1. Dynamic Marker Symbol
  2. Dynamic Line Symbol
  3. Dynamic Text Symbol
  4. Dynamic Fill Symbol
The current state of these four Dynamic Symbols is used to determine how the drawing will be rendered, when the Dynamic Display draw methods are called.
Use the IDynamicSymbolProperties in order to change the current state of the DynamicSymbols. There are two types of methods and properties on IDynamicSymbolProperties, ‘Generic’ and ‘Specific’. The Generic ones take an extra parameter, the type of the Dynamic Symbol, and will change the state of the passed in Dynamic Symbol type. The Specific ones are specific to a Dynamic Symbol type, therefore their name will start with the type of the Dynamic Symbol (e.g. – “Text Leading” is specific to Dynamic Text Symbol).
The following table shows the properties of each Dynamic Symbol:
Property
Generic/Specific
Dynamic Text Symbol
Dynamic Marker Symbol
Dynamic Line Symbol
Dynamic Fill Symbol
Dynamic Glyph
G
+
+
+
+
Color
G
+
+
+
+
Scale (x,y)
G
+
+
+
+
Smooth
G
+
+
+
+
Offset (x,y)
G
+
+
+
+
Use Reference Scale
G
+
+
+
+
Heading
G
+
+
 
+
Rotation Alignment
G
+
+
 
+
Text Vertical Alignment
S
+
 
 
 
Text Horizontal Alignment
S
+
 
 
 
Text Leading
S
+
 
 
 
Text Character Spacing
S
+
 
 
 
Text Word Spacing
S
+
 
 
 
Text Right To Left
S
+
 
 
 
Text Box Horizontal Alignment
S
+
 
 
 
Text Box Use Dynamic Fill Symbol
S
+
 
 
 
Text Box Use Dynamic Line Symbol
S
+
 
 
 
Text Box Margins
S
+
 
 
 
Line Continue Pattern
S
 
 
+
 

Dynamic Glyphs

A Dynamic Glyph is a handle to a graphic resource. The Dynamic Glyph Factory needs to be used in order to create and delete Dynamic Glyphs.
There are four types of Dynamic Glyphs:
  1. Dynamic Marker Glyph
  2. Dynamic Line Glyph
  3. Dynamic Text Glyph
  4. Dynamic Fill Glyph
It is important to correctly manage the Dynamic Glyphs, in order to minimize the application memory usage. Incorrect management of Dynamic Glyphs will lead to over consumption of resources, and might result in poor performance and even an application crash. Try to minimize the Dynamic Glyphs creation and reuse created Dynamic Glyphs as much as possible. For example - create a Dynamic Glyph from a white symbol, set the Dynamic Symbol’s glyph property to use the created Dynamic Glyph, and use the Dynamic Symbol’s color and scale properties, in order to render the Dynamic Symbol (that uses one created Dynamic Glyph) in different colors and sizes.
When a Dynamic Glyph is not in use anymore, use the IDynamicGlyphFactory’s DeleteDynamicGlyph method in order to release the Dynamic Glyph’s resources. Dynamic Glyphs can be created from file, from a symbol, from a Glyphs Group or from a handle to a bitmap.

Dynamic Glyphs Group

A Dynamic Glyphs Group is a container that holds multiple glyphs. It is composed of a bitmap and a database that holds information about the group and the elements (glyphs and glyphs’ items) in the group. The image is a mosaic of sub-images of icons (marker glyphs), lines (line glyphs), and groups of characters (each group composes a text glyph). The bitmap holds color information (Red, Green, Blue, and Alpha values) for each pixel. The bitmap can be loaded from two file images - one that holds the RGB values, and a second one that holds the ALPHA values, or from a single file image that holds RGBA values. The Glyphs Group database is loaded from an XML file. This XML file holds general information about the group, and specific location and size information for each of the items and elements of the group. A new Glyphs Group can be loaded using the IDynamicGlyphFactory.LoadDynamicGlyphsGroup method. The method creates a Glyphs Group, and returns an allocated Glyphs Group ID. The returned ID is a positive integer. GroupID 0 refers to rendering without using an actual graphical resource, meaning simple lines, simple points, etc. Glyphs Group ID 1 is reserved to be the default Glyphs Group, and there is a default one that already exists with the Dynamic Display, and supplies a default set of Dynamic Glyphs. In order to replace the preloaded default group, delete group ID 1, and immediately create a new group. The Dynamic Map will assign the new group ID 1, and use it as the new default Glyphs Group. Performance wise, it is preferable to create a Glyph Group with multiple glyphs, and use the glyphs from the group, rather than creating glyphs from individual image files.
The Dynamic Glyphs Factory is a singleton object; therefore you can always co-create it in order to use it to create and delete dynamic glyphs. Performance wise, it is preferable to create the dynamic glyphs in the context of the IDynamicLayer’s DrawDynamicLayer method, in the esriDDPImmediate draw phase, or in the context of the IDynamicMapEvents BeforeDynamicDraw or AfterDynamicDraw method, while casting the passed in IDynamicDisplay interface to IDynamicGlyphFactory. See also: System.__ComObject and casting to strongly typed RCWs"

Dynamic Display Draw Methods

The Dynamic Display draw methods can be used in order to draw Marker, MultipleMarkers, Line, MultipleLines, Polyline, Polygon, Rectangle, Text, and compound items that include a Marker and some text strings around it. Each draw method gets a point location, and comes in the flavors – map coordinates, or screen (pixel) coordinates:
  1. Map Coordinates – items that will be drawn using these methods will move together with the map (when panning, rotating, navigating by changing the visible bounds, etc.)
  2. Screen Coordinates – items that will be drawn using these methods will be drawn on the screen, and will not be affected by the map’s navigation. The origin of the screen is the lower left corner of the screen, while x values are growing towards the right, and y values are growing towards the top.
Following is a table that shows the correlations of the Dynamic Display’s draw methods on the current state of each Dynamic Symbol:
Draw Method
Dynamic Marker Symbol
Dynamic Text Symbol
Dynamic Line Symbol
Dynamic Fill Symbol
Marker
+
 
 
 
MultipleMarkers
+
 
 
 
Line
 
 
+
 
Polyline
 
 
+
 
Polyline
 
 
+
 
Polygon
 
 
+
(Polygon's Outline)
+
(Polygon's Fill)
Rectangle
 
 
+
(Rectangle's Outline)
+
(Rectangle's Fill)
Text
 
+
+
(TextBox Outline)
+
(TextBox Fill)
CompountMarker*
+
+
+
(TextBox Outline)
+
(TextBox Fill)
ArrayMarker
+
+
+
(TextBox Outline)
+
(TextBox Fill)

When drawing markers and lines, if a Dynamic Glyph that was created from Group ID 0 (or no dynamic glyph) is set to the corresponding dynamic symbol, the Dynamic Display will render simple points and simple lines.

Dynamic Layer

A dynamic layer is a custom layer. At minimum, each dynamic layer must implement the interfaces ILayer, IDynamicLayer and IGeoDataset.
Since a dynamic layer is a custom layer, the implementer needs to implement the underlying data structure of the layer as well as the drawing, selection, identification etc. Since a dynamic layer is implementing both IDynamicLayer and ILayer, it actually has two drawing methods. The IDynamicLayer.DrawDynamicLayer method will get called when the dynamic map is enabled and ILayer.Draw method will get called when the dynamic map is disabled. That way, if your layer must draw both in standard drawing mode and in dynamic mode, you can implement both methods. When implementing the IDynamicLayer.DrawDynamicLayer method, use the Dynamic Display API and/or the OpenGL API. When implementing the ILayer.Draw method, use the standard drawing commands (e.g. ISymbol.Draw) and/or GDI/GDI+ API.

Immediate vs. Compiled Drawing Phases

Dynamic layers can be drawn in two different ways, and therefore have two drawing phases – immediate and compiled. In each of them, when a new set of draw commands need to be generated, the DrawDynamicLayer method needs to iterate through the layer’s underlying data-structure and generate the corresponding draw commands for each item. In the compiled phase the draw commands are being compiled into an internal dedicated Display List of the Dynamic Layer.
Every dynamic cycle, the Dynamic Map checks each Dynamic Layer’s state. If there is a Dynamic Layer that needs to be redrawn, meaning the dynamic layer needs to regenerate a new set of draw commands, the Dynamic Map will call the Dynamic Layer’s DrawDynamicLayer method, with the corresponding draw phase, and the dynamic layer will generate a new set of draw commands. If there is at least one Dynamic Layer that needs to regenerate its drawing commands, the entire Dynamic Display needs to get repainted. A Dynamic layer needs to regenerate its drawing commands (get redrawn), according to the draw phase it is drawing in:
  1. With the Immediate Phase, if it reports that its immediate phase is dirty. In that case the draw commands will be executed immediately.
  2. With the Compiled Phase, if it reports that its Compiled phase is dirty, and its Recompile Rate interval has elapsed. In that case the display list has expired, and the dynamic layer’s draw commands will be recompiled into the display list. This display list will be reused for rendering, every dynamic cycle that the dynamic display needs to get repainted, that is if the dynamic layer is not reporting that the display list has expired (and therefore the display list doesn’t need to get recompiled).
Every dynamic cycle that the Dynamic Display needs to get repainted, the Dynamic Map will call all of the Dynamic Layers DrawDynamicLayer with the Immediate Phase, but will reuse the display lists of the Dynamic Layers with the Compiled Phase.
The difference between the phases is that when the dynamic display needs to be repainted, the Dynamic Map can reuse the display lists that were generated by the Dynamic Layers that draw in the Compiled phase, but has to regenerate the drawing commands for the Dynamic Layers that draw in the immediate phase. In other words, the immediate draw phase will be called every cycle the display needs to be repainted, but the compiled draw phase will be called only when the Dynamic Map is signaled that the display list has expired (when the DynamicRecompileRate interval had elapsed and the DynamicLayerDirty dirty flag for the esriDDCompiled phase is true).
As a good practice, it is recommended for the Dynamic Layer to draw in one of the draw phases, but not in both of them.
As a rule of thumb, it is preferable to use the Compiled Phase, since using it will minimize the CPU usage and the bus traffic to the graphic card, by minimizing the frequency in which the dynamic layer draw commands are being regenerated (the layer items are being iterated and the draw commands are being called). For an example using the compiled phase, please refer to the RSSWeatherLayer sample. That said, if the layer items are being updated very frequently, and therefore the compiled phase display list needs to be recompiled very frequently, it is preferable to render the layer items in the Immediate Phase, instead of in the Compiled Phase. For an example of using the immediate phase, please refer to the MyDynamicLayer sample.
Another advantage of the Compiled Phase over the Immediate Phase is that when using the Immediate Phase, every change in any of the layers (or any other reason that causes a repaint of the display), will cause all of the other layers that are using the Immediate phase to regenerate their drawing code, even when there was no real reason (no change) for them to do so.

Compound Marker and Array Marker

It is frequently required to draw a Marker along with some text strings around it. You can use the Dynamic Display Draw methods : DrawMarker and DrawText in order to implement that. For ease of use, use the IDynamicCompoundMarker2 interface, which provides helper methods that draw a Marker along with some text strings around. The IDynamicCompoundMarker2 interface also provides methods and properties to control the distance of the text from the marker, the spacing between the text strings, etc.
The DrawCompoundMarkerN methods are drawing a Marker with a combination of 1, 2, 4, 8, or 10 text strings around it. These methods are using a location in Map Coordinates only.
The following diagram shows the layout of the DrawCompoundMarker10 method:

The DrawArrayMarker methods are for drawing a Marker with arrays of text strings in each of the five regions around the Marker. The regions are Center, Left, Right, Top, and Bottom. These methods come in two flavors – one with a location in Map Coordinates, and one with a location in Screen (pixel) Coordinates
The following diagram shows the layout of the DrawArrayMarker method with the input of arrays of sizes – Center[4], Left[5], Right[5], Top[2], Bottom[3] :