In this topic
- Using the dynamic display to enable the dynamic map
- Drawing in dynamic mode
- Drawing marker symbols using the dynamic display API
- Direct OpenGL API
- Dynamic layers
- Draw cycle sequence (including DynamicMapEvents)
- Drawing objects API
- Working with dynamic symbols
- Dynamic glyph factory
- General guidelines for drawing dynamic layers
- Draw rates
- In conclusion
It is recommended to enable the dynamic map using the IDynamicMap interface that is implemented by the Map class. Use IDynamicMap to enable or disable the dynamic map (the dynamic display). See the following illustration:
See the following code example for enabling the dynamic map:
[Java]
//Cast the dynamic map from the focus map.
IDynamicMap dynamicMap = (IDynamicMap)hookHelper.getFocusMap();
//Make sure to switch into dynamic mode.
if (!dynamicMap.isDynamicMapEnabled())
dynamicMap.setDynamicMapEnabled(true);
When enabled, the dynamic display is creating an OpenGL rendering context to draw the basic map layers and on top of the base layers, draws the dynamic layers. When the dynamic map is enabled, this is considered as being in dynamic drawing mode.
The following are the two methods to draw in dynamic mode:
- Implementation of IDynamicLayer using IDynamicLayer.DrawDynamicLayer
- Listen to dynamic display events:
The following are the two options for drawing:
- Using dynamic display application programming interface (API)
- Direct OpenGL API
By default, OpenGL textures are enabled. It is required to disable the OpenGL 2D texture flag when drawing OpenGL primitives.
The following code example demonstrates drawing a marker symbol using the dynamic display application programming interface (API):
IDynamicSymbolProperties dynamicSymbolProps = ...;
IDynamicGlyph markerGlyph = ...;
//Set the marker symbol.
dynamicSymbolProps.setDynamicGlyphByRef(esriDynamicSymbolType.esriDSymbolMarker,
markerGlyph);
IDynamicDisplay dynamicDisplay = ...;
//Draw a marker symbol.
dynamicDisplay.drawMarker(point);
In the following code example, drawing is done using a compound marker symbol using the dynamic display API:
[Java]
IDynamicSymbolProperties dynamicSymbolProps = ...;
IDynamicGlyph markerGlyph = ...;
//Draw the item as a compound marker. This means that you do not have to draw the items and its
//accompanying labels separately, thus allowing you to write less code and better set
//the marker symbol.
dynamicSymbolProps.setDynamicGlyphByRef(esriDynamicSymbolType.esriDSymbolMarker,
markerGlyph);
IDynamicCompoundMarker dynamicCompoundMarker = ...;
//Drawing a compound marker symbol using six strings.
dynamicCompoundMarker.drawCompoundMarker6(point, "TOP", "BOTTOM", "LEFT1", "LEFT2",
"RIGHT1", "RIGHT2");
If using the direct OpenGL API, the coordinate system's origin is the center of the window while the width and height are identical to the device frame dimensions. See the following code example:
// Tell JOGL that we are going to use our own OpenGL Context
GLContext context = GLDrawableFactory.getFactory().createExternalGLContext();
context.makeCurrent();
GL gl = context.getGL();
gl.glDisable(GL.GL_TEXTURE_2D);
gl.glPushMatrix();
gl.glLoadIdentity();
// Draw a simple point.
gl.glBegin(GL.GL_POINTS);
gl.glColor3f(1.0f, 1.0f, 0.0f); //Yellow
gl.glVertex2f((float)x, (float)y);
gl.glEnd();
gl.glPopMatrix();
gl.glEnable(GL.GL_TEXTURE_2D);
See How to draw a bitmap element using OpenGL for more information on drawing direct OpenGL using textured geometries.
A dynamic layer is a custom layer. To implement a custom layer, you need to, at a minimum, implement the ILayer interface. Implementing the ILayer interface enables the layer to be added to the map and the table of contents. To implement a dynamic layer, the custom layer needs to implement IDyamicLayer. The custom dynamic layer needs to implement the following:
|
Draws the layer to the specified display for the given draw phase.
|
|
|
Indicates if the dynamic layer has changed since last drawn for the specified draw phase.
|
|
|
Indicates if the dynamic layer has changed since last drawn for the specified draw phase.
|
The dynamic display is an active display. This means that it has a fixed drawing cycle. During every drawing cycle, the dynamic display checks each dynamic layer's dirty property. If at least one of the dynamic layers is dirty, the dynamic display redraws all dynamic layers.
A dynamic layer has two primary draw phases: immediate and compiled. The compiled draw phase stores draw commands in a list. Dynamic display uses this list to draw the commands. The list is recreated when the dirty flag has been set. The immediate draw phase does not store draw commands. The draw commands of the immediate draw phase are immediately drawn.
When redrawing the display, the dynamic display iterates through the dynamic layers and does the following for each:
- Checks if recompile is needed by checking the DynamicLayerDirty with the immediate phase. If any dynamic layer has set the dirty flag for the immediate phase, all dynamic layers DrawDynamicLayer method will be called with the immediate draw phase.
- Draws the immediate phase and calls the DrawDynamicLayer method with the immediate phase.
- Checks if recompile is needed by checking the DynamicLayerDirty (with the compiled phase) and the DynamicRecompileRate property.
- If needed, recompile the dynamic layer by calling the DrawDynamicLayer method with the compiled phase.
- Draw the compiled phase, by drawing the display list.
The following code example demonstrates drawing a dynamic layer in immediate mode:
public void drawDynamicLayer(int phase, IDisplay display, IDynamicDisplay
dynamicDisplay){
//Make sure the current draw phase is immediate. In this example, there is no use of the
//compiled draw phase. Use the esriDDPCompiled draw phase to draw semi-static items (items
//whose update rate is lower than the display update rate).
if (phase != esriDynamicDrawPhase.esriDDPImmediate)
return ;
//Actual drawing to take place here.
//Set the dirty flag to true to let the dynamic display that the layer needs to be redrawn.
this.setDynamicLayerDirty(phase, true);
}
A layer will be recompiled (in compiled phase) when any refresh events or when the following conditions are met:
- DynamicLayerDirty property is set to true
- DynamicRecompileRate time from the previous recompile time has elapsed
The layer's DrawDynamicLayer method will be called with the following:
- Compiled phase—When the layer needs to be recompiled
- Immediate phase—When the layer needs to be redrawn
When redrawing the compiled phase of a dynamic layer, it is not necessary to call its DrawDynamicLayer method but only redraw the already compiled list. The DrawDynamicLayer method (of the compiled phase) is only called when needed to recompile. On the other hand, when redrawing the immediate phase of a layer, the DrawDynamicLayer method (of the immediate phase) is being called.
There are two DynamicMapEvents methods that can be used to draw objects. The two draw phases are esriDMDPLayers and esriDMDPDynamicLayers. During every draw cycle, the layers are being drawn and the dynamic map events are being fired in the following sequence:
- BeforeDynamicDraw(esriDMDPLayers) event is being fired
- Layers are drawn; these are the layers that do not support IDynamicLayers (static layers)
- AfterDynamicDraw(esriDMDPLayers) event is being fired
- BeforeDynamicDraw(esriDMDPDynamicLayers) event is being fired
- Dynamic layers are drawn
- Immediate phase (esriDDPImmediate)
- Compiled phase (esriDDPCompiled)
- AfterDynamicDraw(esriDMDPDynamicLayers) event is being fired
See the following illustration:
The following code example demonstrates drawing in the AfterDynamicDraw on top of the dynamic layers:
map.addIDynamicMapEventsListener(new IDynamicMapEventsAdapter(){
public void afterDynamicDraw(IDynamicMapEventsAfterDynamicDrawEvent event)throws
IOException, AutomationException{
//Make sure we only draw after the dynamic layers have been drawn
if (event.getDynamicMapDrawPhase() !=
esriDynamicMapDrawPhase.esriDMDPDynamicLayers)return ;
//Do the drawings in here.
}
}
;
The dynamic display has the following methods for drawing into the OpenGL rendering context:
- IDynamicLayer.DrawDynamicLayer
- IDynamicMapEvents.BeforeDynamicDraw
- IDynamicMapEvents.AfterDynamicDraw
In these methods, the user can draw using the OpenGL API or the dynamic display draw methods.
- Use the IDynamicDisplay interface to draw objects in map coordintates. Use the IDynamicCompoundMarkerSymbol interface as an additional option for drawing character marker symbols with surrounding attribute text.
- Use the IDynamicScreenDisplay interface to draw objects in screen coordinates. This origin uses the DisplayTransformation.DeviceFrame. In this case, it uses the upper-left of the screen.
- Use the IDynamicGlyphFactory interface to create and delete dynamic glyphs. To get the interface to IDynamicGlyphFactory, use IDynamicDisplay.
- Use the IDynamicSymbolProperties interface to control the dynamic symbols properties (dynamic marker, line, text, and fill).
- Use the IDynamicGlyph interface to access properties of dynamic glyphs. A dynamic glyph is a handle to a resource.
- Use the IDynamicMap interface to set the IDynamicMap.UseSubPixelRendering property.
Dynamic symbols are used to draw objects that update dynamically. Dynamic symbols consist of marker, line, text, and fill properties that can be managed using the IDyanmicSymbolsProperties interface. The following table indicates the properties of each symbol component:
|
Marker
|
Line
|
Text
|
Fill
|
DynamicGlyph
|
?
|
?
|
?
|
|
Color
|
?
|
?
|
?
|
?
|
Heading
|
?
|
|
?
|
|
Smooth
|
?
|
?
|
?
|
|
Scale
|
?
|
?
|
?
|
|
Rotational alignment
|
?
|
|
?
|
|
Vertical alignment
|
|
|
?
|
|
Horizontal alignment
|
|
|
?
|
|
- Symbol is a state of drawing:
- Controls the symbol through IDynamicSymbolProperties
- Needs to be synthesized through DynamicGlyph:
- DynamicGlyph provides resource for symbol
- DynamicSymbol types:
- esriDSymbolMarker
- esriDSymbolLine
- esriDSymbolText
- esriDSymbolFill
- DynamicGlyph types:
- esriDGlyphMarker
- esriDGlyphLine
- esriDGlyphText
Before drawing a symbol, set the DynamicSymbolProperties. Do the following to s
et the DynamicSymbolProperites:
- Get IDynamicGlyphFactory from the DynamicDisplay
- Create marker
- Load from bitmap (BMP)
- PictureMarker.CreateFromFile
- Create line
- Create text
See the following table:
|
Indicates the dynamic glyph for the specified dynamic symbol.
|
|
|
Indicates the color for the specified dynamic symbol.
|
|
|
Scales the dynamic symbol.
|
|
|
Indicates the heading for the specified dynamic symbol. Only valid if dynamic symbol rotation alignment is a heading and for text and marker.
|
|
|
Indicates the rotation alignment for the specified dynamic symbol. Only valid for text and marker.
|
|
|
Indicates the color for the specified dynamic symbol.
|
|
|
Scales the dynamic symbol.
|
|
|
Indicates whether the specified dynamic symbol will be smooth. Only valid for text, line, and marker.
|
|
|
Indicates the horizontal alignment for the text dynamic symbol.
|
|
|
Indicates the vertical alignment for the text dynamic symbol.
|
The DynamicGlyphFactory is the engine used to create and delete glyphs used by the DynamicDisplaySymbol.
The following are the definitions of a glyph:
- Image of a typographical sign
- Image used in the visual representation of characters; how a character looks. A font is a set of glyphs
- A single unit of display in a font (Microsoft). It can be defined by the following:
- An outline (in OpenType)
- A bitmap
- A set of graphic commands
- DynamicGlyph:
- Glyph using in the dynamic display environment
- A handle of the resource for rendering dynamic symbols
See the following table:
|
Creates a dynamic glyph from a symbol.
|
|
|
Creates a dynamic glyph from a file.
|
|
|
Deletes a dynamic glyph from a symbol.
|
|
|
Retrieves a dynamic glyph from a glyph group.
|
|
|
Initializes the dynamic glyph factory.
|
|
|
Loads an external dynamic glyph group from
a file. |
|
|
Unloads an external dynamic glyph group from
a file. |
Using the compiled phase is recommended for drawing most layers. In the compiled phase it is not recommended to create dynamic glyphs or textures. Use the immediate phase to create dynamic glyphs and textures, for example, if you have one layer with many features that update every 20 seconds. In this case, it is recommended to redraw this in the compiled phase. If you have a layer you need to update at subsecond rates, draw it in the immediate phase.
When creating a dynamic glyph from text or a dynamic marker, keep in mind that when dynamic display is enabled, what was once white will become the color you choose. If created with a color, that color will become darker when enabled. However, black will remain black.
When drawing the dynamic layer using the DrawDynamicLayer method or when listening to DynamicMapEvents, it is recommended to initially cache (keep it as a class member) the DynamicGlyphFactory, the DynamicSymbolProperties, and the DynamicCompoundMarker. This is an efficient method considering the repetition of draw cycle sequences.
See the following code example:
private boolean doOnce = true;
private IDynamicGlyphFactory dynamicGlyphFactory = null;
private IDynamicSymbolProperties dynamicSymbolProps = null;
IDynamicCompoundMarker dynamicCompoundMarker = null;
public void drawDynamicLayer(int phase, IDisplay display, IDynamicDisplay
dynamicDisplay){
... if (doOnce){
//Cast the dynamic display into dynamic glyph factory.
dynamicGlyphFactory = dynamicDisplay.getDynamicGlyphFactory();
//Cast the dynamic display into dynamic symbol properties.
dynamicSymbolProps = (IDynamicSymbolProperties)dynamicDisplay;
//Cast the compound marker symbol.
dynamicCompoundMarker = (IDynamicCompoundMarker)dynamicDisplay;
//Do other initializations in here.
doOnce = false;
}
...
}
The default draw cycle is the actual draw time plus the draw rate. This means that
the draw rate is the lag time between each two cycles. In this mode, you can consider the draw rate as sleep time between two draw cycles.
The following are the two types of DynamicMap events:
- DynamicMapStarted and DynamicMapFinished—Fired on start and end of each dynamic map heart bit
- BeforeDynamicDraw and AfterDynamicDraw—Fired on before and after the dynamic display drawing
The draw rate (actual cycle time) is between every two DynamicMapStarted events.
The actual draw time is between every DynamicMapStarted and DynamicMapFinished events.
Dynamic display has been an integral part of the map display pipeline since the ArcGIS 9.2 release. It provides an ArcObjects API for developers to leverage accelerated graphics technology when required. The dynamic display operates as another display mode. This means most other standard ArcGIS tools continue to work. Developers can define dynamic symbols that can be moved, oriented, scaled, or even animated in real-time.
See Also:
About dynamic displayDevelopment licensing | Deployment licensing |
---|---|
Engine Developer Kit | Engine |
ArcGIS for Desktop Basic | |
ArcGIS for Desktop Standard | |
ArcGIS for Desktop Advanced |