元件GIS 4 空間編輯
阿新 • • 發佈:2020-06-30
目錄
TODO:屬性表”屬性修改“,屬性表”欄位計算器“,”非建立要素過程中”的撤銷重做。
4.1 綱要
4.1.1 思維導圖
4.1.2 介面、列舉
- IEngineEditor,IEngineEditSketch,IEngineSketchOperation
- IPoint,IPointCollection,IGeometry,IGeometryCollection
4.1.3 效果動態圖
4.2 編輯命令
撤銷重做包括“建立要素”過程中和非“建立要素”過程中,難度較大。
4.2.1 開始編輯
//1 獲取目標圖層 cboEditingLyr.Items.Clear(); List<string> targetEditingLyr = BasicClass.GetFeatureLayerNameList(axMapControl.Map); cboEditingLyr.Items.AddRange(targetEditingLyr.ToArray()); cboEditingLyr.SelectedIndex = 0; //2 獲取工作空間&開始編輯 IDataset pSet = (IDataset)m_pFeaLyr.FeatureClass; IWorkspace pWs = pSet.Workspace; m_pEditor.EnableUndoRedo(true);//開啟撤銷重做 m_pEditor.StartEditing(pWs, axMapControl.Map);
4.2.2 儲存編輯
DialogResult isSave = MessageBox.Show("是否儲存編輯?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question); IWorkspace pWs = m_pEditor.EditWorkspace; if (isSave == DialogResult.Yes) { m_pEditor.StopEditing(true); m_pEditor.StartEditing(pWs, axMapControl.Map); axMapControl.Refresh(); }
4.2.3 停止編輯
DialogResult isSave = MessageBox.Show("是否儲存編輯?", "提示",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (isSave == DialogResult.Yes)
m_pEditor.StopEditing(true);
else
m_pEditor.StopEditing(false);
4.2.4 撤銷重做(建立要素過程中)
找了草圖工具建立要素過程中撤銷重做的官方介面很久,嘗試了IEngineEditSketch,IEngineSketchOperation,IOperationStack介面發現效果並不是我想要的,最後只能確定官方不提供,只能用C#的堆疊類實現。
注:建議先看”建立要素“思路程式碼。
撤銷
1. 初檢:草圖工具Geometry屬性不為空;
2. 入棧:草圖工具最後一個點;備份點棧;
3. 轉為點串;
4. 刪除最後一個點(面要素是倒數第二個點);
5. 複檢:草圖工具Geometry屬性為空→關閉撤銷許可。
//1 初檢
if (!m_pSketch.Geometry.IsEmpty)
{
//2 入棧
m_pPntStack.Push(m_pSketch.LastPoint);
m_pPntStackCopy = m_pPntStack;//備份
//3 刪除
IPointCollection pPntCol = (IPointCollection)m_pSketch.Geometry;
if (m_pSketch.GeometryType == esriGeometryType.esriGeometryPolygon
&& pPntCol.PointCount > 1)
pPntCol.RemovePoints(pPntCol.PointCount - 2, 1);
else
pPntCol.RemovePoints(pPntCol.PointCount - 1, 1);
m_pSketch.Geometry = (IGeometry)pPntCol;
//4 複檢/更新許可
if (m_pSketch.Geometry.IsEmpty)
canUndo = false;
canRedo = true;
}
//5 重新整理
m_pHookHelper.ActiveView.Refresh();
重做
1. 初檢:棧內要素不為空;
2. 出棧:獲取一個點;
3. 加點:草圖工具新增一個點;
4. 複檢:點棧為空→從備份棧獲取,關閉重做許可。
//1 初檢
if (m_pPntStack.Count > 0)
{
//2 出棧
IPoint pPnt = m_pPntStack.Pop();
//3 複檢
if (m_pPntStack.Count == 0)
{
m_pPntStack = m_pPntStackCopy;
canRedo = false;
}
//4 新增
m_pSketch.AddPoint(pPnt, true);
//5 許可
canUndo = true;
}
//6 重新整理
m_pHookHelper.ActiveView.Refresh();
快捷鍵設定
給axMapControl.ContextMenu屬性賦值一個右鍵選單。
4.3 要素編輯
4.3.1 建立要素
新建CreateFeatureTool類,實現ICommand和ITool介面,關鍵程式碼在ITool成員的OnMouseDown的響應事件中實現
public void OnMouseDown(int button, int shift, int x, int y)
{
//轉成地圖座標
IPoint point = m_pHookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
if (button == 1)
{
m_pSketch.AddPoint(point, true);//新增點
m_pPntStack.Clear();//清空棧
m_pPntStackCopy.Clear();//清空備份棧
canUndo = true;//允許撤銷
isFinishedSketch = false;//建立要素過程中
}
}
//完成草圖
public void OnDblClick()
{
m_pSketch.FinishSketch();
isFinishedSketch = true;
}
4.3.2 移動要素
使用元件庫ICommand cmd = new ControlsEditingEditToolClass();
4.3.3 刪除要素
使用元件庫ICommand cmd = new ControlsEditingEditToolClass();
4.4 結點編輯
要理解”IHitTest.HitTest“引數
bool isTrue = hitShape.HitTest(點選點, 搜尋範圍, 搜尋型別, 反饋點, ref 反饋距離,
ref hitPartIndex, ref hitSegmentIndex, ref bRightSide);
4.4.1 結點插入
參考幫助文件”CustomVertexCommands“,”EditingVertexCommands“。
public void OnMouseDown(int button, int shift, int x, int y)
{
//轉成地圖座標
IPoint clickedPt = m_pHookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
if (button == 1)
{
#region 1 獲取點選測試引數
IHitTest hitShape = (IHitTest)m_pSketch.Geometry;
IPoint hitPoint = new PointClass();
double hitDistance = 0;
int hitPartIndex = 0;
int hitSegmentIndex = 0;
bool bRightSide = false;
esriGeometryHitPartType hitPartType = esriGeometryHitPartType.esriGeometryPartNone;
double searchRadius = 50;
#endregion
//2 節點判斷
hitPartType = esriGeometryHitPartType.esriGeometryPartVertex;
bool isTrue = hitShape.HitTest(clickedPt, searchRadius, hitPartType, hitPoint, ref hitDistance,
ref hitPartIndex, ref hitSegmentIndex, ref bRightSide);
if (isTrue) return; //已存在節點,不需要新增
//3 點選測試
hitPartType = esriGeometryHitPartType.esriGeometryPartBoundary;
isTrue = hitShape.HitTest(clickedPt, searchRadius, hitPartType, hitPoint, ref hitDistance,
ref hitPartIndex, ref hitSegmentIndex, ref bRightSide);
//4 新增節點
if (isTrue)
{
//4.1 草圖操作開始
IEngineSketchOperation pSketchOp = new EngineSketchOperationClass();
pSketchOp.Start(m_pEditor);
pSketchOp.SetMenuString("Insert Vertex (Custom)");
//4.2 獲取點串
IGeometryCollection pGeoCol = (IGeometryCollection)m_pSketch.Geometry;
IPointCollection pPathOrRingPtCol = (IPointCollection)pGeoCol.get_Geometry(hitPartIndex);
//4.3 插入節點
object missing = Type.Missing;
object hitSegmentIndexObject = hitSegmentIndex;
object partIndexObject = hitPartIndex;
pPathOrRingPtCol.AddPoint(hitPoint, ref missing, ref hitSegmentIndexObject);
//4.4 移除舊的,新增新的
pGeoCol.RemoveGeometries(hitPartIndex, 1);
pGeoCol.AddGeometry((IGeometry)pPathOrRingPtCol, ref partIndexObject, ref missing);
//4.5 草圖操作完成
esriEngineSketchOperationType opType =
esriEngineSketchOperationType.esriEngineSketchOperationVertexAdded;
pSketchOp.Finish(null, opType, hitPoint);
}
}
}
4.4.2 結點刪除
public void OnMouseDown(int button, int shift, int x, int y)
{
//轉成地圖座標
IPoint clickedPt = m_pHookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
if (button == 1)
{
#region 1 獲取點選測試引數
IHitTest hitShape = (IHitTest)m_pSketch.Geometry;
IPoint hitPoint = new PointClass();
double hitDistance = 0;
int hitPartIndex = 0;
int hitSegmentIndex = 0;
bool bRightSide = false;
esriGeometryHitPartType hitPartType = esriGeometryHitPartType.esriGeometryPartNone;
double searchRadius = 50;
#endregion
//2 節點判斷
hitPartType = esriGeometryHitPartType.esriGeometryPartVertex;
bool isTrue = hitShape.HitTest(clickedPt, searchRadius, hitPartType, hitPoint, ref hitDistance,
ref hitPartIndex, ref hitSegmentIndex, ref bRightSide);
//3 刪除節點
if (isTrue)
{
//3.1 草圖操作開始
IEngineSketchOperation pSketchOp = new EngineSketchOperationClass();
pSketchOp.Start(m_pEditor);
pSketchOp.SetMenuString("Delete Vertex (Custom)");
//3.2 獲取點串
IGeometryCollection pGeoCol = (IGeometryCollection)m_pSketch.Geometry;
IPointCollection pPathOrRingPtCol = (IPointCollection)pGeoCol.get_Geometry(hitPartIndex);
//3.3 刪除節點
object missing = Type.Missing;
object partIndexObject = hitPartIndex;
pPathOrRingPtCol.RemovePoints(hitSegmentIndex, 1);
//4.4 移除舊的,新增新的
pGeoCol.RemoveGeometries(hitPartIndex, 1);
pGeoCol.AddGeometry((IGeometry)pPathOrRingPtCol, ref partIndexObject, ref missing);
//4.5 草圖操作完成
esriEngineSketchOperationType opType =
esriEngineSketchOperationType.esriEngineSketchOperationVertexDeleted;
pSketchOp.Finish(null, opType, hitPoint);
}
}
}
4.4.3 結點移動
使用元件庫ICommand cmd = new ControlsEditingEditToolClass();
4.5 屬性編輯
注:這裡的儲存是儲存在”工作空間“,還沒有儲存到資料庫中,需要點選【儲存編輯】才是真正的儲存在資料庫中
4.5.1 對話方塊佈局
4.5.1 關鍵程式碼
for (int i = 0; i < dgvAttributeEdit.RowCount; i++)
{
string sFieldName = (string)dgvAttributeEdit.Rows[i].Cells[0].Value;
object objFieldValue = dgvAttributeEdit.Rows[i].Cells[1].Value;
if (sFieldName != null && sFieldName != string.Empty
&& !sFieldName.ToUpper().Equals("OBJECTID") && objFieldValue != null)
{
int index = m_pFea.Fields.FindField(sFieldName);
m_pFea.Value[index] = objFieldValue;
}
}
m_pFea.Store();