前几天自己一时兴起,想根据GPS点文件做一个动画,或者叫做追踪分析吧,以前没有做过这方面的东西,第一印象应该是三维上面的沿路径飞行,我决定采用Arcsence来开发。
首先研究这个名词“路径飞行”肯定得有路径,OK,我们联想到PathGeometry或者Path,根据这两个关键字去AE10.0的帮助里去搜索,发现沿路径飞行需要IAGAnimationUtils、IAGImportPathOptions等动画接口(在ArcGlobal里同样适用)。
顺便在这里插上一句:VS2010升级后,真TM难用,帮助文件是网页形式的,而且很多帮助都找不到,还没有VS2008的帮助好用呢,而且VS2010还进行了很多重大的改进,特别是对互操作程序集的改进,也就是说我们已经习惯后面有”Class”字符的类不能用了,只能去掉”Class”后缀,具体文档详见:
http://bbs.esrichina-bj.cn/ESRI/viewthread.php?tid=107612&extra=page%3D1
http://msdn.microsoft.com/zh-cn/library/ee855831.aspx
不过研究和在网上查资料,这个问题还可以解决哦,有两种方式:
(1) 在VS项目属性中的“目标框架”里不选择.Net4.0就可以了。
(2)
在所有引用的属性里的“嵌入互操作类型”修改为false 也可以。
好了,继续上接路径飞行,既然路径飞行,那我肯定需要路径啊,那么路径就肯定是GPS的点喽,那么我们需要先处理GPS数据,使其成为点类型的Shp
(http://www.cnblogs.com/fengyunlishi/archive/2012/10/02/2710574.html),
获得点后开始生成路径线,根据路径线生成动画,具体代码如下:
主代码:
ILayerFactoryHelper pLayerFactoryHelper = new LayerFactoryHelperClass();
IFileName filename = new FileNameClass();
filename.Path = @"E:\GPSData\GSM32295.shp";
IEnumLayer enumlayer = pLayerFactoryHelper.CreateLayersFromName(filename as IName);
ILayer layer;
enumlayer.Reset();
layer = enumlayer.Next();
while (layer != null)
{
axSceneControl1.Scene.AddLayer(layer, false);
layer = enumlayer.Next();
axSceneControl1.SceneGraph.RefreshViewers();
}
// axSceneControl1.LoadSxFile(@"E:\GPSData\test.sxd"); 这句话后面有解释
IPolyline pPolyline = new PolylineClass();
pPolyline.SpatialReference = _spatial;
IPointCollection pPolycollect = pPolyline as IPointCollection;
getPointcollection(pPolycollect);
CreateAnimationFromPath(axSceneControl1.Scene, pPolyline, 1,30);
处理点击,成为PolyLine
public IPointCollection getPointcollection( IPointCollection pPolycollect)
{
IWorkspaceFactory pWSF = new ShapefileWorkspaceFactoryClass();
IFeatureWorkspace pWS = (IFeatureWorkspace)pWSF.OpenFromFile(@"E:\GPSData", 0);
IFeatureClass pFeatureclass= pWS.OpenFeatureClass("GSM32295.shp");
IFeatureCursor pCursor= pFeatureclass.Search(null, false);
while (pCursor!=null)
{
IFeature pFeature = pCursor.NextFeature();
if (pFeature != null)
{
IGeometry pGeometry = pFeature.Shape;
object objmiss = Type.Missing;
IPoint pPoint = new PointClass();
pPoint.SpatialReference = _spatial;
pPoint.X =Convert.ToDouble( pFeature.get_Value(4));
pPoint.Y = Convert.ToDouble(pFeature.get_Value(3));
pPoint.Z = Convert.ToDouble(pFeature.get_Value(5));
pPolycollect.AddPoint(pPoint, ref objmiss, ref objmiss);
}
else
{
pCursor = null;
}
}
if (pPolycollect.PointCount != 0)
return pPolycollect;
else
return null;
}
飞行代码:
//第三个参数是移动的方式,其中1表示移动观察者,2表示移动目标,其他表示两个都移动
///
///
///
///
///
///
public void CreateAnimationFromPath(IScene pScene, IPolyline _pPolyline, int _pType, double _pDuration)
{
IScene _pScene = pScene;
// 获取动画扩展对象
ESRI.ArcGIS.Analyst3D.IBasicScene2 pBasicScene2 = (ESRI.ArcGIS.Analyst3D.IBasicScene2)_pScene; // Explicit Cast
ESRI.ArcGIS.Animation.IAnimationExtension pAnimationExtension = pBasicScene2.AnimationExtension;
//创建两个对象,一个用于导入路径,一个用于播放
ESRI.ArcGIS.Animation.IAGAnimationUtils pAGAnimationUtils = new ESRI.ArcGIS.Animation.AGAnimationUtilsClass();
ESRI.ArcGIS.Animation.IAGImportPathOptions pAGImportPathOptions = new ESRI.ArcGIS.Animation.AGImportPathOptionsClass();
// 设置参数
//参数设置不正确会出错,尤其是类型,对象等信息!
pAGImportPathOptions.BasicMap = (ESRI.ArcGIS.Carto.IBasicMap)_pScene;
pAGImportPathOptions.AnimationTracks = pAnimationExtension.AnimationTracks;
pAGImportPathOptions.AnimationType = new AnimationTypeCameraClass();
// pAGImportPathOptions.AnimationType = new AnimationTypeGlobeCameraClass();
pAGImportPathOptions.LookaheadFactor = 1;
pAGImportPathOptions.PutAngleCalculationMethods(esriPathAngleCalculation.esriAngleAddRelative,
esriPathAngleCalculation.esriAngleAddRelative,
esriPathAngleCalculation.esriAngleAddRelative);
pAGImportPathOptions.AnimatedObject = _pScene.SceneGraph.ActiveViewer.Camera;//
//pAGImportPathOptions.AnimatedObject = pScene.SceneGraph.ActiveViewer.Camera;
pAGImportPathOptions.PathGeometry = _pPolyline;
//都移动
if (_pType == 1)
{
pAGImportPathOptions.ConversionType = ESRI.ArcGIS.Animation.esriFlyFromPathType.esriFlyFromPathObsAndTarget;
}//观察者移动
else if (_pType == 2)
{
pAGImportPathOptions.ConversionType = ESRI.ArcGIS.Animation.esriFlyFromPathType.esriFlyFromPathObserver;
}
else
{
pAGImportPathOptions.ConversionType = ESRI.ArcGIS.Animation.esriFlyFromPathType.esriFlyFromPathTarget;
}
pAGImportPathOptions.RollFactor = 0;
pAGImportPathOptions.AnimationEnvironment = pAnimationExtension.AnimationEnvironment;
pAGImportPathOptions.ReversePath = false;
ESRI.ArcGIS.Animation.IAGAnimationContainer AGAnimationContainer = pAnimationExtension.AnimationTracks.AnimationObjectContainer;
// pAGAnimationUtils.CreateFlybyFromPath(AGAnimationContainer,pAGImportPathOptions);
//该接口相当于播放的界面,可以自己做一个界面
IAGAnimationPlayer pAGAplayer = pAGAnimationUtils as IAGAnimationPlayer;
IAGAnimationEnvironment pAGAeviroment = new AGAnimationEnvironmentClass();
pAGAeviroment.AnimationDuration = _pDuration;
pAGAeviroment.PlayMode = esriAnimationPlayMode.esriAnimationPlayOnceForward;
pAGAplayer.PlayAnimation(_pScene as IAGAnimationTracks, pAGAeviroment, null);
注意事项:
在CreateAnimationFromPath函数中有一个
ESRI.ArcGIS.Animation.IAGAnimationContainer AGAnimationContainer = pAnimationExtension.AnimationTracks.AnimationObjectContainer;
各位一定要注意这句话,这句话的运行条件是:必须以加载.sxd的形式填充axSceneControl1,否则获得的AGAnimationContainer就会为空,即必须采用这样的方式
axSceneControl1.LoadSxFile(@"E:\GPSData\test.sxd");
但是AE中没有提供建立.sxd文档的接口,所以大家只能自己事先将.sxd做好,然后在填充axSceneControl1了。
所以本文不支持以添加图层的形式填充axSceneControl1:
axSceneControl1.Scene.AddLayer(layer, false);
而倾向于用户先把.sxd自己做好,然后在在axSceneControl1中加载:
axSceneControl1.LoadSxFile(@"E:\GPSData\test.sxd");
作者: 风云
出处: http://www.cnblogs.com/fengyunlishi/
本文版权归风云和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.