1. 程式人生 > >ArcEngine10.0三維開發

ArcEngine10.0三維開發

並且 perl ogr int max null 一個 cas 文檔

該系統分為四個模塊,分別是文件的操作、場景的瀏覽、點查詢和矢量文件生成TIN。下面分別對這四個模塊做詳細介紹。

文件操作。該模塊包括打開工程文件(打開sxd文件)、打開柵格文件(打開Raster文件)和保存圖片文件。所用到的控件有:SceneControl控件(用於顯示打開的工程文件和柵格文件)、

Button控件、OpenFileDialog控件、SaveFileDialog控件、TabControl控件(頁面布局控件)、TOCControl控件(用於顯示圖層)。其布局如下:

技術分享圖片

控件類型

Text屬性

控件名稱

備註

SceneControl

mSceneControl

顯示數據

TOCControl

mTOCControl

顯示圖層

Button

打開sxd文件

OpenSxdFile

打開工程的文件

Button

打開Raster文件

OpenRasterFile

打開柵格的文件

Button

保存圖片文件

SaveImage

抓圖

TabControl

兩個頁面分別為“基本操作”和“圖層”

tabControl1

分為兩個頁面,“基本操作”和“圖層”

除了上述表所列出的屬性需要設置,另外還要將TOCControl的Buddy屬性設置為mSceneControl,其方法如下:

(1) 選中TOCControl控件,右擊彈出菜單並選擇“屬性”。

(2) 彈出對話框,選擇General頁面,並找到Buddy復選框,選擇mSceneControl。

將控件的屬性設置完畢之後,為三個Button控件添加Click事件,並添加以下處理代碼:

OpenSxdFile按鈕控件的Click事件代碼:

         /************************************************************************/

        /*                  "打開sxd文件"按鈕按下事件                           
*/ /************************************************************************/ //打開sxd工程文件 private void OpenSxdFile_Click(object sender, EventArgs e) { //文件過濾 mOpenFileDialog.Filter = "sxd文件|*.sxd"; //打開文件對話框打開事件 if (mOpenFileDialog.ShowDialog() == DialogResult.OK) { //從打開對話框中得到打開文件的全路徑,並將該路徑傳入到mSceneControl中 mSceneControl.LoadSxFile(mOpenFileDialog.FileName); } }

OpenRasterFile按鈕控件的Click事件代碼:

         /************************************************************************/

        /*                  "打開Raster文件"按鈕按下事件                        */

        /************************************************************************/

        //向工程中添加柵格數據

        private void OpenRasterFile_Click(object sender, EventArgs e)

        {

            string sFileName = null;

            //新建柵格圖層

            IRasterLayer pRasterLayer = null;

            pRasterLayer = new RasterLayerClass();

            //取消文件過濾

            mOpenFileDialog.Filter = "所有文件|*.*";

            //打開文件對話框打開事件

            if (mOpenFileDialog.ShowDialog() == DialogResult.OK)

            {

                //從打開對話框中得到打開文件的全路徑

                sFileName = mOpenFileDialog.FileName;

                //創建柵格圖層

                pRasterLayer.CreateFromFilePath(sFileName);

                //將圖層加入到控件中

                mSceneControl.Scene.AddLayer(pRasterLayer,true);

                //將當前視點跳轉到柵格圖層

                ICamera pCamera = mSceneControl.Scene.SceneGraph.ActiveViewer.Camera;

                //得到範圍

                IEnvelope pEenvelop = pRasterLayer.VisibleExtent;

                //添加z軸上的範圍

                pEenvelop.ZMin = mSceneControl.Scene.Extent.ZMin;

                pEenvelop.ZMax = mSceneControl.Scene.Extent.ZMax;

                //設置相機

                pCamera.SetDefaultsMBB(pEenvelop);

                mSceneControl.Refresh();

            }

     }

SaveImage按鈕控件的Click事件代碼:

        /************************************************************************/

        /*                  "保存圖片文件"按鈕按下事件                          */

        /************************************************************************/

        //抓圖,將場景保存成圖片文件

        private void SaveImage_Click(object sender, EventArgs e)

        {

            string sFileName = "";

            //保存對話框的標題

            mSaveFileDialog.Title = "保存圖片";

            //保存對話框過濾器

            mSaveFileDialog.Filter = "BMP圖片|*.bmp|JPG圖片|*.jpg";

            //圖片的高度和寬度

            int Width = mSceneControl.Width;

            int Height = mSceneControl.Height;

            if( mSaveFileDialog.ShowDialog() == DialogResult.OK)

            {

                sFileName = mSaveFileDialog.FileName;

                if(mSaveFileDialog.FilterIndex == 1)//保存成BMP格式的文件

                {

                    mSceneControl.SceneViewer.GetSnapshot(Width, Height, 

                        esri3DOutputImageType.BMP, sFileName);

                }

                else//保存成JPG格式的文件

                {

                    mSceneControl.SceneViewer.GetSnapshot(Width, Height,

                        esri3DOutputImageType.JPEG, sFileName);

                }

                MessageBox.Show("保存圖片成功!");

                mSceneControl.Refresh();

            }

     }

有兩種方法定制場景的瀏覽,第一種方法是利用arcgis的向導,定制常用的瀏覽方法,如漫遊、放大、縮小等等,該方法簡單,並且不需要編寫代碼,第二種方法是通過添加代碼的方法更改場景的CurrentTool屬性,從而實現場景瀏覽的功能,下面對以上兩種方法一一介紹:

第一種方法:

第一步:添加ToolbarControl控件,該控件位於“工具箱”中的“ArcGIS Windows Forms”選項中,把它的名字設置為 ”mToolbarControl”,將“Dock”屬性設置為“Top”,並將其Buddy屬性設置為mSceneControl,設置方法與mTOCControl控件相同。

第二步:進入“mToolbarControl”屬性對話框中的“items”頁面,並單擊“Add…”按鈕。彈出Control Commands對話框,在Control Commands對話框中選中“Category”列表框中的“Scene”選項,在“Commands”列表中就會出現與“Scene”關聯的命令,雙擊命令就可以將該命令加入到“mToolbarControl”工具條中。

第二種方法:

第一步,加入C#工具條(ToolStrip控件),並將其“Dock”屬性設置為“Top”,

第二步,在工具條中加入按鈕,並為按鈕添加事件,並寫入事件處理程序,其代碼如下:

        /************************************************************************/

        /*                  工具條“ZoomIn”按鈕按下事件                        */

        /************************************************************************/

        //將場景的縮放

        private void ZoomIn_Click(object sender, EventArgs e)

        {

            //創建命令

            ICommand pCommand = new ControlsSceneZoomInTool();

            pCommand.OnCreate(mSceneControl.Object);

            //將當前工具設置為縮放工具

            mSceneControl.CurrentTool = pCommand as ITool;

            pCommand = null;

            //刷新

            mSceneControl.Refresh();

    }

本例僅以縮放為例,其他瀏覽工具與此相同。

SceneControl控件中常用的瀏覽功能如下:

類名

功能

ControlsSceneFlyTool (Controls)

飛行

ControlsSceneFullExtentCommand (Controls)

全景視圖

ControlsSceneNavigateTool (Controls)

導航

ControlsSceneOpenDocCommand (Controls)

打開文檔

ControlsScenePanTool (Controls)

漫遊

ControlsSceneZoomInTool (Controls)

放大

ControlsSceneZoomOutTool (Controls)

縮小

點查詢是通過鼠標點擊事件來獲取要素的方法,該功能是三維系統最常見的方法,arcgis中提供的LocateMultiple可以很方便的實現點查詢功能,以下對點查詢功能做詳細的介紹:

第一步,在主窗口中添加一個CheckBox控件,並命名為mPointSearch,如圖7所示,該控件控制是否進行點查詢操作。

第二步,新建一個Windows窗口,命名為ResultForm,並將Text屬性改為“查詢結果”ResultForm窗口中有一個TreeView控件,該控件以樹狀形式顯示了查詢的結果,如圖8所示:

技術分享圖片

第三步,為MainFrom添加私有成員函數private ResultForm mResultForm,並初始化。為mSceneControl控件添加鼠標按下事件OnMouseDown,並加入如下代碼:

        /************************************************************************/

        /*                  mSceneControl的OnMouseDown事件                      */

        /************************************************************************/

        //處理點查詢

        private void OnMouseDown(object sender, ISceneControlEvents_OnMouseDownEvent e)

        {

            if(mPointSearch.Checked)//check按鈕處於打勾狀態

            {

                //查詢

              mSceneControl.SceneGraph.LocateMultiple(mSceneControl.SceneGraph.ActiveViewer,

                    e.x, e.y, esriScenePickMode.esriScenePickAll, false, out mHit3DSet);

                mHit3DSet.OnePerLayer();

                if (mHit3DSet == null)//沒有選中對象

                {

                    MessageBox.Show("沒有選中對象");

                }

                else

                {

                    //顯示在ResultForm控件中。mHit3DSet為查詢結果集合

                    mResultForm.Show();

                    mResultForm.refeshView(mHit3DSet);

                }

                mSceneControl.Refresh();

            }

      }

第四步,在ResultForm中顯示結果結合,其代碼如下:

         //顯示結果集合

        public void refeshView(IHit3DSet pHit3Dset)

        {

            //用tree控件顯示查詢結果

            mTreeView.BeginUpdate();

            //清空tree控件的內容

            mTreeView.Nodes.Clear();

            IHit3D pHit3D;

            int i;

            //遍歷結果集

            for (i = 0; i < pHit3Dset.Hits.Count; i++)

            {

                pHit3D = pHit3Dset.Hits.get_Element(i) as IHit3D;

                if(pHit3D.Owner is ILayer)

                {

                    ILayer pLayer = pHit3D.Owner as ILayer;

                    //將圖層的名稱和坐標顯示在樹節點中

                    TreeNode node = mTreeView.Nodes.Add(pLayer.Name);

                    node.Nodes.Add("X=" + pHit3D.Point.X.ToString());

                    node.Nodes.Add("Y=" + pHit3D.Point.Y.ToString());

                    node.Nodes.Add("Z=" + pHit3D.Point.Z.ToString());

                    //將該圖層中的所有元素顯示在該樹節點的子節點

                    if(pHit3D.Object != null)

                    {

                        if (pHit3D.Object is IFeature)

                        {

                            IFeature pFeature = pHit3D.Object as IFeature;

                            int j;

                            //顯示Feature中的內容

                            for (j = 0; j < pFeature.Fields.FieldCount; j++)

                            {

                                node.Nodes.Add(pFeature.Fields.get_Field(j).Name + ":" +

                                   pFeature.get_Value(j).ToString());

                            }

                        }

                    }

                }

            }

            mTreeView.EndUpdate();

    }

本例主要是利用大量的矢量文件生成不規則三界網TIN,並顯示到mSceneControl控件中.其控件布局如下所示:

控件類型

Text屬性

控件名稱

備註

ComboBox

mLayerCombox

選擇圖層

ComboBox

mFeildCombox

選擇與圖層對應的字段

ComboBox

mTINType

選擇生成Tin文件的類型

Button

刷新圖層

RefreshLayer

將當前工程的圖層顯示到mLayerCombox中去

Button

構建TIN

ConstructTin

創建TIN

另外,由於生成Tin文件的類型是固定的,不需要從場景中獲得,所以mTINType復選框下拉菜單的內容也是固定的,可以通過修改ComboBox控件的Items屬性來設定下拉菜單的內容,如圖。本文主要介紹以下“點”、“直線”、“光滑線”三種構建TIN的類型,其他的類型請參閱arcgis幫助文檔。

技術分享圖片

為RefreshLayer按鈕添加Click事件,其代碼如下:

       /************************************************************************/

        /*             RefreshLayer按鈕Click事件                                */

        /************************************************************************/

        //刷新圖層

        private void RefreshLayer_Click(object sender, EventArgs e)

        {

            mLayerCombox.Items.Clear();

            //得到當前場景中所有圖層

            int nCount = mSceneControl.Scene.LayerCount;

            if (nCount <= 0)//沒有圖層的情況

            {

                MessageBox.Show("場景中沒有圖層,請加入圖層");

                return;

            }

            int i;

            ILayer pLayer = null;

            //將所有的圖層的名稱顯示到復選框中

            for (i = 0; i < nCount; i++)

            {

                pLayer = mSceneControl.Scene.get_Layer(i);

                mLayerCombox.Items.Add(pLayer.Name);

            }

            //將復選框設置為選中第一項

            mLayerCombox.SelectedIndex = 0;

            addFieldNameToCombox(mLayerCombox.Items[mLayerCombox.SelectedIndex].ToString());

        }

為mLayerCombox控件添加SelectedIndexChanged事件,其代碼如下:

/************************************************************************/

        /*               mLayerCombox的SelectedIndexChanged事件                 */

        /************************************************************************/

        private void OnSelectIndexChange(object sender, EventArgs e)

        {

            addFieldNameToCombox(mLayerCombox.Items[mLayerCombox.SelectedIndex].ToString());

        }

        //更加圖層的名字將該圖層的字段加入到combox中

        private void addFieldNameToCombox(string layerName)

        {

            mFeildCombox.Items.Clear();

            int i;

            IFeatureLayer pFeatureLayer = null;

            IFields pField = null;

            int nCount = mSceneControl.Scene.LayerCount;

            ILayer pLayer = null;

            //尋找名稱為layerName的FeatureLayer;

            for (i = 0; i < nCount; i++)

            {

                pLayer = mSceneControl.Scene.get_Layer(i) as IFeatureLayer;

                if (pLayer.Name == layerName)//找到了layerName的Featurelayer

                {

                    pFeatureLayer = pLayer as IFeatureLayer;

                    break;

                }

            }

            if(pFeatureLayer != null)//判斷是否找到

            {

                pField = pFeatureLayer.FeatureClass.Fields;

                nCount = pField.FieldCount;

                //將該圖層中所用的字段寫入到mFeildCombox中去

                for (i = 0; i < nCount; i++ )

                {

                    mFeildCombox.Items.Add(pField.get_Field(i).Name);

                }

            }

            mFeildCombox.SelectedIndex = 0;

        }

為ConstructTin按鈕添加Click事件,其代碼如下:

        /************************************************************************/

        /*                      ConstructTin按鈕的Click事件                     */

        /************************************************************************/

        //創建Tin

        private void ConstructTin_Click(object sender, EventArgs e)

        {

            if(mLayerCombox.Text == ""|| mFeildCombox.Text == "")//判斷輸入合法性

            {

                MessageBox.Show("沒有相應的圖層");

                return;

            }

            ITinEdit pTin = new TinClass();

            //尋找Featurelayer

            IFeatureLayer pFeatureLayer =

                mSceneControl.Scene.get_Layer(mLayerCombox.SelectedIndex) as IFeatureLayer;

            if(pFeatureLayer != null)

            {

                IEnvelope pEnvelope = new EnvelopeClass();

                IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass;

                IQueryFilter pQueryFilter = new QueryFilterClass();

                IField pField = null;

                //找字段

                pField = pFeatureClass.Fields.get_Field(pFeatureClass.Fields.FindField(mFeildCombox.Text));

                if(pField.Type == esriFieldType.esriFieldTypeInteger ||

                     pField.Type ==esriFieldType.esriFieldTypeDouble ||

                     pField.Type == esriFieldType.esriFieldTypeSingle)//判斷類型

                {

                    IGeoDataset pGeoDataset = pFeatureLayer as IGeoDataset;

                    pEnvelope = pGeoDataset.Extent;

                    //設置空間參考系

                    ISpatialReference pSpatialReference;

                    pSpatialReference = pGeoDataset.SpatialReference;

                    //選擇生成TIN的輸入類型

                    esriTinSurfaceType pSurfaceTypeCount = 

esriTinSurfaceType.esriTinMassPoint;

                    switch (mTINType.Text)

                    {

                        case "":

                            pSurfaceTypeCount = esriTinSurfaceType.esriTinMassPoint;

                            break;

                        case "直線":

                            pSurfaceTypeCount = esriTinSurfaceType.esriTinSoftLine;

                            break;

                        case "光滑線":

                            pSurfaceTypeCount = esriTinSurfaceType.esriTinHardLine;

                            break;

                    }

                    //創建TIN

                    pTin.InitNew(pEnvelope);

                    object missing = Type.Missing;  

                    //生成TIN

                    pTin.AddFromFeatureClass(pFeatureClass, pQueryFilter, pField, pField, pSurfaceTypeCount, ref missing);

                    pTin.SetSpatialReference(pGeoDataset.SpatialReference);

                    //創建Tin圖層並將Tin圖層加入到場景中去

                    ITinLayer pTinLayer = new TinLayerClass();

                    pTinLayer.Dataset = pTin as ITin;

                    mSceneControl.Scene.AddLayer(pTinLayer,true);

                }

                else

                {

                    MessageBox.Show("該字段的類型不符合構建TIN的條件");

                }

            }

     }

ArcEngine10.0三維開發