利用动态图层实现数据的实时显示

转自原文 利用动态图层实现数据的实时显示

(ArcEngine IDynamiclayer)

说明:最近一个项目用到这方面知识,文章主要来至网络,后期会加入自己的开发心得。(以下的代码实例中,地图看样子是采用ADF开发)

 

 1.1 前言

不刷新地图而能让数据实时显示,这在ArcGIS中已经不在是一个困扰我们的难题,在ArcGIS Engine的开发过程中,每一次更新数据后都需要刷新才能,更改大量数据并不断的刷新,让用户在静静的等待,这不是很痛苦吗?为此ArcGIS提供了一个动态图层,专门用于解决这样问题。

ArcGIS 显示子系统管理着要素的显示和刷新,异步刷新显示和大量数据的渲染使得CPU的利用率增大,这可能导致显示延迟等问题.我们看一下ArcGIS 显示子系统的结构图,从这张图我们更能清楚的看到ArcGIS的显示原理:

动态显示技术将渲染大量的数据从CPU端移动到了显卡上,利用了显卡的性能,这明显提高了显示性能.动态显示技术提供同步显示机制使得大量的动态数据以及高频率刷新的操作可以在瞬间完成。

1.2 动态图层介绍

动态图层是一个自定义图层,因此至少应该继承ILayer,IDynamiclayer和IGeoDataset这三个接口,好在Esri提供了一个BaseDynamicLayer这个抽象类,该接口已经继承了我们所说的相关接口,因此我们只需要在实现动态图层的时候继承该类就行.

1.3 和动态显示相关的接口

在了解了动态显示原理之后,我们看下ArcGIS Engine为动态显示,提供的主要接口:

l IDynamicMap—该接口提供Enable属性用来控制动态显示是否可用,这个接口和我们地图是一一对应的.但我们要使用动态图层的时候,必须用该接口开启动态显示功能,也就是Enable属性设置为true。

l IDynamicScreenDisplay—该接口控制是否启用动态显示

l IDynamicLayer—该接口和ILayer以及IGeoDataset接口写作完成动态显示,也就是符号的绘制等,此接口提供了自定义图层动态显示内容的机制

l IDynamicGlyph—这个接口用来处理资源,这些资源可以是线,点,文本,这些资源作为符号将被动显示。

l IDynamicGlyphFactory—该接口用来管理动态符号,用此接口可以创建,删除动态符号,这些符号就是我们上面所提到的IDynamicGlyph的内容

l IDynamicSymbolProperties—该接口用来管理显示符号的大小,比例尺,颜色,方向等.

l IDynamicDisplay— IDynamicDisplay提供了在地图上描绘几何图形的绘图机制,并且提供了访问动态符号工厂对象.在地图上绘制不同的几何图形,该接口和IDynamicSymbolProperties接口协同,使用IDynamicSymbol-Properties来设置的动态符号,然后使用IDynamicDisplay绘制形状。

IDynamicDisplay接口其实是下面几何绘图回调函数的参数IDynamicLayer.DrawDynamicLayer、 IDynamicMapEvents.BeforeDynamicDraw、 IDynamicMapEvents.AfterDynamicDraw.

1.4 动态绘制模式

动态图层有两种绘制模式,如下:

  • · 重写 IDynamicLayer.DrawDynamicLayer方法
  • · 通过动态地图的事件: IDynamicMapEvents.BeforeDynamicDraw ;IDynamicMapEvents.AfterDynamicDraw

1.5 绘图选择

·使用动态显示API

·使用OPengl API

1.6 绘制动态图层

动态图层,有两种不同的绘图方式,因此有两个绘图阶段 :立即阶段和编译阶段。在每一个阶段,每产生一组新的绘制命令,DrawDynamicLayer方法需要遍历图层的底层数据结构,并为每个项目生成相应的绘图命令,在编译阶段的绘图命令被编译成内部专用的一个清单列表。

每一个绘图周期内,动态地图检查每个动态层的状态。如果一个动态层需要重新绘制(动态图层需要重新生成新的绘图命令),动态地图根据相应的绘图阶段调用动态层的DrawDynamicLayer方法,为动态层将产生一套新的绘图命令。如果有多于一个需要重新生成绘图命令的动态图层,则整个动态显示需要重新绘制。

动态图层是主动显示方式,也就是说他有一个固定的绘图周期,在每一个绘图周期内,都会检查动态图层的dirty 属性,如果有一个动态图层是dirty的,那么都会在所有的动态图层上绘制。动态图层主要有以下两个阶段:

Immediate—不存储绘图命令. 如果它报告其当前的阶段是脏,在这种情况下,绘制命令,将立即执行。

Compiled—在一个清单中存储绘图命令. 动态显示将使用这个清单列表绘图,当dirty 改变了这个清单列表就重新创建。在编译阶段,如果它报告编译阶段是脏的并且它重新编译的速度间隔已经过去了,当这连个条件同时满足的时候,将重新编译显示列表和动态层的绘图命令。

动态图层绘制需要熟悉和实现下面的方法:


DrawDynamicLayer


在一个给定的阶段向具体的设备绘制图层.


DynamicLayerDirty


指示动态图层从上一个指定的绘制阶段是否发生改变


DynamicRecompileRate


重新编译速率是在编译阶段调用绘图方法的时间间隔。

当重新绘制的时候,动态显示遍历动态图层并按照下面的步骤:

通过检查立即阶段的DynamicLayerDirty以重新编译是否需要,如果任何一个动态图层在理解阶段设置了dirty标志,所有的动态图层都会在立即阶段调用DrawDynamicLayer方法

在立即阶段直接调用DrawDynamicLayer方法

通过检查编译阶段的DynamicLayerDirty和DynamicRecompileRate属性确定编译是不是需要

如果需要的话,在编译阶段通过调用DrawDynamicLayer方法重新编译这个图层

在编译阶段通过显示裂变绘图

1.7使用动态图层

动态图层是一个自定义的图层,当我们定义了这个动态图层之后,他就和一个普通的图层一样,需要添加到一个地图中,然后我们就可以在上面绘制符号和图形等,要使用一个动态图层,按下面的步骤就可以完成:

1开启动态显示功能;

2 创建自定义的动态图层并重写相关的绘图方法(上面提到的第一种方式);

3在Map中添加自定义的动态图层;

4 实时数据的传递.

1.7.1 开启动态地图功能

void InitMap()

{

IAGSServerObjectName pServerObjectName = GetMapServer("http://services.arcgisonline.com/ArcGIS/services", "ESRI_Imagery_World_2D", false);

IName pName = (IName)pServerObjectName;

IAGSServerObject pServerObject = (IAGSServerObject)pName.Open();

IMapServer pMapServer = (IMapServer)pServerObject;

ESRI.ArcGIS.Carto.IMapServerLayer pMapServerLayer = new ESRI.ArcGIS.Carto.MapServerLayerClass();

pMapServerLayer.ServerConnect(pServerObjectName, pMapServer.DefaultMapName);

axMapControl1.AddLayer(pMapServerLayer as ILayer);

axMapControl1.Refresh();

pActvie = axMapControl1.Map as IActiveView;

IDynamicMap pDynamicMap = pActvie.FocusMap as IDynamicMap;

pDynamicMap.DynamicMapEnabled = true;

pDynamicMap.DynamicDrawRate = 15;

}

1.7.2 定义自定义的动态图层并重写DrawDynamicLayer方法

using System;

using System.Collections.Generic;

using System.Text;

using System.Drawing;

using System.Timers;

using ESRI.ArcGIS.ADF;

using ESRI.ArcGIS.ADF.Connection.Local;

using ESRI.ArcGIS.ADF.BaseClasses;

using ESRI.ArcGIS.Geodatabase;

using ESRI.ArcGIS.Geometry;

using ESRI.ArcGIS.Carto;

using ESRI.ArcGIS.Display;

using ESRI.ArcGIS.SystemUI;

namespace QARFlight

{

public sealed class FlightDynamicLayer : BaseDynamicLayer

{

public bool m_bOnce = true;

private IDynamicGlyph m_myGlyph = null;

IDynamicGlyph m_lineGlyph = null;

private IDynamicSymbolProperties2 m_dynamicSymbolProps = null;

private IDynamicSymbolProperties2 m_ldynamicSymbolProps = null;

private IPoint m_point = null;

private Timer m_updateTimer = null;

public double Course;

public FlightDynamicLayer(): base()

{

base.m_sName = "My Dynamic layer";

m_updateTimer = new Timer(10);

m_updateTimer.Enabled = false;

m_updateTimer.Elapsed += new ElapsedEventHandler(OnTimerElapsed);

}

public void Draw(IPoint pPoint)

{

this.m_point = pPoint;

}

IPointCollection pPointCollection;

///

///更新飞机的位置和姿态

///

public void Update(double x, double y, double Course)

{

if (this.m_point == null)

{

m_point = new PointClass();

pPointCollection = new PolylineClass() as IPointCollection;

}

this.m_point.X = x;

this.m_point.Y = y;

this.Course = Course;

pPointCollection.AddPoint(this.m_point);

}

///

///获取线的渲染符号

///

public ESRI.ArcGIS.Display.ISimpleLineSymbol GetSimpleLineSymbol(ESRI.ArcGIS.Display.IRgbColor rgbColor, System.Double inWidth, ESRI.ArcGIS.Display.esriSimpleLineStyle inStyle)

{

if (rgbColor == null)

{

return null;

}

ESRI.ArcGIS.Display.ISimpleLineSymbol simpleLineSymbol = new ESRI.ArcGIS.Display.SimpleLineSymbolClass();

simpleLineSymbol.Style = inStyle;

simpleLineSymbol.Color = rgbColor;

simpleLineSymbol.Width = inWidth;

return simpleLineSymbol;

}

public override void DrawDynamicLayer(esriDynamicDrawPhase DynamicDrawPhase, IDisplay Display, IDynamicDisplay DynamicDisplay)

{

if (DynamicDrawPhase != esriDynamicDrawPhase.esriDDPImmediate)

return;

if (!m_bValid || !m_visible)

return;

IEnvelope visibleExtent = Display.DisplayTransformation.FittedBounds;

IDynamicGlyphFactory dynamicGlyphFactory = null;

if (m_bOnce)

{

dynamicGlyphFactory = DynamicDisplay.DynamicGlyphFactory;

m_dynamicSymbolProps = DynamicDisplay as IDynamicSymbolProperties2;

m_ldynamicSymbolProps = DynamicDisplay as IDynamicSymbolProperties2;

IDynamicGlyphFactory2 dynamicGlyphFactory2 = dynamicGlyphFactory as IDynamicGlyphFactory2;

IPictureMarkerSymbol pPicture = new PictureMarkerSymbolClass();

if (this.Course < 0)

{

this.Course = Math.Abs(this.Course);

}

pPicture.Angle = Course;

pPicture.Size = 46;

pPicture.BitmapTransparencyColor = ESRI.ArcGIS.ADF.Connection.Local.Converter.ToRGBColor(Color.FromArgb(255, 255, 255)) as IColor;

pPicture.CreateMarkerSymbolFromFile(esriIPictureType.esriIPictureBitmap, @".\plane.bmp");

m_myGlyph = dynamicGlyphFactory.CreateDynamicGlyph(pPicture as ISymbol);

m_updateTimer.Enabled = true;

m_bOnce = false;

ISimpleLineSymbol pSimpleLineSym = GetSimpleLineSymbol(ESRI.ArcGIS.ADF.Connection.Local.Converter.ToRGBColor(Color.FromArgb(0, 255, 0)) as IRgbColor, 2, esriSimpleLineStyle.esriSLSSolid);

m_lineGlyph = dynamicGlyphFactory.CreateDynamicGlyph((ISymbol)pSimpleLineSym);

}

m_dynamicSymbolProps.set_DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker, m_myGlyph);

m_dynamicSymbolProps.SetScale(esriDynamicSymbolType.esriDSymbolMarker, 1.0f, 1.0f);

m_dynamicSymbolProps.set_RotationAlignment(esriDynamicSymbolType.esriDSymbolMarker, esriDynamicSymbolRotationAlignment.esriDSRAScreen);

DynamicDisplay.DrawMarker(m_point);

if (pPointCollection.PointCount > 1)

{

m_ldynamicSymbolProps.set_DynamicGlyph(esriDynamicSymbolType.esriDSymbolLine, m_lineGlyph);

m_ldynamicSymbolProps.SetScale(esriDynamicSymbolType.esriDSymbolLine, 1.0f, 1.0f);

DynamicDisplay.DrawPolyline(pPointCollection);

}

//绘制完毕

base.m_bIsImmediateDirty = false;

}

void OnTimerElapsed(object sender, ElapsedEventArgs e)

{

//确保下一个绘图周期

base.m_bIsImmediateDirty = true;

}

}

}

1.7.3 加载动态图层

FlightDynamicLayer pFlightLayer = new FlightDynamicLayer();

Global.MainForm.pActvie.FocusMap.AddLayer(pFlightLayer as ILayer);

1.7.4 动态绘制数据

pFlightLayer.Update(point.X, point.Y, Course);

public IAGSServerObjectName GetMapServer(string pHostOrUrl, string pServiceName, bool pIsLAN)

{

//设置连接属性

IPropertySet pPropertySet = new PropertySetClass();

if (pIsLAN)

pPropertySet.SetProperty("machine", pHostOrUrl);

else

pPropertySet.SetProperty("url", pHostOrUrl);

//打开连接

IAGSServerConnectionFactory pFactory = new AGSServerConnectionFactory();

IAGSEnumServerObjectName pServerObjectNames = pConnection.ServerObjectNames;

pServerObjectNames.Reset();

IAGSServerObjectName ServerObjectName = pServerObjectNames.Next();

while (ServerObjectName != null)

{

if ((ServerObjectName.Name.ToLower() == pServiceName.ToLower()) &&

(ServerObjectName.Type == "MapServer") )

{

break;

}

ServerObjectName = pServerObjectNames.Next();

}

//返回对象

return ServerObjectName;

}

时间: 2024-10-19 06:13:14

利用动态图层实现数据的实时显示的相关文章

利用unison+inotify 实现数据双向实时同步

利用unison+inotify 实现数据双向实时同步 环境:Centos 6.5 64位 server1 :192.168.1.201 server2 :192.168.1.250 需求软件:ocaml unison inotify 我这里全是使用yum安装的,若是喜欢使用源码编译安装的可以官网下载源码包. yum install ocaml unison inotify 第一步:保证两台服务器之间可以通过ssh无密码访问,为了安全,需要创建一个普通用户: 两边执行的步骤一样: useradd

html页面下拉列表中动态添加后台数据(格式化数据,显示出数据的层次感)

html页面下拉列表中动态添加后台数据(格式化数据,显示出数据的层次感) 效果图: 运行原理和技术: 当页面加载完毕,利用jquery向后台发送ajax请求,去后台拼接<select></select>中的option字符串.让后将字符串响应回来,动态添加到<select>中.其中的字符串中包含了后台的数据. 页面js代码: 1 <script type="text/javascript"> 2 //加载部门 3 function loa

arcgis server 10.1 发布动态图层展示海量及频繁更新的数据步骤

转自原文 arcgis server 10.1 发布动态图层展示海量及频繁更新的数据步骤 Arcgis server  发布动态图层及调用动态图层 做这个动态图层功能的原由是 有一个30万的数据需要通过arcgis GP工具转成shp然后渲染加载进地图,原来的做法是遍历生成shp面要素,读取面的环状点然后转成json,这个也能实现结果但是时间较长,与预期的时间差别较多,在公司内部讨论时有提到这个动态图层可以解决海量频繁数据的替换,要是每个都发一个图层服务这样不可取.故此讨论后研究这个神奇的功能.

jquery+ajax 实现text框模糊搜索并可利用listbox实时显示模糊搜索列表结果

功能描述: text框中输入,text框下面的listbox中实时显示依据输入的内容进行模糊搜索的结果 js代码 1 $j(function() { 2 $j("input[id='txtCos']").bind('input propertychange', function () { searchCostCenterbyName($j(this).val()); }); 3 }); 4 5 function searchCostCenterbyName(parameters) {

利用Flume将MySQL表数据准实时抽取到HDFS

转自:http://blog.csdn.net/wzy0623/article/details/73650053 一.为什么要用到Flume 在以前搭建HAWQ数据仓库实验环境时,我使用Sqoop抽取从MySQL数据库增量抽取数据到HDFS,然后用HAWQ的外部表进行访问.这种方式只需要很少量的配置即可完成数据抽取任务,但缺点同样明显,那就是实时性.Sqoop使用MapReduce读写数据,而MapReduce是为了批处理场景设计的,目标是大吞吐量,并不太关心低延时问题.就像实验中所做的,每天定

利用rsync+inotify实现数据实时同步脚本文件

将代码放在Server端,实现其它web服务器同步.首先创建rsync.shell,rsync.shell代码如下: #!/bin/bash host1=133.96.7.100 host2=133.96.7.101 host3=133.96.7.102 src=/data/www/ dst1=web1 dst2=web2 dst3=web3 user1=web1 user2=web2 user3=web3 /usr/local/inotify/bin/inotifywait -mrq --ti

脚本_实时显示网卡eth0上的数据流量

#!bin/bash#功能:使用死循环,实时显示网卡eth0发送的数据包流量#作者:liusingbonwhile : do       echo "本地网卡eth0的数据流量信息如下:"       ifconfig eth0|grep "RX pack"|awk '{print $5}'       ifconfig eth0|grep "TX pack"|awk '{print $5}'       sleep 1done 原文地址:htt

项目实例改编:利用structs2的action 实时显示图片、pdf和其他内容的框架抽取。(转)

转自:http://www.verydemo.com/demo_c167_i1382.html 针对:预览文件(图片,PDF)文件来源为action中的inputStream 重点: structs2的action的配置 action的写法和结果类型 resulttype的写法 网页上实时显示   1 structs2的action的配置 首先在package的标签中加入自定义的结果类型<result-types>的名字displayResult,以及后面提到的自定义类DisplayFileR

报表实时显示时间

报表,除了相对静态地展现汇总统计数据以及分布.趋势等数据内容外,也可以用于显示和时间相关的即时信息,包括实时显示时间.例如,下面这个设备监控应用统系中,首页除了显示实时监控数据外,还需要在右上角显示实时时间: 这种形式的"动态报表"其实在我们生活中也随处可见,最常见的就是火车站大屏幕上的列车时刻表,上面显示的当前时间,让旅客能够一目了然地知道自己的列车还有多长时间开,等待的列车什么时候到. 其实,要在报表中做到上面的效果很简单,基本思路就是让页面定时(比如每隔一秒钟)调用JS方法,在J