ArcEngine10.0三維開發
該系統分為四個模塊,分別是文件的操作、場景的瀏覽、點查詢和矢量文件生成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三維開發