Development licensing
|
Development licensing
|
Engine Developer kit
|
Engine Runtime
|
|
ArcView
|
|
ArcEditor
|
|
ArcInfo
|
1. 动态显示的原理
2.1 概述
这个专题主要涉及动态显示的原理及涉及的接口
2.2 背景
动态显示技术是对地图渲染引擎核心功能的加强。这是一种新的功能,包括对多个对象亚秒级的刷新支持,而且显示过程能够平滑支持移动,缩放,旋转等操作。这也使得ArcGIS平台可及范围能够进入动态显示领域,通常该领域中的平台在计算能力上有限的(受到处理器效率和内存的限制)。如下图
2.3 概念
这个部分主要讨论一些动态显示技术的概念。
ArcGIS显示子系统管理着地图的显示和刷新。异步显示刷新和密集的地图渲染操作能导致CPU的大量运算操作。CPU的负载能够延迟,甚至阻止地图显示刷新和用户对地图显示的交互。如下图
动态显示技术把密集的图形渲染工作负担从CPU运算转移到图形设备硬件上来,最重要的是它提升了性能。动态显示技术提供了一种同步刷新机制,能够让许多的移动对象的到快速的刷新。如下图
2.4 结构
以下是AO中动态显示用到的主要接口
IDynamicMap—该接口主要用于控制动态显示。接口被用于控制动态显示的可用或不可用。控制动态地图的全局属性。在maps和dynamic maps之间有一对一的关系。
IDynamicLayer—它常和ILayer,IGeoDataset接口联系在一起。IDynamicLayer提供这样的机制,如果实现了通常的Layers,那么在动态显示可用状态下调用对象的动态绘制内容。
IDynamicScreenDisplay—用于控制动态显示的可用或不可用
IDynaimcGlyph—动态字符处理需要被动态显示所渲染的资源。
IDynaimcGlyphFactory—它用来管理动态字符(Dynamic Glyph),可以通过使用IDynamicGlyphFactory接口来得到,新建和删除动态字符。这意味着你能够使用标准的AO符号,如字体符号,文本符号,图形符号等或者也可以使用其它的资源,例如icons和位图。此外,动态字符也能够由动态字符组来新建,动态字符组的概念就是若干按顺序排列的字符拼接出来的image。使用来自动态字符组的字符能够得到更好的绘制效果,原应是一个动态字符组绘制一个纹理对象。动态显示中包括了一个内置的默认的动态字符组,因此它来load或者unload字符。
IDynamicSymbolProperties—可以设置选中的符号的各种属性,例如颜色,比例,转向和字符。通过使用符号属性使符号在绘制到地图之前得到控制。
IDynamicDisplay—通过他来提供一种机制,在地图上绘制不同的地理几何对象。此外提供动态字符工厂的接口。在地图上绘制地理几何对象,也需要同时使用动态字符和动态符号属性。使用动态符号属性来设置符号,然后使用动态显示来画形状。
IDynamicDrawScreen—使用它可以采用屏幕坐标系在map上绘制地理几何对象。
IDynamicCompoundMarker—它可以在绘制的符号周围带有labels和属性。
1. 如何使用动态显示技术
3.1概述
这个介绍主要说明如何有效地使用ArcGIS Framework中的动态显示技术。介绍当前的一些使用方法和需求,演示一些GIS中需要采用动态显示技术的例子,以及一些接口的使用介绍。
3.2 Dynamic map在动态显示技术中的使用
推荐使用基于DynamicMap类的IDynamicMap接口,来使Dynamic map可用或不可用。
下面是IDynamicMap使用代码:
[C#]
//Cast the dynamic map from the focus map.
IDynamicMap dynamicMap = m_hookHelper.FocusMap as IDynamicMap;
//Make sure to switch into dynamic mode.
if (!dynamicMap.DynamicMapEnabled)
dynamicMap.DynamicMapEnabled = true;
[VB.NET]
' Cast the dynamic map from the focus map.
Dim dynamicMap As IDynamicMap = CType(m_hookHelper.FocusMap, IDynamicMap)
' Make sure to switch into dynamic mode.
If (Not dynamicMap.DynamicMapEnabled) Then
dynamicMap.DynamicMapEnabled = True
End If
(上述或以下有可能涉及的代码都是.net例子,但是最近我自己完成了vc6.0的Demons)
当设置Dynamic map为Enable,那么动态显示将使用OPenGL的render context来绘制基本的地图图层和动态图层。
3.3 Dynamic mode下的绘图
以下是两种Dynamic mode绘图方式:
(1) 实现IDynaimcLayer接口中的DrawDynamicLayer方法
(2) 监听动态显示的两个事件:
IDynamicMapEvents.BeforeDynamicDraw;
IDynamicMapEvents.AfterDynamicDraw;
3.3.1 绘图方式的两种选择(事实是本质的draw都是OpenGL方法)
(1)使用AO的API
(2)直接调用OpenGL的API
默认情况下OpenGL的纹理(texture)可用。需要注意的是,在最初需要开始利用OpenGL的方法时,要求关闭OpenGL 2D texture flag。
3.4绘图方式采用使用AO的API
[C#]
//Set the marker symbol.
m_dynamicSymbolProps.set_DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker,
m_markerGlyphs[2]);
//Draw a marker symbol.
DynamicDisplay.DrawMarker(m_point);
[VB.NET]
'Set the marker symbol.
m_dynamicSymbolProps.DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker) = m_markerGlyphs(2)
'Draw a marker symbol.
DynamicDisplay.DrawMarker(m_point)
In the following code example, drawing is done using a compound marker symbol using the dynamic display API:
[C#]
//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.
m_dynamicSymbolProps.set_DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker,
m_markerGlyphs[2]);
//Drawing a compound marker symbol using six strings.
m_dynamicCompoundMarker.DrawCompoundMarker6(m_point, "TOP", "BOTTOM", "Item " +
Convert.ToString(r[0]), heading.ToString("###.##"), m_point.X.ToString(
"###.#####"), m_point.Y.ToString("###.#####"));
[VB.NET]
'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.
m_dynamicSymbolProps.DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker) = m_markerGlyphs(2)
'Drawing a compound marker symbol using six strings.
m_dynamicCompoundMarker.DrawCompoundMarker6
(m_point,
"TOP",
"BOTTOM",
"Item " & Convert.ToString(r(0)),
heading.ToString("###.##"),
m_point.X.ToString("###.#####"), m_point.Y.ToString("###.#####"))
3.5绘图方式使用OpenGL的API
[C#]
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);
[VB.NET]
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)
GL.glVertex2f(CType(x, Single), CType(y, Single))
GL.glEnd()
GL.glPopMatrix()
GL.glEnable(GL.GL_TEXTURE_2D)
3.5动态图层
动态图层也是普通的图层。它实现了普通图层的接口,当然为此你必须最小程度上实现ILayer接口。事实上,实现了ILayer接口能够使自己加载到map上,也能使自己被放在内容列表中。需要实现一个动态图层,也需要实现IDynamicLayer接口,那就有如下的方法需要被实现:
DrawDynamicLayer | 在绘制阶段决定画什么内容 | |
DynamicLayerDirty | 表明上次画完后的动态显示是否改变 | |
DynamicRecompileRate | 重新编译率是以百分之一秒为间隔的,这使得编译阶段的动态显示中的绘制方法(DrawDynamicLayer)可以被调用。 |
由于动态显示是处于激活状态的,这就意味着它就有固定的循环过程。在每次的阶段绘制过程中,都会检查DynaimcLayer中的脏标志,来重绘所有的动态图层中的内容。
ArcGIS9.3对Dynamic Display做了很大的改进,底层显示方式做了本质的一些改变。其中最大的变化是添加了IDynamicCacheLayerManager 接口,这个接口极大提升了动态图层显示时地图的显示效果,9.3以前的版本,地图的缩放都是重复刷新每个地图背景,在地图比较复杂的情况下,几乎是无法忍受的慢,但是如果采用9.3的新接口,可以在使用之前先用类似Arcgis Server的方法对地图进行cache工作,而后在IDynamicCacheLayerManager 中使用connect方法指定cache的文件夹,便能达到理想的效果,其实也可以自己利用该接口直接做cache,那么在多次浏览后,cache的效果使得地图背景显示的效果极佳。部分程序代码如下:
VARIANT_BOOL varCacheable;
ipLayer->put_Cached(VARIANT_TRUE);
IDynamicCacheLayerManagerPtr ipDynamicCacheLayerManager(CLSID_DynamicCacheLayerManager);
hr= ipDynamicCacheLayerManager->Init(m_ipMap,ipLayer);
hr=ipDynamicCacheLayerManager->get_Cacheable(&varCacheable);
CComBSTR bstrFoldName;
CComBSTR bstrFoldPath;
hr= ipDynamicCacheLayerManager->get_FolderPath(&bstrFoldPath);
hr= ipDynamicCacheLayerManager->get_FolderName(&bstrFoldName);
hr= ipDynamicCacheLayerManager->Connect(bstrFoldPath,bstrFoldName);
hr= ipDynamicCacheLayerManager->put_ConsolidatedGroupLayer(VARIANT_TRUE);
hr= ipDynamicCacheLayerManager->put_DetailsThreshold(20);
hr= ipDynamicCacheLayerManager->Invalidate(NULL,VARIANT_TRUE);
hr= ipDynamicCacheLayerManager->put_Format(CComBSTR("PNG"));
break;
目前也可以直接使用ArcGIS Server的地图服务作为Dynamic Layer显示背景。
何种情况下使用Dynamic Display比较合适
前期和客户做过目标显示的比对测试,如果动态目标个数在一千以上,选择使用Dynamic Display比较合适。
如果动态目标数量不多,则建议使用element,主要是程序实现比较简单。
扩展性和底层控制,Dynamic Display效果更好,但是仍有缺陷,例如symbol的部分中文支持。