1、需求
要实现的需求就是ArcGis中的重塑(Reshape)编辑操作,在ArcGIS的帮助文档中对这一工具的说明如下图:
我的理解其实就是用一个线要素改变面或者线的形状,可以理解成操作更方便的节点编辑。
2、实现思路
如果因为需求比较急于实现可以直接跳过该部分,直接转向下一部分。通过查看ArcObject帮助,得知三个接口下有Reshape方法,分别是IRing、IPolyline、IGeometryServer2,通过接口的名字就可以排除第三个,这个操作和几何服务没有什么关系。
2.1 IPolyline.Reshape
通过查看Geometry对象模型图可以知道,IPolyline.Reshape方法中有一个IPath参数,这个IPath参数应该就是重塑线要素时画的那个形状,在ArcObject的帮助文档中也有这样的说明:
Reshape replaces the Segments in the Polyline between consecutive Intersections with the input Path segments that connect those intersections.
(重塑将折线中连续交叉点之间的线段替换为连接这些交叉点的输入路径线段。)
那么如何获取这个IPath,在对象模型图中了解到IPath和IPolyline之间存在一对多的关系,即一个Polyline对象对应多个IPath对象,所以在绘制了重塑的形状之后可以将绘制的Geometry对象转换为Polyline,Polyline对象转换为Path对象的集合,进而获得IPolyline.Reshape的IPath参数。
2.2 IRing.Reshape
对面要素进行重塑比较麻烦一点。从对象模型图中可以知道Ring对象和Polygon对象存在着多对一的关系,也就是说多个Ring对应一个Polygon,**在CSDN中的代码由于没有考虑到Polygon可能出现内环的情况,所以在内环上Reshape操作的时候是失败的,在github上更新了相关代码,可以正常操作,**所以我们要做的就是找到Polygon包含的所有Ring对象,对每一个Ring对象进行Reshape。在ArcObject的帮助中给出了获取Polygon中所有Ring的示例代码,如下:
在帮助文档中还找到了这样一句话:
Does not work in .NET. Use IPolygon4.ExteriorRingBag instead.
所以需要用IPolygon4接口。
3、代码实现
写自定义工具的代码网上有很多,这里贴出Reshape编辑操作的核心代码,代码中的reshaprGeometry是实现Reshape操作所绘制的几何对象:
IPolyline reshapePolyline,sourcePolyline = null;
IPolygon4 polygon = null;
IRing ring=null,innerRing = null,outRing=null;
IPath reshapePath = null;
IGeometryCollection pathCollection = null;
IGeometry geometry = m_selectedFeature.Shape;
switch (geometry.GeometryType)
{
case esriGeometryType.esriGeometryPolygon:
bool outerSuccess = false, innerSuccess = false;
IGeometryBag innerRingGeometryBag = null;
IGeometryCollection innerRingGeometryCollection = null;
reshapePolyline = reshaprGeometry as IPolyline;
pathCollection = reshapePolyline as IGeometryCollection;
//只可能产生一条polyline,直接写死
reshapePath = pathCollection.Geometry[0] as IPath;
polygon = geometry as IPolygon4;
IGeometryBag exteriorRingGeometryBag = polygon.ExteriorRingBag;
IGeometryCollection exteriorRingGeometryCollection = exteriorRingGeometryBag as IGeometryCollection;
for(int i = 0; i < exteriorRingGeometryCollection.GeometryCount; i++)
{
outRing = exteriorRingGeometryCollection.Geometry[i] as IRing;
bool a= outRing.Reshape(reshapePath);
outerSuccess = outerSuccess|| a;
innerRingGeometryBag = polygon.get_InteriorRingBag(outRing);
innerRingGeometryCollection = innerRingGeometryBag as IGeometryCollection;
for(int j = 0; j < innerRingGeometryCollection.GeometryCount; j++)
{
innerRing= innerRingGeometryCollection.Geometry[j] as IRing;
bool b = innerRing.Reshape(reshapePath);
innerSuccess = innerSuccess || b;
}
}
isSuccess = innerSuccess || outerSuccess;
break;
case esriGeometryType.esriGeometryPolyline:
sourcePolyline = geometry as IPolyline;
reshapePolyline = reshaprGeometry as IPolyline;
pathCollection = reshapePolyline as IGeometryCollection;
//只可能产生一条polyline,直接写死
reshapePath = pathCollection.Geometry[0] as IPath;
isSuccess = sourcePolyline.Reshape(reshapePath);
break;
}
if (isSuccess)
{
workspaceEdit.StartEditOperation();
m_selectedFeature.Shape = geometry;//如果没加这句gdb无法编辑
m_selectedFeature.Store();
m_activeView.Refresh();
workspaceEdit.StopEditOperation();
}
else
throw new Exception("重塑要素失败!");
m_activeView.Refresh();