天天看點

ArcGIS Engine三維動畫開發 來自:http://www.iarcgis.com/?p=826

ArcGIS Engine 三維開發

在三維中,經常使用的一個功能就是播放動畫,也就是我們要對一條動畫軌迹進行播放,而在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等類庫,看下面的描述:

​​Animation ​​​ and ​​AnimationUI​​—Contain objects to work with animations in ArcMap, ArcScene, or ArcGlobe. An animation in ArcMap, ArcScene, or ArcGlobe is composed of animation tracks (AGAnimationTracks), which are further composed of keyframes (AGAnimationKeyframes) of the same type. Each keyframe stores properties of the animation objects. When an animation is played, keyframes are interpolated, and the interpolated properties are then applied to the animated objects to create the dynamic visual effect.

在幫助中,我們可以看到更多的資訊,首先看到實作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);      
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 =