2016.7.8 新思路探讨 文档中能用AE解决的部分
![]() |
多边形要素拓扑规则名称 |
SOE无法不通过arcserver直接操作,可能要换思路
1.直接获取shp文件
string pPath=openFileDialog1 .FileName;
string pFolder=Path.GetDirectoryName (pPath);
string pFileName=Path.GetFileName(pPath);
IWorkspace pWorkspace=pWorkspaceFactory .OpenFromFile(pFolder ,0); // 2
IFeatureWorkspace pFeatureWorkspace =pWorkspace as IFeatureWorkspace ;
IFeatureClass pFC=pFeatureWorkspace .OpenFeatureClass (pFileName ); //3
IFeatureLayer pFLayer=new FeatureLayerClass (); // 4
pFLayer.FeatureClass =pFC;
pFLayer.Name =pFC.AliasName ; // 5
ILayer pLayer=pFLayer as ILayer ;
遍历要素(可能要强制转换上面的pLayer)
IFeatureCursor pFeatureCursor;
pFeatureCursor = pFeatureLayer.FeatureClass.Search(null, false);
IFeature pFeature;
pFeature = pFeatureCursor.NextFeature();
while (pFeature != null)
{
IPolygon pPolygon = (IPolygon)pFeature.Shape;
pointcoll2.AddPointCollection(pPolygon as IPointCollection);
pFeature = pFeatureCursor.NextFeature();
}
2.ArcGIS Engine+拓扑操作
/// <summary> /// 建立拓扑 /// </summary> /// <param name="featureDataset">目标数据集</param> /// <param name="topologyName">拓扑名称</param>
public void CreateTopology(IFeatureDataset featureDataset, string topologyName)
{ // 建立一个空拓扑(拓扑名称、获得数据集的XY容差作为拓扑容差)
ITopologyContainer topologyContainer = (ITopologyContainer)featureDataset;
ITopology topology = topologyContainer.CreateTopology(topologyName,
topologyContainer.DefaultClusterTolerance, -1, "");
// 获得“Roads”线状要素类加入到拓扑当中,拓扑等级为1
IFeatureClassContainer featureclassContainer = (IFeatureClassContainer)featureDataset;
IFeatureClass featureClass = featureclassContainer.get_ClassByName("Roads");
topology.AddClass(featureClass, 5, 1, 1, false); // 建立一个拓扑规则(线丌重合)
ItopologyRuleContainer topologyRuleContainer = (ITopologyRuleContainer)topology;
ITopologyRule topologyRule = new TopologyRuleClass();
topologyRule.TopologyRuleType = esriTopologyRuleType.esriTRTLineNoOverlap;
topologyRule.OriginClassID = featureClass.ObjectClassID;
topologyRule.AllOriginSubtypes = true; topologyRule.Name = "Roads No Overlap"; // 把建立好的拓扑规则添加到拓扑中
if (topologyRuleContainer.get_CanAddRule(topologyRule))
{ topologyRuleContainer.AddRule(topologyRule); }
// 验证拓扑 IGeoDataset geoDataset = (IGeoDataset)topology;
//根据拓扑对象获得范围 IPolygon searchArea = new PolygonClass();
ISegmentCollection segmentCollection = (ISegmentCollection)searchArea;
segmentCollection.SetRectangle(geoDataset.Extent); // 获得整个拓扑中的“脏区”
IPolygon dirtyArea = topology.get_DirtyArea(searchArea); // 验证“脏区”
IEnvelope dirtyAreaEnvelope = dirtyArea.Envelope; topology.ValidateTopology(dirtyAreaEnvelope);
3.在系统中需要通过鼠标绘制图形实现裁剪,那么GP工具就不是那么方便。通过参考其他文章,实现了利用ITopologicalOperator完成裁剪功能,该方法同样适用于文件类型的裁剪图层,也适用于鼠标绘制实现裁剪。
IGeometry outputGeometry = null; //裁剪后的图形
ITopologicalOperator2 topo = null;
if (sourceGeometry.SpatialReference != clipGeometry.SpatialReference) //sourceGeometry为被裁剪的图形
{
clipGeometry.Project(sourceGeometry.SpatialReference);
} //此处应保持裁剪与被裁剪图层的空间参考一致,否则容易发生异常
switch (sourceGeometry.GeometryType)
{
case esriGeometryType.esriGeometryPolyline:
topo = sourceGeometry as ITopologicalOperator2;
topo.IsKnownSimple_2 = true;
topo.Simplify();
outputGeometry = topo.Intersect(topo.Intersect(clipGeometry, esriGeometryDimension.esriGeometry1Dimension), esriGeometryDimension.esriGeometry1Dimension);
break;
case esriGeometryType.esriGeometryPolygon:
topo = sourceGeometry as ITopologicalOperator2;
topo.IsKnownSimple_2 = true;
topo.Simplify();
outputGeometry = topo.Difference(topo.Difference(clipGeometry));
break;
default:
outputGeometry = sourceGeometry;
break;
}
return outputGeometry;
注: ITopologicalOperator接口
通过一系列基于一个或者多个几何图形中点间的逻辑比较,然后返回另外一些几何图形,这个过程就是空间几何图形的拓扑运算。
![]() |
ITopologicalOperator接口 |
空间几何图形的拓扑运算包括裁切(Clip)、凸多边形(Convex hull)、切割(Cut)、差分(Difference)、交集(Intersect)、对称差分(又称为异或,Symmetric difference)和并集(Union)等,这些拓扑运算在ITopologicalOperator接口中定义,在GeometryBag、Multipoint、Point、Polygon、Polyline类中实现。
注意ITopologicalOperator接口的方法仅仅能使用在高级几何对象上,即Point、Multipoint、Polyline和Polygon;如果要在低级的几何对象上如Segment、Path或Ring上使用,则需要先组合为高级别几何对象才行。
ITopologicalOperator::Boundary可以返回一个几何对象的边界,边界的维度比源对象要低一维。
ITopologicalOperator::Buffer可以给一个高级别几何对象产生一个缓冲区,无论是点、多边形还是多义线,他们的缓冲区都是一个具有面积的几何对象。
ITopologicalOperator::Clip方法可以将一个几何对象使用一个包络线来进行裁切,裁切的结果为几何对象被包络线包围的部分。
ITopologicalOperator::ConstructUnion方法可以将一个几何对象的枚举(包含了多个几何对象的枚举值)与同维度的单个几何对象合并,这种方法在大量几何对象合并的时候是非常有效的;Union方法则可以合并两个同维度的单个几何对象,合并后的两个单个几何对象将变成一个几何对象。
ITopologicalOperator::ConvexHull方法可以产生一个几何图形的最小的边框凸多边形。
ITopologicalOperator::Cut方法指定一条切割曲线和一个几何图形,经过切割运算后把几何图形分为左右两部分,左右两部分是相对曲线的方向而言;注意,点和多点是不能被切割的,而折线和多边形只有与切割曲线相交时才能进行切割运算。
ITopologicalOperator::Difference方法可以产生两个几何对象的差集。如A是源对象,B是参与运算的几何对象,则C是A减去A与B的交集后剩下的部分;而SymmetricDifference(对称差分)方法则是将A与B的并集减去A与B的交集部分。
ITopologicalOperator::Intersection则可以返回两个维度几何形体对象的交集,即两个对象重合部分。
参与空间拓扑运算的几何形体,必须是拓扑上简单的(topologically simple),否则会产生esriGeometryError536错误。
4.A 查询主要涉及接口: 1.IQueryFilter 通过设置这个接口的WhereClause属性来作为查询条件,本属性的语句为SQL的where后的条件语句。 2.IFeatureLayer 矢量图层,一般由ILayer进行转化。该接口的Search方法进行查询,Search方法的参数有两个,前面的是IQueryFilter对象 ,后面的是bool值,一般设为false. 3.IFeature 要素接口,用来接收查询出来的要素。 4.IFeatureCursor 游标接口,通过Search进行查询,可以讲结果保存在这里,从而利用NextFeature方法,遍历所有要素。 B 基本的思想 获取图层,设置条件,进行查询,显示要素类。 C 如何获取IFeatureLayer 地图的图层的索引从0开始,一般通过get_Layer方法或者Layer属性获取ILayer,然后将ILayer强制转换为IFeatureLayer。 D 举例 下面是一个整体的过程。 首先定义一个方法: /// /// 查询并高亮显示 /// /// 为WhereClause赋值 /// 图层,ILayer对象 public void QueryAndHight(string sql, ILayer pLayer) {//查询 this.axMapControl1.Map.ClearSelection();//清除地图的选择 IFeatureLayer pFeatureLayer = pLayer as IFeatureLayer;//定义矢量图层 IQueryFilter pQueryFilter = new QueryFilter();//实例化一个查询条件对象 pQueryFilter.WhereClause = sql;//将查询条件赋值 IFeatureCursor pFeatureCursor = pFeatureLayer.Search(pQueryFilter, false);//进行查询 IFeature pFeature; pFeature = pFeatureCursor.NextFeature();//此步是将游标中的第一个交给pFeature if (pFeature == null)//判断是否查到结果 {//如果没有查到报错并结束 MessageBox.Show('没有查询到地物!', '查询提示', MessageBoxButtons.OK, MessageBoxIcon.Information); return; } axMapControl1.Map.SelectFeature(pLayer, pFeature);//将查询到的地物作为选择对象高亮显示在地图上 axMapControl1.CenterAt(pFeature.Shape as ESRI.ArcGIS.Geometry.IPoint);//设置当前查询到的要素为地图的中心 axMapControl1.MapScale = pLayer.MinimumScale;//将当前地图的比例尺设置为ILayer的最小显示比例尺 axMapControl1.ActiveView.Refresh();//刷新地图,这样才能显示出地物 }