ArcGIS Engine三维动画开发 来自:http://www.iarcgis.com/?p=826
ArcGIS Engine 三维开发
来自:http://www.iarcgis.com/?p=826
在三维中,经常使用的一个功能就是播放动画,也就是我们要对一条动画轨迹进行播放,而在ArcGIS Engine中做3D开发的时候,轨迹有两个对应的对象
IAnimationTrack和IAGAnimationTrack,
如果在帮助中仔细查看还会发现更多跟这两个类似的区别,一个接口比另一个接口多两个字母AG,
如IAnimationTracks和IAGAnimationTracks,IKeyframe和IAGKeyframe。
我们看下这些的描述
IAGKeyframe:访问运动对象的关键帧(Provides access to keyframes of animated objects. )
IKeyframe:访问运动对象的关键帧(Provides access to keyframes of animated objects.)
从描述上看,没有任何区别,那么为什么会有两个这样的接口,带AG的出来的比较晚,而且位于ESRI.ArcGIS.Animation中,而不带AG的是早期的接口位于ESRI.ArcGIS.Analyst3D中,而且这些接口的属性和方法都很类似:
Ikeyframe
IAGKeyframe
1.1 原因何在
既然两个接口提供的方法和接口很类似,为什么会有两套这样的接口呢?原来带AG的是后来出现的,而且是在9.2的时候增加的,在9.2的时候增加了Animation等类库,看下面的描述:
在帮助中,我们可以看到更多的信息,首先看到实现IAGAnimationTrack的接口有两个类即AGAnimationTrack和AnimationTrack,也就是说凡是带了AG的接口很多都被早期的对象继承,如下:
AGAnimationTrack类只实现了IAGAnimationTrack接口,如下图:
而AnimationTrack类不仅仅实现了1AnimationTrack接口,还实现了 1AGAnimationTrack接口,如下图:
1.1 后出现的不一定就节省力气
1.1.1 关键帧创建
在创建关键帧的时候两者差别不大,除了创建的时候的参数不一样,其他几乎没有变化,下面为使用IKeyframe创建的:
IKeyframe pKeyframe = new GlobeCameraKeyframeClass();
pKeyframe.Name = "Key" + Convert.ToString(_AnimationTrack.KeyframeCount + 1);
IScene pScene = globe.Globe as IScene;
pKeyframe.CaptureProperties(pScene, globe.GlobeDisplay.ActiveViewer.Camera);
_AnimationTrack.InsertKeyframe(pKeyframe, -1); for (int index = 0; index < _AnimationTrack.KeyframeCount; index++)
{
_AnimationTrack.get_Keyframe(index).TimeStamp = (double)index / (double)(_AnimationTrack.KeyframeCount - 1);
}
下面为使用IAGKeyframe创建的:
public static void InsertKeyfr(IGlobe pGlobe, string pTrackName)
{
IAGAnimationTracks pTracks = pGlobe as IAGAnimationTracks;
IAGAnimationTrack _AnimationTrack = GetAGAnimationTrack(pTracks, pTrackName);
if (_AnimationTrack == null)
{
_AnimationTrack = new AGAnimationTrackClass();
_AnimationTrack.Name = pTrackName; pTracks.AddTrack(_AnimationTrack); } IAGAnimationTrackKeyframes pAGKyeFrames = _AnimationTrack as IAGAnimationTrackKeyframes;
IAGKeyframe pKeyframe = new GlobeCameraKeyframeClass();
pKeyframe.Name = "Capture" + Convert.ToString(pAGKyeFrames.KeyframeCount + 1);
IScene pScene = pGlobe.GlobeDisplay.Scene; //还可以直接转换
pKeyframe.CaptureProperties(pGlobe as IAGAnimationContainer, pGlobe.GlobeDisplay.ActiveViewer.Camera);
(_AnimationTrack as IAGAnimationTrackKeyframes).InsertKeyframe(pKeyframe, -1); for (int index = 0; index < pAGKyeFrames.KeyframeCount; index++)
{
pAGKyeFrames.get_Keyframe(index).TimeStamp = (double)index / (double)(pAGKyeFrames.KeyframeCount - 1);
}
//更新窗体;
}
1.1.1 关键帧获取
但是有的时候不带AG的比带了AG的方便,比如要获取一条轨迹的关键帧,使用IAnimationTrack接口的时候只需要下面两个步骤:
- IAnimationTrack.KeyframeCount
- IAnimationTrack.Keyframe
而IAGAnimationTrack接口则需要3个步骤:
- IAGAnimationTrackKeyframes
- IAGAnimationTrackKeyframes.KeyframeCount
- IAGAnimationTrackKeyframes.Keyframe
1.1.2 播放动画
而在播放动画的饿时候使用IAnimationTracks,我们只需要用下面的步骤代码:
在播放的时候用下面的代码是可以实现动画播放的:
IAnimationTracks pTracks = globe.Globe as IAnimationTracks;
for (int i = 0; i < pTracks.TrackCount; i++)
{
IAnimationTrack pTrack = pTracks.Tracks.get_Element(i) as IAnimationTrack;
pTrack.IsEnabled = true;//设置为true 才可以播放这条轨迹
}
DateTime startTime = DateTime.Now;
TimeSpan timeSpan;
double elapsedTime;
double duration = 10;
bool play = true;
do
{
timeSpan = (DateTime.Now).Subtract(startTime);
elapsedTime = timeSpan.TotalSeconds;
if (elapsedTime > duration)
{
play = false;
elapsedTime = duration;
}
pTracks.ApplyTracks(globe.GlobeDisplay.ActiveViewer, elapsedTime, duration);
globe.GlobeDisplay.RefreshViewers();
} while (play);
我们在前面说到了,带AG的接口提供的方法和属性和不带的非常类似,但下面的代码播放之后是不能实现动画播放的
for (int i = 0; i < pTracks.TrackCount; i++)
{
IAGAnimationTrack pAnimationTrack = pTracks.AGTracks.get_Element(i) as IAGAnimationTrack;
pAnimationTrack.IsEnabled = true;
}
DateTime startTime = DateTime.Now;
TimeSpan timeSpan;
double elapsedTime;
double duration = 10;
bool play = true;
do
{
timeSpan = (DateTime.Now).Subtract(startTime);
elapsedTime = timeSpan.TotalSeconds;
if (elapsedTime > duration)
{
play = false;
elapsedTime = duration;
}
pTracks.ApplyTracks(false, duration);
this.globe.GlobeDisplay.RefreshViewers();
} while (play);
如何才能播放呢,既然已经知道带AG的来自Animation库,那就应该在这个库中找,使用下面的接口:
如果对ArcGlobe的动画非常熟悉的朋友,应该知道这4个方法对应了播放工具上的四个操作,录制,破防。暂停和停止
private IAGAnimationEnvironment CreatAnimationEnvironment(IGlobe pGlobe)
{
DateTime startTime = DateTime.Now; Double playTimeInterval = 10;
IBasicScene2 pBasicScene2 = pGlobe as IBasicScene2;
_pAGAnimationEnvironment = pBasicScene2.AnimationExtension.AnimationEnvironment;
_pAGAnimationEnvironment.IsIntervalPlay = true;
_pAGAnimationEnvironment.PlayInAllViewers = true;
_pAGAnimationEnvironment.PlayMode = esriAnimationPlayMode.esriAnimationPlayOnceForward;
_pAGAnimationEnvironment.AnimationDuration = playTimeInterval;
_pAGAnimationEnvironment.PlayType = esriAnimationPlayType.esriAnimationPlayTypeDuration;
_pAGAnimationEnvironment.PlayTime = playTimeInterval;
_pAGAnimationEnvironment.PutPlayInterval(0, playTimeInterval);//尤其关键,设置播放时间段。
_pAGAnimationEnvironment.RestoreState = true;
IArray pArr = new ArrayClass(); return _pAGAnimationEnvironment;
} //List存放了我路径轨迹的名称
private void PlayAnimaiton(IGlobe pGlobe)
{
IAGAnimationTracks pAGAnimationTracks = pGlobe as IAGAnimationTracks;
IAGAnimationUtils pAGAnimationUtils = new AGAnimationUtilsClass();
IAGAnimationPlayer pAGAnimaitonPlayer = pAGAnimationUtils as IAGAnimationPlayer;
_pAGAnimationEnvironment = CreatAnimationEnvironment(pGlobe);
List pList = new List();
if (checkedListBoxtracks.SelectedItems.Count > 0)
{
for (int j = 0; j < checkedListBoxtracks.CheckedItems.Count; j++)
{
pList.Add(checkedListBoxtracks.CheckedItems[j].ToString());
}
}
for (int i = 0; i < pAGAnimationTracks.TrackCount; i++)
{
IAGAnimationTrack pT=pAGAnimationTracks.AGTracks.get_Element(i) as IAGAnimationTrack; if (pList.Contains(pT.Name))
{
pT.IsEnabled = true;
}
else
{
pT.IsEnabled = false;
}
} pAGAnimaitonPlayer.PlayAnimation(pAGAnimationTracks, _pAGAnimationEnvironment, null);
//pAGAnimationUtils.SaveAnimationFile(pAGAnimationTracks.AnimationObjectContainer, "C:\\test.asa", ESRI.ArcGIS.esriSystem.esriArcGISVersion.esriArcGISVersion93);
}
1.3 但后出现的比较灵活
在使用不带AG的播放动画是,播放结束后,是不能回到原来的状态,但是后者却可以,还有就是在播放的时候,前者是不能停止和暂停(除非播放结束或系统出现问题),但是后者却可以,还有就是后者提供了录制的功能,而前者没有。同时,后者在播放的时候,只要将播放环境接口IAGAnimationEnvironment中的信息设置OK后,就不用自己去写while循环用来判断时间。在创建关键帧的时候,我们往往都是创建路径,然后将帧插入到路径中,但是后者有有个默认的路径,下面的代码就是向默认的路径中捕获当前的视图,也就是ArcGlobe中的那个照相机的功能:
ESRI.ArcGIS.Animation.IAGAnimationUtils pAnimationUtils = new ESRI.ArcGIS.Animation.AGAnimationUtilsClass();
ESRI.ArcGIS.Animation.IAGAnimationTracks pAnimationTracks = (ESRI.ArcGIS.Animation.IAGAnimationTracks)globe;
ESRI.ArcGIS.Analyst3D.IBasicScene2 pBasicScene2 = (ESRI.ArcGIS.Analyst3D.IBasicScene2)globe;
ESRI.ArcGIS.Animation.IAGAnimationEnvironment pAnimationEnvironment = pBasicScene2.AnimationExtension.AnimationEnvironment;
pAnimationUtils.CaptureCurrentView(pAnimationTracks, pAnimationEnvironment);
作者
ArcGIS Engine三维动画开发 来自:http://www.iarcgis.com/?p=826的更多相关文章
- 《ArcGIS Engine+C#实例开发教程》第七讲 图层符号选择器的实现2
原文:<ArcGIS Engine+C#实例开发教程>第七讲 图层符号选择器的实现2 摘要:在第七讲 图层符号选择器的实现的第一阶段中,我们完成了符号选择器窗体的创建与调用.在第二阶段中, ...
- 《ArcGIS Engine+C#实例开发教程》第八讲 属性数据表的查询显示
原文:<ArcGIS Engine+C#实例开发教程>第八讲 属性数据表的查询显示 第一讲 桌面GIS应用程序框架的建立 第二讲 菜单的添加及其实现 第三讲 MapControl与Page ...
- 《ArcGIS Engine+C#实例开发教程》第六讲 右键菜单添加与实现
原文:<ArcGIS Engine+C#实例开发教程>第六讲 右键菜单添加与实现 摘要:在这一讲中,大家将实现TOCControl控件和主地图控件的右键菜单.在AE开发中,右键菜单有两种实 ...
- 《ArcGIS Engine+C#实例开发教程》第四讲 状态栏信息的添加与实现
原文:<ArcGIS Engine+C#实例开发教程>第四讲 状态栏信息的添加与实现 摘要:在上一讲中,我们完成了 MapControl 和PageLayoutControl两种视图的同步 ...
- 《ArcGIS Engine+C#实例开发教程》第五讲 鹰眼的实现
原文:<ArcGIS Engine+C#实例开发教程>第五讲 鹰眼的实现 摘要:所谓的鹰眼,就是一个缩略地图,上面有一个矩形框,矩形框区域就是当前显示的地图区域,拖动矩形框可以改变当前地图 ...
- 《ArcGIS Engine+C#实例开发教程》第三讲 MapControl与PageLayoutControl同步
原文:<ArcGIS Engine+C#实例开发教程>第三讲 MapControl与PageLayoutControl同步 摘要:在ArcMap中,能够很方面地进行MapView和Layo ...
- 《ArcGIS Engine+C#实例开发教程》第二讲 菜单的添加及其实现
原文:<ArcGIS Engine+C#实例开发教程>第二讲 菜单的添加及其实现 摘要:在上一讲中,我们实现了应用程序基本框架,其中有个小错误,在此先跟大家说明下.在“属性”选项卡中,我们 ...
- 《ArcGIS Engine+C#实例开发教程》
原文:<ArcGIS Engine+C#实例开发教程> 摘要:<ArcGIS Engine+C#实例开发教程>,面向 ArcGIS Engine(以下简称AE)开发初学者,本教 ...
- 《ArcGIS Engine+C#实例开发教程》第一讲桌面GIS应用程序框架的建立
原文:<ArcGIS Engine+C#实例开发教程>第一讲桌面GIS应用程序框架的建立 摘要:本讲主要是使用MapControl.PageLayoutControl.ToolbarCon ...
随机推荐
- (转)使用Spring配置文件实现事务管理
http://blog.csdn.net/yerenyuan_pku/article/details/52886207 前面我们讲解了使用Spring注解方式来管理事务,现在我们就来学习使用Sprin ...
- Android(java)学习笔记184:多媒体之 MediaPlayer使用
MediaPlayer类可用于控制音频/视频文件或流的播放.关于如何使用这个类的方法还可以阅读VideoView类的文档. 1.MediaPlayer 状态图 对播放音频/视频文件和流的控 ...
- springcloud 之 bus 消息总线
在分布式系统中,我们通常使用轻量级消息代理(rabbitmq.kafuka)建立一个公共的主题,让所有的微服务都链接进来,并且监听消费这个主题的内容,我们就称这个主题是 消息总线. (可以用作配置文件 ...
- TIOJ1208 第K大连续和
第k大的题一般都有点麻烦 pbds库的tree,需要研究一下https://codeforces.com/blog/entry/11080find_by_order() and order_of_ke ...
- 总结vue2.0 配置的实例方法
总结vue2.0 配置的实例方法 http://www.php.cn/js-tutorial-369603.html
- mysql数据库比较,各数据库不同之处
和mysql数据库比较,各数据库不同之处: Oracle数据库:字段类型不同 postgresql数据库:show tables不同; SQL语句需要前面加上 模式名 Mongodb数据库:文档存储, ...
- C++友元函数和运算符重载
非成员友元函数.成员友元函数和友元类 1.友元的作用: (1)友元提供了不同类的成员函数之间.类的成员函数与一般函数之间进行了数据共享的机制: 2.友元的优点和缺点 优点:提高程序的运行效率: 缺点: ...
- SQL Server 2008 阻止保存要求重新创建表的更改
取消[阻止保存要求重新创建表的更改]复选框
- ios operationqueue
http://www.hrchen.com/2013/06/multi-threading-programming-of-ios-part-2/
- TeeChart Pro VCL/FMX教程之使用函数
函数类型 函数特点 TeeChart Pro功能是一个系列,几乎可以是任何系列类型,应用代数函数,数据源是另一个图表系列. 所有函数都派生自TTeeFunction组件并继承TeeFunction的P ...