赞
踩
5. 如何实现经度纬度到平面坐标的相互转换?(转载)... 7
7. ArcEngine中使用上下左右键移动地图功能的实现... 15
17. ArcGIS Engine 中的相交分析的实现... 40
31. 利用ArcEngin进行空间分析的简单应用- -110
32. IfeatureSelection:SelectFeatures方法介绍... 114
36. AE开发中的一些基本方法(1)数据连接... 134
发现AE比起其它的组件GIS来要好用的多
但也有一些bt的地方
比如说AE没有提供图层编辑的工具条
但最近因为程序里要添加图元
必须得开发图层编辑的功能
于是去找了找资料
发现自带的帮助里有一个MapEditing的示例
但是从AO的示例改造而来
需要从按钮写起
想想如果这样搞的话
倒不如直接用AO算了
一直想省点事
在AE自带的工具条上做点文章
其实AE中也有一组相似的编辑按钮,是用于编辑Graphics的
自然就有了一个想法:能不能先生成一个Graphic,然后将其加载进来
琢磨了几日,终于实现了
现在把代码拿出来和大家分享
private void Form1_Load(object sender, System.EventArgs e)
{
//清空图层
this.axMapControl1.Map.ClearLayers();
//加载服务器SDE地图信息
ESRI.ArcGIS.esriSystem.IpropertySet Proset= new ESRI.ArcGIS.esriSystem.PropertySetClass();
//属性集
ESRI.ArcGIS.Geodatabase.IWorkspaceFactory Fact;//工作空间仓库
ESRI.ArcGIS.Geodatabase.IWorkspaceWorkspace;//工作空间
Proset.SetProperty("Server","服务器名");//服务器名
Proset.SetProperty("Instance","端口");//实例化端口
Proset.SetProperty("user","用户名");//SDE用户名
Proset.SetProperty("password","密码");//密码
Proset.SetProperty("version","sde.DEFAULT");//连接版本
Fact = new ESRI.ArcGIS.DataSourcesGDB.SdeWorkspaceFactoryClass();//实例化为SDE工作空间仓库
Workspace = Fact.Open(Proset,Int32.Parse(this.Handle.ToString()));//填入属性集
ESRI.ArcGIS.Geodatabase.IFeatureWorkspace FeatureWorkspace;
FeatureWorkspace = Workspace as ESRI.ArcGIS.Geodatabase.IFeatureWorkspace;//传递给Feature工作空间
ESRI.ArcGIS.Geodatabase.IFeatureClass FeatureClass;
FeatureClass =FeatureWorkspace.OpenFeatureClass("SDE.BBBB");//填充所需Feature集合
ESRI.ArcGIS.Carto.FeatureLayerFLayer = new ESRI.ArcGIS.Carto.FeatureLayerClass();
FLayer.FeatureClass =FeatureClass;//将Feature加载到图层
axMapControl1.Map.AddLayer(FLayer);//加载图层
axMapControl1.Update();//更新空白区域
axMapControl1.Refresh();//刷新地图视窗
}
private void Form1_Closed(object sender, System.EventArgs e)
{
ESRI.ArcGIS.esriSystem.IAoInitializeaoi = new ESRI.ArcGIS.esriSystem.AoInitializeClass();
aoi.Shutdown();
}
private void button1_Click(object sender, System.EventArgs e)
{
IGraphicsContainerSelectGraphicsContainerSelect = (IGraphicsContainerSelect)axMapControl1.Map;
if(GraphicsContainerSelect.ElementSelectionCount ==0)//判断是否选中图斑
{
MessageBox.Show("请选中欲导入图斑!");
return;
}
IWorkspaceEdit WorkspaceEdit;
IFeatureLayer FeatureLayer;
IFeatureClass FeatureClass;
IFeature Feature;
IDataset Dataset;
FeatureLayer =(IFeatureLayer)this.axMapControl1.get_Layer(0);//选中导入图层
FeatureClass= FeatureLayer.FeatureClass;//该图层的feature集
Dataset = (IDataset)FeatureClass;//该图层的数据集
WorkspaceEdit =(IWorkspaceEdit)Dataset.Workspace;//关联到编辑空间
WorkspaceEdit.StartEditing(true);//使之可编辑
WorkspaceEdit.StartEditOperation();//开始编辑
Feature =FeatureClass.CreateFeature();//创建空feature
Feature.Shape =GraphicsContainerSelect.SelectedElement(0).Geometry;//仅导入最新选中图斑,即多选时只有一个可以导入
Feature.Store();
WorkspaceEdit.StopEditOperation();
WorkspaceEdit.StopEditing(true);//结束编辑并保存
IGraphicsContainer GraphicsContainer= (IGraphicsContainer)GraphicsContainerSelect;
GraphicsContainer.DeleteAllElements();//删除graphic图层
axMapControl1.ActiveView.Refresh();//刷新当前视图
MessageBox.Show("ok");
}
对Feature的编辑分为以下几个部分
1.新建
2.修改
3.删除
涉及到的接口有以下几个
IWorkspaceEdit
IFeatureClass
IFeatureCursor
IFeature
其中IWorkspaceEdit用于启动编辑开始编辑操作结束编辑操作结束编辑
IFeatureClass 是数据的所在地
IFeatureCursor 是一个游标提供访问数据的接口和修改数据的接口
IFeature 是对象的代表我们要编辑的目标
编辑的过程如下:
1.添加一个Feature
//假设space是一个IWorkspaceEdit
//参数表示是否需要使用Undo/Redo功能,该功能的粒度是EditOperator.
spaceEdit.StartEditing(false);
spaceEdit.StartEditOperator();
//添加一个Feature
IFeature newFea=feaClass.createFeature();
//为Feature 添加属性设置图形
newFea.Store();//保存属性和图形
spaceEdit.StopEditOperator();//结束编辑操作
//结束编辑过程
//参数表示是否保存编辑
spaceEdit.StopEditing(true);
2.添加多个Feature
添加多个Feature也可以向上面一样使用多次就可以了
当时也可以使用IFeatureCursor来添加数据
3.修改Feature
添加Feature中的修改属性和图形部分就是
每次修改后一定要调用Store方法这样变化才可以保存下来
4.删除
IFeature 有一个方法Delete 可以用于删除当时经过测试发现对Shapefile
会抛出异常来。
IFeatureCuror有一个DeleteFeature方法可以用来删除当前的Feature,经测试
对所有的数据源类型都可以使用。
注意事项
1.不能设置Feature的OID
2.不能设置Feature的Area
3.不能设置Feature的Lenght
4.不能设置Feature的Shape字段,需要调用单独的方法来给Feature关联几何图形。
Feature是二次开发中最常用的对象,feature是featureclass中一个记录,从object中派生出来的,因此也具有属性和方法,object又是从row中派生的,所以featureclass其实一张表,featured就是表中的一条记录,feature可以保存空间数据对象,要素中的几何型体对象定义了要素的类型,它可以保存的几何型体对象有点、点集、多边形、多义线。这些都是些简单的要素对象,在有些情况下要素还可以参与拓扑、网络运算。
Feature相关接口
Feature有派生出很多类,如:networkfeature、rastercatalogfeature、coverageannotationfeature、annotationfeature、dimensionfeature。
feature的主要接口是Ifeature,其中的Extent用来返回要素对象的包络线,显示要素的空间范围;Featuretype返回要素的类型;Shape返回要素的几何型体对象;ShapeCopy得到几何型体对象的一个拷贝。
IfeatureBuffer中的Shape得到缓冲要素的几何型体对象
IfeatureEdit中MoveSet、RotateSet、DeleteSet分别是移动、旋转、删除一个或者是多个要素组成的要素集上。Split主要是用来分割几何型体的,通过点分割线,通过多义线分割多边形,分割后旧的被删除,新的要素自动产生。因为每个要素都有对应的属性,要素改变了,其对应的属性也相应的要改变。Splitattributes就是用来分割要素属性字段中的值。该方法可以在Split方法执行后自动执行。
IfeatureDraw中的InvalidArea属性得到一个绘画的区域。Draw在显示设备上绘制要素
IfeatureChanges中OriginalShape得到要素的最初几何类型,ShapeChanged指示要素的几何类型是否改变。
IfeatureSimplify中SimplifyGeometry按照该元素的拓扑规则进行拓扑一致
现在好多人在使用ArcObject的时候都可能需要作经纬度和平面坐标的相互转换。由于经纬度是球面坐标,平面坐标是X-Y的笛卡尔坐标系统,所以这是一个看起来比较难的问题。
好多人一上来就搬出地图学、地图投影学或者测绘学中的投影公式(如高斯投影或墨卡托投影),又是基准坐标又是角度的搞的人头都大了。
实际上要想实现这个功能非常easy。 ARC Engine中的IPoint就可以进行投影和反投影运算了。
投影过程(C#):
/// flatref 投影的坐标系统,这里的54013是世界投影 ,世界投影所有经纬度都可以转换为平面坐标,但是由于投影面积大失真也会比较大(相当于把整个地球劈成一片片的,然后拉伸最后贴到平面上,失真当然大了)。当然也可以选择精度更高的平面如:esriSRProjCS_Beijing1954GK_23N 对应数值21483 仅仅把北京附近的地球平面拉伸铺在平面上,由于投影面积变小,所以投影经度提高。但是由于面积变小,所以有些经度纬度不能转换,比如所美国的精度纬度用北京投影就投不了。
flatref =pfactory.CreateProjectedCoordinateSystem(54013);
//没什么说的,标准大地经纬度,可以将X-Y逆投影为经度和纬度
earthref =pfactory.CreateGeographicCoordinateSystem((int)esriSRGeoCSType.esriSRGeoCS_NAD1983);
/// 将经纬度点转换为平面坐标。
private IPoint GetProject(double x,double y)
{
IPoint pt = newPointClass();
pt.PutCoords(x, y);
IGeometry geo =(IGeometry)pt;
geo.SpatialReference =earthref;
geo.Project(flatref);
return pt;
}
/// 将平面坐标转换为经纬度。
private IPoint GetGeo(double x, doubley)
{
IPoint pt = newPointClass();
pt.PutCoords(x, y);
IGeometry geo =(IGeometry)pt;
geo.SpatialReference =flatref;
geo.Project(earthref);
double xx = pt.X;
return pt;
}实际上IPoint的投影和任何地图都没什么大关系,完全可以不用地图,直接调用IPoint进行投影的转换
//闪烁目标
public static voidFlashFeature(AxMapControl mapControl,IFeature iFeature, IMap iMap)
{
IActiveViewiActiveView = iMap as IActiveView;
if(iActiveView != null)
{
iActiveView.ScreenDisplay.StartDrawing(0,(short)esriScreenCache.esriNoScreenCache);
//根据几何类型调用不同的过程
switch (iFeature.Shape.GeometryType)
{
case esriGeometryType.esriGeometryPolyline:
FlashLine(mapControl, iActiveView.ScreenDisplay, iFeature.Shape);
break;
case esriGeometryType.esriGeometryPolygon:
FlashPolygon(mapControl, iActiveView.ScreenDisplay, iFeature.Shape);
break;
case esriGeometryType.esriGeometryPoint:
FlashPoint(mapControl, iActiveView.ScreenDisplay, iFeature.Shape);
break;
default:
break;
}
iActiveView.ScreenDisplay.FinishDrawing();
}
}
//闪烁线
static void FlashLine(AxMapControlmapControl,IScreenDisplay iScreenDisplay,IGeometry iGeometry)
{
ISimpleLineSymbol iLineSymbol;
ISymboliSymbol;
IRgbColoriRgbColor;
iLineSymbol = new SimpleLineSymbol();
iLineSymbol.Width = 4;
iRgbColor =new RgbColor();
iRgbColor.Red = 255;
iLineSymbol.Color = iRgbColor;
iSymbol =(ISymbol)iLineSymbol;
iSymbol.ROP2= esriRasterOpCode.esriROPNotXOrPen;
mapControl.FlashShape(iGeometry, 3, 200, iSymbol);
}
//闪烁面
static voidFlashPolygon(AxMapControl mapControl, IScreenDisplay iScreenDisplay, IGeometryiGeometry)
{
ISimpleFillSymbol iFillSymbol;
ISymboliSymbol;
IRgbColoriRgbColor;
iFillSymbol = new SimpleFillSymbol();
iFillSymbol.Style = esriSimpleFillStyle.esriSFSSolid;
iFillSymbol.Outline.Width = 12;
iRgbColor = new RgbColor();
iRgbColor.RGB = System.Drawing.Color.FromArgb(100, 180, 180).ToArgb();
iFillSymbol.Color = iRgbColor;
iSymbol = (ISymbol)iFillSymbol;
iSymbol.ROP2= esriRasterOpCode.esriROPNotXOrPen;
iScreenDisplay.SetSymbol(iSymbol);
mapControl.FlashShape(iGeometry, 3, 200, iSymbol);
}
//闪烁点
static void FlashPoint(AxMapControlmapControl, IScreenDisplay iScreenDisplay, IGeometry iGeometry)
{
ISimpleMarkerSymbol iMarkerSymbol;
ISymboliSymbol;
IRgbColoriRgbColor;
iMarkerSymbol = new SimpleMarkerSymbol();
iMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSCircle;
iRgbColor =new RgbColor();
iRgbColor.RGB = System.Drawing.Color.FromArgb(0, 0, 0).ToArgb();
iMarkerSymbol.Color = iRgbColor;
iSymbol =(ISymbol)iMarkerSymbol;
iSymbol.ROP2= esriRasterOpCode.esriROPNotXOrPen;
mapControl.FlashShape(iGeometry, 3, 200, iSymbol);
}
蓝蓝的小志 发表于 2005-6-510:07:08
本文以面图层为例,并且把创建的缓冲区就存储在面图层中,当然也可以把创建的缓冲区另存为一个新的图层。程序运行环境(.NET+AO)
代码如下:
Private SubITopologicalOperator_Buffer(ByVal pFeatLyr As ESRI.ArcGIS.Carto.IFeatureLayer,ByVal distance As Double, Optional ByVal pFeatClass AsESRI.ArcGIS.Geodatabase.IFeatureClass = Nothing)
'pFeatLyr 为面图层
'distance缓冲距离
Dim pFeatureClass AsESRI.ArcGIS.Geodatabase.IFeatureClass
Dim pTopoOper AsESRI.ArcGIS.Geometry.ITopologicalOperator
Dim pBufferPoly As ESRI.ArcGIS.Geometry.IPolygon
Dim pFeatCursor AsESRI.ArcGIS.Geodatabase.IFeatureCursor
Dim pFeature AsESRI.ArcGIS.Geodatabase.IFeature
Try
pFeatureClass =pFeatLyr.FeatureClass
pFeatCursor = pFeatureClass.Search(Nothing,False)
pFeature = pFeatCursor.NextFeature
Do
If Not (pFeature Is Nothing)Then
pTopoOper =pFeature.Shape()
pBufferPoly =pTopoOper.Buffer(distance)
'pFeature = pFeatClass.CreateFeature
pFeature.Shape =pBufferPoly
pFeature.Store()
pFeature =pFeatCursor.NextFeature()
End If
Loop Until (pFeature Is Nothing)
Catch
MsgBox(Err.Description,MsgBoxStyle.OKOnly, "错误提示")
pFeature = Nothing
pFeatCursor = Nothing
pBufferPoly = Nothing
pTopoOper = Nothing
pFeatureClass = Nothing
pFeatLyr = Nothing
End Try
pFeature = Nothing
pFeatCursor = Nothing
pBufferPoly = Nothing
pTopoOper = Nothing
pFeatureClass = Nothing
pFeatLyr = Nothing
End Sub
1. axMapControl1是主控件,axMapControl2是鹰眼控件
2. 1.鹰眼地图资源载入
3. private void axMapControl1_OnMapReplaced(object sender, IMapControlEvents2_OnMapReplacedEvent e)
4. {
5. //当主地图显示控件的地图更换时,鹰眼中的地图也跟随更换
6. axMapControl2.LoadMxFile(axMapControl1.DocumentFilename);
7. axMapControl2.Extent = axMapControl2.FullExtent;
8. }
9. 2.绘制鹰眼矩形框
10.private void axMapControl1_OnExtentUpdated(object sender, IMapControlEvents2_OnExtentUpdatedEvent e)
11. {
12. // 得到新范围
13. IEnvelope pEnv = (IEnvelope)e.newEnvelope;
14. IGraphicsContainer pGra = axMapControl2.Map as IGraphicsContainer;
15. IActiveView pAv = pGra as IActiveView;
16. //在绘制前,清除axMapControl2中的任何图形元素
17. pGra.DeleteAllElements();
18. IRectangleElement pRectangleEle = new RectangleElementClass();
19. IElement pEle = pRectangleEle as IElement;
20. pEle.Geometry = pEnv;
21. //设置鹰眼图中的红线框
22. IRgbColor pColor = new RgbColorClass();
23. pColor.Red = 255;
24. pColor.Green = 0;
25. pColor.Blue = 0;
26. pColor.Transparency = 255;
27. //产生一个线符号对象
28. ILineSymbol pOutline = new SimpleLineSymbolClass();
29. pOutline.Width = 2;
30. pOutline.Color = pColor;
31. //设置颜色属性
32. pColor = new RgbColorClass();
33. pColor.Red = 255;
34. pColor.Green = 0;
35. pColor.Blue = 0;
36. pColor.Transparency = 0;
37. //设置填充符号的属性
38. IFillSymbol pFillSymbol = new SimpleFillSymbolClass();
39. pFillSymbol.Color = pColor;
40. pFillSymbol.Outline = pOutline;
41. IFillShapeElement pFillShapeEle = pEle as IFillShapeElement;
42. pFillShapeEle.Symbol = pFillSymbol;
43. pGra.AddElement((IElement)pFillShapeEle, 0);
44. pAv.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
45. }
46.3. 实现互动
47. private void axMapControl2_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
48. {
49. IPoint pPt=new PointClass ();
50. pPt.PutCoords (e.mapX ,e.mapY );
51. //改变主控件的视图范围
52. axMapControl1 .CenterAt (pPt );
53. }
拓扑(ITopology)的使用包括
1.建立拓扑
2.验证拓扑
3.编辑过程中保证拓扑的正确
4.查询系统中存在的拓扑
1.首先 来看看建立拓扑
Topology实现了ITopology这个接口 但是给类是不能用来创建对象的。
必须要通过调用 ITopologyContainer::CreateTopology这个方法来建立一个Topology
FeatureDataset 实现了ITopologyContainer这个接口。那么 这就是说拓扑只能在一个
FeatureDataset的范围内建立。而不能独立存在于Workspace中。这样做的原因是需要保证
参与同一个拓扑的FeatureClass具有同一个投影坐标系统。 建立拓扑后需要将ObjectClass
加入到拓扑中去。这样这个拓扑就可以用来验证这几个ObjectClass 的对象之间的关系了。
验证关系就要有规则,规则是由ITopologyRule来表达的。ITopologyRule必须要被
加入到一个ITopologyRuleContainer中去。而Topology实现了这个接口。
一个ITopologyRule用来表达两个ObjectClass的对象之间的某个关系。
具体代码参看接口就可以了。
2.验证拓扑
ITopology有一个方法 ValidateTopology 用来验证指定区域内的拓扑。需要注意没有版本
的拓扑可以在 任何时候验证。而有版本的拓扑必须在编辑回话中验证。
3.拓扑编辑
1.移动共用点
1.首先需要打开拓扑 建立拓扑图(ITopologyGraph)
代码如下:
//topoLayer 是一个打开的拓扑图层
ITopologyGraph pTG=topoLayer.Topology.Cache;
pTG.Build(pA.Extent,false);
2.然后 需要获得当前节点或者边 这个操作要使用拓扑图的点击测试
ITopologyElement topeEle
pTG.HitTest(... ref topeEle);
这个方法在点击测试成功的时候返回true.而且会通过topeEle这个ref 参数将选中的元素(点或者边)
返回.
3.还有一种获取节点的方法
首先调用拓扑图的Select方法 选中点击测试的元素(pTG.Select)
然后可以查询拓扑图的选中节点集合 就可以找到该节点(pTG.NodeSelection)
4.为该元素使用一个Feedback.
//其中 pNode 就是当前节点 sr 是参考坐标系可以使用null
//还有给Feedback设置Display
m_pNodeFeedback =pTG.GetSplitMoveNodeFeedback(pNode,false,sr);
m_pNodeFeedback.Display= activeView.ScreenDisplay;
5.在鼠标移动的时候 调用Feedback的MoveTo 方法。
if(m_pNodeFeedback!=null)
{
//activeView 是活动的试图
//首先要把将点坐标转换为地图中的坐标。
//然后调用MoveTo 方法
IPoint pt=activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(X,Y);
m_pNodeFeedback.MoveTo(pt);
}
6.在鼠标释放的时候
//获取拓扑图
ITopologyGraph pTG=topoLayer.Topology.Cache;
//转换坐标
IPoint pt=pA.ScreenDisplay.DisplayTransformation.ToMapPoint(X,Y);
//获得正在做拓扑编辑的元素
ITopologyNode pTN=(ITopologyNode)m_pTopoElement;
//实施拓扑编辑
pTG.SplitMoveNode(pTN,pt,false);
//提交拓扑编辑结果
IEnvelope pE;
pTG.Post(out pE);
4.查询系统中的拓扑
还是ITopologyContainer 这个接口 这个接口有FeatureDataset这个唯一的实现。
CreateTopology 建立一个新的拓扑
DefaultClusterTolerance The default cluster tolerance as per the topologyengine.
MaximumClusterTolerance The maximal cluster tolerance as per the topologyengine.
MinimumClusterTolerance The minimal cluster tolerance as per the topologyengine.
Topology 通过索引打开拓扑.
TopologyByID 通过ID打开拓扑.
TopologyByName 通过名字打开拓扑
TopologyCount 拓扑的数目
进行接口的介绍,必须介绍一下程序语言发展的历史才行,鲁迅先生说过“治学先治史”,明白了程序语言发展的前世今生,才能知道为什么这么多语言为什么会这样,为什么么会那样?
计算机出现以后,科学家相继开发了多种语言,从smalltalk,Pascal,Basic,C语言,C++,java,.net等等,这些语言的发展步伐,可以看作是从面向过程向面向对象发展的一段历史。很多面向对象的书在介绍自己的历史的时候,都会给读者介绍这一段历史,并鼓吹OO编程是多么多么的优异。问题是,很多刚开始学程序的人根本不知道为什么要有这个转变,他们也很难理解OO语言中的虚函数,接口等概念到底为了什么而提出来。
我们在了解这一段历史以前,首先给大家介绍一个概念??“粒度”,什么是粒度?作者认为所谓粒度其实就是一个程序中使用代码单元的组合尺度,我们可以举一个例子,沙砾??砖块??房屋模板,我们设想去修建一座房子,其实有很多中修筑方法,如果你不闲麻烦,可以使用沙砾一点点地建筑,或者将沙砾烧制为砖块,用砖块来砌,甚至直接从工厂购买房屋的门,窗,墙组件来堆砌。这三种不同的方法代表了三种不同的组合尺度。沙砾是最小的单位,使用它搭建小的房子说不定还可以,但是毫无疑问,我们必须使用很多很多“沙砾”,不便于管理;砖块比沙砾聚合了一层,可以用来修建较大的房子了;房屋模板是最高的尺寸,使用它可以快速地搭建大规模的房屋。这三种尺度的区别和联系,与我们编写程序概念是有很大的相似之处的。
在早期学习Pascal,老师告诉我们这种面向过程语言的最基本的单元是过程和函数,它们是程序中的最小的组件。过程和函数可以实现最基本的代码重用,当我们把某些固定功能的代码使用过程和函数编写后,我们可以在程序中调用它们而不必在任何需要的地方都写上这样一段代码,这样的好处是显而易见的。在一些小型的程序里面,使用过程和函数是合适的,但是在大中型程序中,它们的弊端就显示出来,过程和函数的粒度太低了,如果我们一个系统,有10000个函数和过程,我们的程序员将不得不花费大量的时间去寻找和维护它们,10000个没有任何关系的函数和过程的管理难度是显而易见的,就好像10000个人的企业一样,如果没有部门和职务,这还不乱了套?!
面向对象语言的出现,就是为了解决这个问题,别听OO语言吹的天花乱坠,其实它出现就为一个理由??提高编程的粒度。面向对象语言的基本单位是类CLASS,类封装了很多数据成员和成员函数,过程,将最小组件的提高了一个等级,我们需要直接操作的不是过程和函数了,而是一个个更高层次上的类。我们把10000人分了很多部门,不同的部门负责不同的事宜,这样公司终于可以走上正轨了。
做成了类CLASS是否就万事大吉了呢?不一定,新的问题随之而来,也许我们有一个部门的人很多,可以做很多事情,如何在部门内部实现更好的管理呢?好比我们有一个类,它提供了很多种方法和属性,这些方法和属性其实可以分为一堆堆,为不同的功能服务,但是我们的类并没有做这个管理。在AO种,map对象拥有很多功能,比如管理图层,管理元素,管理选择集,进行地图显示,每种不同的功能都有好多方法和属性,现在这些属性和方法是杂乱无章,没有任何区别堆积在一个类里面的,当我们的程序员需要寻找一个方法的时候,不得不一个个去寻找,很不方便。
这个时候,接口interface出现了,C++的发明者第一次提出纯虚函数(其实就是接口)概念的时候,遭到了很多抵制,很多人都不明白接口的意义何在,我们用虚函数好好的,何必又出来个啥东西都没有的空架子?说它是类吧,又不能实现产生一个对象;说它是对象吧,又没有方法体来使用。接口出来干了一件好事,就是将类内部进行分类。对于map对象,我们可以做好几个接口,这些接口中定义不同功能的方法,函数和属性,map类实现这些接口,这样我们可以使用接口定义,实现对象。因此,所谓接口就是一系列相关方法与属性集合的定义。
Dim pGraphicsContainer as iGraphicsContainer
pGraphicsContainer=application.document.ActiveView.focusMap
pGraphicsContainer可以使用的属性和方法就只能是它定义的那部分了,而不能使用管理元素等的接口定义的方法和属性,那我们如何使用其它的功能呢?这就是所谓的QI(QueryInterface)功能。从一个接口查询另一个接口。
Dim pGeoFeatureLayer as iGeofeatureLayer
pGeoFeatureLayer= pGraphicsContainer QI
好了,我们罗嗦了这么多,已经走进了COM的概念了,在正式介绍COM以前我们得最后罗嗦一点:计算机语言的发展历史,其实就是一部不断提高组件粒度的历史,不断提高代码重用的历史。以前我们使用过程和函数,后来我们使用类,现在我们使用接口,都是为了一个目的,让我们操作的组件在具体和抽象之间寻找一个平衡点。太具体了,如过程和函数,就没有了框架;太抽象,如类,就无法分别。
一个代码示例:
public interface IForm
{
void Show();
void ShowDialog();
}
public class A:IForm
{
public void Show()
{
}
public void ShowDialog()
{
}
}
public class B:IForm
{
public void Show()
{
}
public void ShowDialog()
{
}
}
public class FormFactory
{
public static IForm CreateInstance(string parm)
{
if (parm == "A")
{
return new A();
else if (parm == "B")
return new B();
}
return null;
}
}
这是逻辑的抽象
这是方法的具体
这就是编写程序的哲学.
//闪烁目标
public static voidFlashFeature(AxMapControl mapControl,IFeature iFeature, IMap iMap)
{
IActiveViewiActiveView = iMap as IActiveView;
if(iActiveView != null)
{
iActiveView.ScreenDisplay.StartDrawing(0,(short)esriScreenCache.esriNoScreenCache);
//根据几何类型调用不同的过程
switch (iFeature.Shape.GeometryType)
{
case esriGeometryType.esriGeometryPolyline:
FlashLine(mapControl, iActiveView.ScreenDisplay, iFeature.Shape);
break;
case esriGeometryType.esriGeometryPolygon:
FlashPolygon(mapControl, iActiveView.ScreenDisplay, iFeature.Shape);
break;
case esriGeometryType.esriGeometryPoint:
FlashPoint(mapControl, iActiveView.ScreenDisplay, iFeature.Shape);
break;
default:
break;
}
iActiveView.ScreenDisplay.FinishDrawing();
}
}
//闪烁线
static void FlashLine(AxMapControlmapControl,IScreenDisplay iScreenDisplay,IGeometry iGeometry)
{
ISimpleLineSymbol iLineSymbol;
ISymboliSymbol;
IRgbColoriRgbColor;
iLineSymbol = new SimpleLineSymbol();
iLineSymbol.Width = 4;
iRgbColor =new RgbColor();
iRgbColor.Red = 255;
iLineSymbol.Color = iRgbColor;
iSymbol =(ISymbol)iLineSymbol;
iSymbol.ROP2= esriRasterOpCode.esriROPNotXOrPen;
mapControl.FlashShape(iGeometry, 3, 200, iSymbol);
}
//闪烁面
static voidFlashPolygon(AxMapControl mapControl, IScreenDisplay iScreenDisplay, IGeometryiGeometry)
{
ISimpleFillSymbol iFillSymbol;
ISymboliSymbol;
IRgbColoriRgbColor;
iFillSymbol = new SimpleFillSymbol();
iFillSymbol.Style = esriSimpleFillStyle.esriSFSSolid;
iFillSymbol.Outline.Width = 12;
iRgbColor = new RgbColor();
iRgbColor.RGB = System.Drawing.Color.FromArgb(100, 180, 180).ToArgb();
iFillSymbol.Color = iRgbColor;
iSymbol = (ISymbol)iFillSymbol;
iSymbol.ROP2= esriRasterOpCode.esriROPNotXOrPen;
iScreenDisplay.SetSymbol(iSymbol);
mapControl.FlashShape(iGeometry, 3, 200, iSymbol);
}
//闪烁点
static void FlashPoint(AxMapControlmapControl, IScreenDisplay iScreenDisplay, IGeometry iGeometry)
{
ISimpleMarkerSymboliMarkerSymbol;
ISymboliSymbol;
IRgbColoriRgbColor;
iMarkerSymbol = new SimpleMarkerSymbol();
iMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSCircle;
iRgbColor =new RgbColor();
iRgbColor.RGB = System.Drawing.Color.FromArgb(0, 0, 0).ToArgb();
iMarkerSymbol.Color = iRgbColor;
iSymbol =(ISymbol)iMarkerSymbol;
iSymbol.ROP2= esriRasterOpCode.esriROPNotXOrPen;
mapControl.FlashShape(iGeometry,3, 200, iSymbol);
}
编号: 000037 相关产品及版本: ArcSDE 3.x,8.x,9.0 平台: N/A
提交时间: 2004-08-23 修改时间: 2004-08-31 提交人: 吴乐茂
内容摘要
有时候,我们需要有多于一个的ArcSDE实例同时运行。只要存在多个数据库实例,就可以实现这个目的。ArcSDE与RDBMS之间必须是一个一一对应的关系。ArcSDE会锁定版本表,以保证每个数据库实例只对应一个ArcSDE实例。
过程描述
对于Windows:
1. 拷贝 %SDEHOME% 到一个新的位置。
2. 用适当的RDBMS连接变量(如RACLE_SID)更新新的dbinit.sde 文件。
3. 用新的实例名、端口号和网络协议更新%SDEHOME%etcservices.sde文件。
4. 添加服务名、端口号和网络协议到WINNTsystem32driversetcservices 文件中。须确认所用的端口号没有被用过。
5. 删除新的giomgr.log文件中的内容。
6. 如果需要,更新新的giomgr.defs文件,以指定新实例的操作参数。
7. 如果需要,更新新的dbtune.sde 文件,以指定参数给在新实例的数据库中创建数据时使用。
8. 确认SDEHOME 变量指向正确的新ArcSDE实例位置,并运行给对应数据库使用的sdesetup 命令来创建新数据的存储表。
9. 使用 “sdeservice -o create” 命令创建新的ArcSDE服务。
对于UNIX:
1. 给新实例创建一个新的工作目录。
2. 拷贝 $SDEHOME 到新创建的工作目录。
3. 用适当的RDBMS 连接变量(如ORACLE_SID)更新新的dbinit.sde 文件。
4. 用新的实例名、端口号和网络协议更新$SDEHOME/etc/services.sde 文件。
5. 添加服务名、端口号和网络协议到 /etc/services 文件。须确认所用的端口号没有被用过。
6. 删除新的giomgr.log文件中的内容。
7. 如果需要,更新新的giomgr.defs文件,以指定新实例的操作参数。
8. 如果需要,更新新的dbtune.sde 文件,以指定参数给在新实例的数据库中创建数据时使用。
9. 确认SDEHOME 变量指向正确的新ArcSDE实例位置,并运行给对应数据库使用的sdesetup 命令来创建新数据的存储表。
常用ArcSDE命令
启动cmd
1. 创建和删除ArcSDE服务操作命令(sdeservice)
创建ArcSDE for oracle9i服务 sdeservice -o create -d oracle9i,sid -p sde -i esri_sde
删除ArcSDE for oracle9i服务 sdeservice -o delete -i esri_sde -d oracle9i,sid
注:-d 后面填写数据库类型及其SID
sdeservice命令帮助
创建、删除SDE服务
2.ArcSDE 服务操作命令(sdemon)
检测服务状态命令: Sdemon -o status -I esri_sde
启动服务命令: Sdemon -o start -I esri_sde -p sde
停止服务命令: Sdemon -o shutdown -I esri_sde -p sde
Sdemon命令帮助
更多操作命令,请查看路径“\ArcSDE\ora9iexe\bin”下的“*.exe”文件
[ 来源:cnblogs.com | 作者:Flyingis | 时间:2007-04-20 09:26:57 | 收藏本文 ] 【大 中小】
ArcEngine Geometry库定义了基本几何图形的矢量表达形式,顶级的几何图形有Points、Multipoints、Polylines、Polygons、 Multipatches,Geodatabase和绘图系统使用这些几何图形来定义其他各种形状的特征和图形,提供了编辑图形的操作方法和地图符号系统符号化特征数据的途径。
Geometry库中几个核心类和接口构成了Geometry对象的基本框架。
GeometryEnvironment
GeometryEnvironment提供了从不同的输入、设置或获取全局变量来创建几何图形的方法,以便控制geometry方法的行为。GeometryEnvironment对象是一个单例对象。
以下为引用的内容:
public IPolyline TestGeometryEnvironment()
{
ISpatialReferenceFactory spatialReferenceFactory = newSpatialReferenceEnvironmentClass();
//Create a projected coordinate system and define its domain,resolution, and x,y tolerance.
IspatialReferenceResolutionspatialReferenceResolution =spatialReferenceFactory.CreateProjectedCoordinateSystem((int)esriSRProjCSType.esriSRProjCS_NAD1983UTM_11N)as ISpatialReferenceResolution;
spatialReferenceResolution.ConstructFromHorizon();
ISpatialReferenceTolerance spatialReferenceTolerance =spatialReferenceResolution as ISpatialReferenceTolerance;
spatialReferenceTolerance.SetDefaultXYTolerance();
ISpatialReference spatialReference = spatialReferenceResolution asISpatialReference;
Chinaz.com
//Create an array of WKSPoint structures starting in the middle of thex,y domain of the
//projected coordinate system.
double xMin;
double xMax;
double yMin;
double yMax;
spatialReference.GetDomain(out xMin, out xMax, out yMin, out yMax);
double xFactor = (xMin + xMax) * 0.5;
double yFactor = (yMin + yMax) * 0.5;
WKSPoint[] wksPoints = new WKSPoint[10];
for (int i = 0; i < wksPoints.Length; i++)
{
wksPoints[i].X = xFactor + i;
wksPoints[i].Y = yFactor + i;
}
IPointCollection4 pointCollection = newPolylineClass();
IGeometryBridge2 geometryBridge = new GeometryEnvironmentClass();
geometryBridge.AddWKSPoints(pointCollection, ref wksPoints);
IPolyline polyline = pointCollection as IPolyline;
polyline.SpatialReference= spatialReference;
return polyline;
}
newGeometryEnvironmentClass仅仅是创建了一个指向已存在的GeometryEnvironmentClass的引用。注意 IGeometryBridge2接口的使用,addWKSPoints方法将WKSPoint二维点添加到PointCollection中,用于构建 path、ring、polyline、polygon,或增加新点到Multipoint、TriangleFan、TriangleStrip。在 Geometry库中,除了IGeometryBridge2还有IGeometryBridge接口,后者继承了前者,增加了一些编辑功能(添加点、插入点、重置点、分段等)。 GeometryBag
GeometryBag是支持IGeometry接口的几何对象引用的集合,任何几何对象都可以通过IGeometryCollection接口添加到 GeometryBag中,但是在使用拓扑操作的时候,需要注意不同类型的几何类型可能会有相互不兼容的情况。在向GeometryBag中添加几何对象的时候,GeometryBag对象需要指定空间参考,添加到其中的几何对象均拥有和GeometryBag对象一样的空间参考。
以下为引用的内容:
private IPolygonGeometryBag_Example(IFeatureClass featureClass)
{
//Check input objects.
if (featureClass == null)
{
return null;
}
IGeoDataset geoDataset = featureClass asIGeoDataset;
ISpatialFilter queryFilter = new SpatialFilterClass();
//Set the properties of the spatial filter here.
IGeometry geometryBag = new GeometryBagClass();
//Define the spatial reference of the bag before adding geometries toit.
geometryBag.SpatialReference = geoDataset.SpatialReference;
//Use a nonrecycling cursor so each returned geometry is a separateobject.
IFeatureCursor featureCursor = featureClass.Search(queryFilter, false);
IGeometryCollection geometryCollection = geometryBag asIGeometryCollection;
IFeature currentFeature = featureCursor.NextFeature();
while (currentFeature != null)
{
//Add a reference to this feature's geometry into the bag.
//You don't specify the before or after geometry (missing),
//so the currentFeature.Shape IGeometry is added to the end of thegeometryCollection.
object missing = Type.Missing;
geometryCollection.AddGeometry(currentFeature.Shape, ref missing, refmissing);
currentFeature = featureCursor.NextFeature();
}
// Create the polygon that will be the union of the features returnedfrom the search cursor.
// The spatial reference of this feature does not need to be set aheadof time. The
// ConstructUnion method defines the constructed polygon's spatialreference to be the same as
// the input geometry bag.
ITopologicalOperator unionedPolygon = new PolygonClass();
unionedPolygon.ConstructUnion(geometryBag as IEnumGeometry);
return unionedPolygon as IPolygon;
}
Points
一个点包括X、Y坐标,同时可以增加M、Z值及ID属性来扩展点的功能。
Multipoints
点的集合,多点组成Multipoint几何类型,使用multipoint对象实现了的IPointCollection接口可以访问所有的点元素,这些点同样可以拥有M、Z值及ID属性来获得更多的地理空间内涵。
下面列举一个例子,通过一个已知的polyline来定义一个新的multipart polyline。
以下为引用的内容:
public IPolylineConstructMultiPartPolyline(IPolyline inputPolyline)
{
IGeometry outGeometry = new PolylineClass();
//Always associate new, top-level geometries with an appropriate spatialreference.
outGeometry.SpatialReference = inputPolyline.SpatialReference;
IGeometryCollection geometryCollection = outGeometry asIGeometryCollection;
ISegmentCollection segmentCollection = inputPolyline asISegmentCollection;
//Iterate over existing polyline segments using a segment enumerator.Chinaz^com
IEnumSegment segments = segmentCollection.EnumSegments;
ISegment currentSegment;
int partIndex = 0;;
int segmentIndex = 0;;
segments.Next(out currentSegment,ref partIndex, ref segmentIndex);
while(currentSegment != null)
{
ILine normal = new LineClass();
//Geometry methods with _Query_ in their name expect to modify existinggeometries.
//In this case, the QueryNormal method modifies an existing line
//segment (normal) to be the normal vector to
//currentSegment at the specified location along currentSegment.
currentSegment.QueryNormal(esriSegmentExtension.esriNoExtension, 0.5,true, currentSegment.Length / 3, normal);
//Since each normal vector is notconnected to others, create a new path for each one.
ISegmentCollection newPath = new PathClass();
object missing = Type.Missing;
newPath.AddSegment(normal as ISegment, ref missing, ref missing);
//The spatial reference associated with geometryCollection will beassigned to all incoming paths and segments.
geometryCollection.AddGeometry(newPath as IGeometry, ref missing, refmissing);
segments.Next(out currentSegment,ref partIndex, ref segmentIndex);
}
//The geometryCollection now contains the new, multipart polyline.
return geometryCollection as IPolyline;
}
ISegment接口的QueryNormal方法用来在弧段上的某一点生成该弧段的法线,指定其长度,这样就生成了新的segment,并且多个path添加到geometryCollection中,以IPolyline的形式返回。
Polylines
Polylines是有序path组成的集合,可以拥有M、Z和ID属性值。Polyline对象的IPointCollection接口包含了所有节点的复制,IGeometryCollection接口可以获取polyline的paths,ISegmentCollection接口可以获取 polyline的segments。
Polyline结构图
Polygons
Polygon是一系列rings组成的集合,可以拥有M、Z和ID属性值。每一个ring由一个或多个segment组成,Polygon或ring对象的IPointCollection接口包含了所有节点的复制,IGeometryCollection接口可以获取polygon的rings,ISegmentCollection接口可以获取polygon的segments。
Polygon结构图
Multipatch
Multipatch用于描述3D面状几何类型,由一系列的矢量三角形构成,如果其中的part是一个ring,那么它必须是封闭的,第一个节点和最后一个节点相同,另外每个part所包含节点的顺序非常重要,Inner Rings在Outer Rings之后,代表单个表面patch的一系列rings必须由第一个ring开始。
在9.0以后的开发包中,使用IGeneralMultiPatchCreator创建新的Multipatch,IGeometryMaterial进行材质贴图。
以下为引用的内容:
public IMultiPatch CreateMultipatch()
{
//Prepare the geometry material list.
IGeometryMaterial texture = newGeometryMaterialClass();
texture.TextureImage = "C:\\Temp\\MyImage.bmp";
IGeometryMaterialList materialList = new GeometryMaterialListClass();
materialList.AddMaterial(texture);
//Create the multipatch.
IGeneralMultiPatchCreator multiPatchCreator= new GeneralMultiPatchCreatorClass();
multiPatchCreator.Init(4, 1, false, false, false, 4, materialList);
//Set up part.
//Could also use a Ring or a TriangleFan.
multiPatchCreator.SetPatchType(0,esriPatchType.esriPatchTypeTriangleStrip);
multiPatchCreator.SetMaterialIndex(0, 0);
multiPatchCreator.SetPatchPointIndex(0, 0);
multiPatchCreator.SetPatchTexturePointIndex(0, 0);
//Set real-world points.
WKSPointZ upperLeft = newWKSPointZ();
WKSPointZ lowerLeft = newWKSPointZ();
WKSPointZ upperRight = new WKSPointZ();
WKSPointZ lowerRight = new WKSPointZ();
upperLeft.X = 0;
upperLeft.Y = 0;
upperLeft.Z = 0;
upperRight.X = 300;
upperRight.Y = 0;
upperRight.Z = 0;
lowerLeft.X = 0;
lowerLeft.Y = 0;
lowerLeft.Z = -100;
lowerRight.X = 300;
lowerRight.Y = 1;
lowerRight.Z = -100;
multiPatchCreator.SetWKSPointZ(0, ref upperRight);
multiPatchCreator.SetWKSPointZ(1, ref lowerRight);
multiPatchCreator.SetWKSPointZ(2, ref upperLeft);
multiPatchCreator.SetWKSPointZ(3, ref lowerLeft);
//Set texture points.
//Set the texture coordinates for a panel.
WKSPoint textureUpperLeft = newWKSPoint();
WKSPoint textureLowerLeft = newWKSPoint();
WKSPoint textureUpperRight = new WKSPoint();
WKSPoint textureLowerRight = new WKSPoint();
textureUpperLeft.X = 0;
textureUpperLeft.Y = 0;
textureUpperRight.X = 1;
textureUpperRight.Y = 0;
textureLowerLeft.X = 0;
textureLowerLeft.Y = 1;
textureLowerRight.X = 1;
textureLowerRight.Y = 1;
multiPatchCreator.SetTextureWKSPoint(0, ref textureUpperRight);
multiPatchCreator.SetTextureWKSPoint(1, ref textureLowerRight);
multiPatchCreator.SetTextureWKSPoint(2,ref textureUpperLeft);
multiPatchCreator.SetTextureWKSPoint(3, ref textureLowerLeft);
IMultiPatch multiPatch = multiPatchCreator.CreateMultiPatch() asIMultiPatch;
return multiPatch;
}
GIS的面向用户的应用功能不仅仅表现在它能提供一些静态的查询、检索数据,更有意义的在于用户可以根据需要建立一个应用分析的模式,通过动态的分析,从而为评价、管理和决策服务。这种分析功能可以在系统操作运算功能的支持下或建立专门的分析软件来实现,如空间信息量测与分析、统计分析、地形分析、网络分析、叠置分析、缓冲分析、决策支持等。系统本身是否具有建立各种应用模型的功能是判别它好坏的重要标志之一,因为这种功能在很大程度上决定了该系统在实际应用中的灵活性和经济效益。
空间查询和空间分析是从GIS目标之间的空间关系中获取派生的信息和新的知识,用以回答有关空间关系的查询和应用分析。
拓扑空间查询
在此操作中,用户将地图当作查询工具,而不仅仅是数据载体。空间目标之间的拓扑关系可以有两类:一种是几何元素的结点、弧段和面块之间的关联关系,用以描述和表达几何元素间的拓扑关系;另一种是GIS中地物之间的空间拓扑关系,可以通过关联关系和位置关系隐含表达,用户需通过特殊的方法查询。
这些空间关系主要有以下几项:面与面的关系,如检索与某个面状地物相邻的所有多边形及属性;线与线的关系,如检索与某一主干河相关联的所有支流;点与点的关系,如检索到某点一定距离内的所有点状地物;线与面的关系,如检索某公路所经过的所有县市或某县市内的所有公路;点与线的关系,如某河流上的所有桥梁;点与面的关系,如检索某市所有银行分布点。
缓冲区分析
缓冲区用以确定围绕某地要素绘出的定宽地区,以满足一定的分析条件。点的缓冲区是个圆饼,线的缓冲区是个条带状,多边形的缓冲区则是个更大的相似多边形。缓冲区分析是GIS中基本的空间分析功能之一,尤其对于建立影响地带是必不可少的。如道路规划中建立缓冲区以确定道路两边若干距离内的土地利用性质。
叠加分析
叠加分析提供根据两幅或两幅以上图层在空间上比较地图要素和属性的能力,通常有合成叠加和统计叠加之分,前者是根据两组多边形边界的交点建立具有多重属性的多边形,后者则进行多边形范围的属性特征统计分析(如图1-3所示)。合成叠加得到一张新的叠加图,产生了许多新多边形,每个多边形都具有两种以上的属性。统计叠加的目的是统计一种要素在另一种要素中的分布特征。
距离分析及相邻相接分析
距离分析提供了在地图上距离的功能,相邻分析确定哪些地图要素与其它要素相接触或相邻,而相接分析则结合距离和相邻分析两者的针对性,提供确定地图要素间邻近或邻接的功能。相邻和相接分析广泛应用于环境规划和影响评价的公共部门。大多数GIS软件目前不能直接进行相邻相接分析,而是通过先建立一定要求的缓冲区,再与其它图形要素进行叠置分析的间接方法解决。
地形分析功能
通过数字地形模型DTM,以离散分布的平面点来模拟连续分布的地形,再从中内插提取各种地形分析数据,地形分析包括以下内容:
等高线分析
等高线图是人们传统上观测地形的主要手段,可以从等高线上精确地获得地形的起伏程度,区域内各部分的高程等。
透视图分析
等高线虽然精确,但不够直观,用户往往需要从直观上观察地形的概貌,所以GIS通常具有绘制透视图的功能,有些系统还能在三维空间格网上着色,使图形更为逼真。
坡度坡向分析
在DTM中计算坡度和坡向,派生出坡度坡向图供地形分析(如日照分析、土地适宜性分析等)。
断面图分析
用户可以在断面图上考察该剖面地形的起伏并计算剖面面积,以便用于工程设计和工程量算。
地形表面面积和填挖方体积计算
利用DTM数据,可以比较容易地求出所需要地区的地形表面面积以及施工区域内填挖方的体积(土石方量)。
制图功能、地理数据库、空间查询与空间分析能力是GIS最具有独特吸引力所在。而系统是否具有良好的用户接口和各种应用分析程序的支持也是至关重要的,但是应由GIS开发人员和用户来共同完成的。
地理信息系统技术广泛应用于农业、林业、国土资源、地矿、军事、交通、测绘、水利、广播电视、通讯、电力、公安、社区管理、教育、能源等几乎所有的行业,并正在走进人们日常的工作、学习和生活中。
地理信息系统的主要任务是对与地理空间位置或区域有关的社会经济、人文景观、自然资源及环境等多种信息进行综合管理和分析,主要任务有以下三个方面
最近在做AO的一些东西,有些空间关系让我搞不太懂,查到一个东西,还是很好的
名词解释:
Boundary(边界):
只有线和面才有边界。面的边界是指组成面的框架线;线的边界是指线的二个端点(即起点和终点,不包括中间部分的节点);点没有边界。
Interior(内部):
除去边界后剩下的部分即是一个要素的内部。因此线的内部指除去端点后的部分;面的内部是指除去框架线后的部分;点的内部就是点本身。
Exterior(外部):
除去该要素后的剩余的空间范围即是该要素的外部。
空间关系具体描述(Queryable Spatial Relationships):
示意图:
空间关系:
1, esriSpatialRelTouches(邻接)
应用范围:
除点与点之间的关系外,其它的要素之间都可以具有该关系。
描述:
如果二个要素有相同的边界,且它们内部不相交的话,称这二个要素之间的关系是邻接的关系,图1-1、2-1、3-1、3-2,注意图3-3中点与线是包涵的关系。
当查询要素和被查询要素具有该关系时,即spatialRel的值是esriSpatialRelTouches,则会返回查询要素。
2, esriSpatialRelCrosses (交叉)
应用范围:
线与面,线与线等。不能用于面与面(面与面相交部分是面,不能二个要素中的最高维数低一),面与点,点与线(二个要素的维数差2)。
描述:
如果二个要素的相交部分不为空,并且相交部分形状的维数比两个要素中最高维数低1(即线面交叉是线,线线交叉是点)则称这二个要素具有交叉关系,图2-4、4-1,图2-1中中二条线的关系属于邻接关系,而不属于交叉关系,因为它们的内部相交部分为空。
当查询要素和被查询要素具有该关系时,即spatialRel的值是esriSpatialReCrosses,则会返回查询要素。
3, esriSpatialRelOverlaps(重叠关系)
应用范围:
线与线,面与面之间,其它的不具有该关系。
描述:
二个同维的要素之间的相交部分的图形具有与这二个要素相同的维数的,且不与任何一个要素完全相同,则称这二个要素重叠。图1-2、2-2均是重叠关系,但是2-3中的二条线不是重叠关系,因为相交的部分与黄色的线完全相同。
当查询要素和被查询要素具有该关系时,即spatialRel的值是esriSpatialRelOverlaps,则会返回查询要素。
4,esriSpatialRelWithin和esriSpatialRelContains(包涵)
应用范围:
所有要素类之间均具有该关系。
描述:
该关系可细分为一个要素完全位于另一个要素的内部和一个要素完全包涵另外一个要素,它们是相对的关系。如果说要素1完全位于要素2的内部,则要素2完全包涵要素1。
当查询的要素完全位于被查询的要素内部的话(即spatialRel的值是esriSpatialRelWithin),则返回被查询的要素;同时如果查询的要素完全被被查询的要素包括时(即spatialRel的值是esriSpatialRelContains)则返回被查询的要素。
5,esriSpatialRelIntersects(相交)
描述:
相交关系是一个广义的关系,包括上述4种关系。因此如果spatialRel的值是esriSpatialRelIntersects关系的话,只要查询要素和被查询要素之间满足上述四种空间关系的任一种空间关系,即可返回被查询的要素。
6,esriSpatialRelRelate
描述:
需要通过SpatialRelDescription属性对二个要素的空间关系进行定制,可以对二个要素的内部,外部,边界之间的相交的情况进行描述,例如:字符串'****T***'代表的是二个要素共享边界。
在ArcGIS Engine中实现点和面进行相交分析,应该是用IBasicGeoprocessor.Intersect方法,不知道对不对啊?
用点和面进行相交分析,主要目的是为了确定点在哪个区域内!比如可以用一个井的点图层和一个行政区划的面图层进行相交分析,得到的是一个井的点图层,而此图层的属性包含了两个图层的属性,从而通过对属性表的查询,来确定在某个区域内井的个数等等信息。
以下代码编译通过,但是在运行时,就报错,说是参数错误,各位帮忙看看,谢谢!!
1 private void M_OverLayer_Click(object sender, System.EventArgs e)
2 {
3 try
4 {
5 //分析层
6 ILayerpLayer=this.axMapControl1.get_Layer(0);
7 IFeatureLayerpInputFeatLayer=pLayer as IFeatureLayer;
8 ITable pInputTable=pLayer asITable;
9 IFeatureClasspInputFeatClass=pInputFeatLayer.FeatureClass;
10
11 //叠加表
12 pLayer=this.axMapControl1.get_Layer(1);
13 ITable pOverlayTable=pLayer asITable;
14
15 //叠加分析表
16 IFeatureClassNamepFeatClassName=new FeatureClassNameClass();
17 pFeatClassName.FeatureType=esriFeatureType.esriFTSimple;
18 pFeatClassName.ShapeFieldName="shape";
19 pFeatClassName.ShapeType=pInputFeatClass.ShapeType;
20
21 //工作空间名称
22 IWorkspaceName pNewWSName=newWorkspaceNameClass();
23 pNewWSName.WorkspaceFactoryProgID= "esriDataSourcesFile.ShapefileWorkspaceFactory";
24 pNewWSName.PathName =@"C:\temp";
25
26 //数据集名称
27 IDatasetNamepDatasetName=pFeatClassName as IDatasetName;
28 pDatasetName.Name="ss";
29 pDatasetName.WorkspaceName=pNewWSName;
30
31 //几何处理
32 IBasicGeoprocessor pBGP=newBasicGeoprocessorClass();
33 IFeatureClasspOutputFeatClass=pBGP.Intersect(pInputTable,false,pOverlayTable,false,0.01,pFeatClassName);
34
35 //输出要素层设置
36 IFeatureLayerpOutputFeatLayer=new FeatureLayerClass();
37 pOutputFeatLayer.FeatureClass=pOutputFeatClass;
38 pOutputFeatLayer.Name=pOutputFeatClass.AliasName;
39
40 this.axMapControl1.AddLayer((ILayer)pOutputFeatClass,0);
41 axMapControl1.Update();
42 }
43 catch(Exception ex)
44 {
45 MessageBox.Show(ex.Message);
46 }
47 }
1、地理信息系统(geographic information system ,即gis )——一门集计算机科学、信息学、地理学等多门科学为一体的新兴学科,它是在计算机软件和硬件支持下,运用系统工程和信息科学的理论,科学管理和综合分析具有空间内涵的地理数据,以提供对规划、管理、决策和研究所需信息的空间信息系统。gis有以下子系统:数据输入子系统,数据存储和检索子系统,数据操作和分析子系统,报告子系统.
信息系统
非空间的 空间的
管理信息系统 非地理学的 gis
cad/cam 其他gis lis
社会经济,人口普查 基于非地块,基于地块的
2、比较gis与cad、cac间的异同。
cad——计算机辅助设计,规则图形的生成、编辑与显示系统,与外部描述数据无关。
cac——计算机辅助制图,适合地图制图的专用软件,缺乏空间分析能力。
gis——地理信息系统,集规则图形与地图制图于一身,且有较强的空间分析能力。
3、图层:将空间信息按其几何特征及属性划分成的专题。
4、地理数据采集——实地调查、采样;传统的测量方法,如三角测量法、三边测量法;全球定位系统(gps);现代遥感技术;生物遥测学;数字摄影技术;人口普查。
5、信息范例——传统的制图方法,称为信息范例,即假定地图本身是一个最终产品,通过使用符号、分类限制的选择等方式交换空间信息的模式。这个范例是传统的透视图方法,由于原始而受到很多限制,地图用户不能轻易获得预分类数据。也就是说,用户只限于处理最终产品,而无法将数据重组为更有效的形式以适应环境或需求的变化。
6、分析范例(整体范例)——存储保存原始数据的属性数据,可根据用户的需求进行数据的显示、重组和分类。整体范例是一种真正的用于制图学和地理学的整体方法。
7、栅格——栅格结构是最简单最直接的空间数据结构,是指将地球表面划分为大小均匀紧密相邻的网格阵列,每个网格作为一个象元或象素由行、列定义,并包含一个代码表示该象素的属性类型或量值,或仅仅包括指向其属性记录的指针。因此,栅格结构是以规则的阵列来表示空间地物或现象分布的数据组织,组织中的每个数据表示地物或现象的非几何属性特征。特点:属性明显,定位隐含,即数据直接记录属性本身,而所在的位置则根据行列号转换为相应的坐标,即定位是根据数据在数据集中的位置得到的,在栅格结构中,点用一个栅格单元表示;线状地物用沿线走向的一组相邻栅格单元表示,每个栅格单元最多只有两个相邻单元在线上;面或区域用记有区域属性的相邻栅格单元的集合表示,每个栅格单元可有多于两个的相邻单元同属一个区域。
8、矢量——它假定地理空间是连续,通过记录坐标的方式尽可能精确地表示点、线、多边形等地理实体,坐标空间设为连续,允许任意位置、长度和面积的精确定义。对于点实体,矢量结构中只记录其在特定坐标系下的坐标和属性代码;对于线实体,用一系列坐标对的连线表示;多边形是指边界完全闭合的空间区域,用一系列坐标对的连线表示。
9、“拓扑”(topology)一词来源于希腊文,它的原意是“形状的研究”。拓扑学是几何学的一个分支,它研究在拓扑变换下能够保持不变的几何属性——拓扑属性(拓扑属性:一个点在一个弧段的端点,一个点在一个区域的边界上;非拓扑属性:两点之间的距离,弧段的长度,区域的周长、面积)。这种结构应包括:唯一标识,多边形标识,外包多边形指针,邻接多边形指针,边界链接,范围(最大和最小x、y坐标值)。地理空间研究中三个重要的拓扑概念(1)连接性:弧段在结点处的相互联接关系;(2)多边形区域定义:多个弧段首尾相连构成了多边形的内部区域;(3)邻接性:通过定义弧段的左右边及其方向性来判断弧段左右多边形的邻接性。
10、矢量的实体错误——伪节点:即需要假节点进行识别的节点,发生在线和自身相连接的地方(如岛状伪结点——显示存在一个岛状多边形,这个多边形处于另一个更大的多边形内部),或发生在两条线沿着平行路径而不是交叉路径相交的地方(节点——表示线与线间连接的特殊点)。摇摆结点:有时称为摇摆,来源于3种可能的错误类型:闭合失败的多边形;欠头线,即结点延伸程度不够,未与应当连接的目标相连;过头线,结点的线超出想与之连接的实体。碎多边形:起因于沿共同边界线进行的不良数字化过程,在边界线位置,线一定是不只一次地被数字化。高度不规则的国家边境线,例如中美洲,特别容易出现这样的数字变形。标注错误:丢失标注和重复标注。异常多边形:具有丢失节点的多边形。丢失的弧。
11、空间分析方法——1、空间信息的测量:线与多边形的测量、距离测量、形状测量;2、空间信息分类:范围分级分类、邻域功能、漫游窗口、缓冲区;3、叠加分析:多边形叠加、点与多边形、线与多边形;4、网络分析:路径分析、地址匹配、资源匹配; 5、空间统计分析:插值、趋势分析、结构分析;6、表面分析:坡度分析、坡向分析、可见度和相互可见度分析。
12、欧拉数——最通常的空间完整性,即空洞区域内空洞数量的度量,测量法称为欧拉函数,它只用一个单一的数描述这些函数,称为欧拉数。数量上,欧拉数=(空洞数)-(碎片数-1),这里空洞数是外部多边形自身包含的多边形空洞数量,碎片数是碎片区域内多边形的数量。有时欧拉数是不确定的。
13、函数距离——描述两点间距离的一种函数关系,如时间、摩擦、消耗等,将这些用于距离测量的方法集中起来,称为函数距离。
14、曼哈顿距离——两点在南北方向上的距离加上在东西方向上的距离,即d(i,j)=|xi-xj|+|yi-yj|。对于一个具有正南正北、正东正西方向规则布局的城镇街道,从一点到达另一点的距离正是在南北方向上旅行的距离加上在东西方向上旅行的距离因此曼哈顿距离又称为出租车距离,曼哈顿距离不是距离不变量,当坐标轴变动时,点间的距离就会不同。
15、邻域功能——所谓邻域是指具有统一属性的实体区域或者焦点集中在整个地区的较小部分实体空间。邻域功能就是在特定的实体空间中发现其属性的一致性。它包括直接邻域和扩展邻域。
16、缓冲区分析——是指根据数据库的点、线、面实体基础,自动建立其周围一定宽度范围内的缓冲区多边形实体,从而实现空间数据在水平方向得以扩展的空间分析方法。缓冲区在某种程度上受控于目前存在的摩擦表面、地形、障碍物等,也就是说,尽管缓冲区建立在位置的基础上,但是还有其他实质性的成分。确定缓冲区距离的四种基本方法:随机缓冲区、成因缓冲区、可测量缓冲区、合法授权缓冲区。
17、统计表面——表面是含有z值的形貌,z值又称为高度值,它的位置被一系列x和y坐标对定义且在区域范围内分布。z值也常被认为是高程值,但是不必局限于这一种度量。实际上,在可定义的区域内出现的任意可测量的数值(例如,序数、间隔和比率数据)都可以认为组成了表面。一般使用的术语是统计表面,因为在考虑的范围内z值构成了许多要素的统计学的表述(robinson et al., 1995)。
18、dem——数字高程模型(digitalelevation model)。地形模型不仅包含高程属性,还包含其它的地表形态属性,如坡度、坡向等。dem通常用地表规则网格单元构成的高程矩阵表示,广义的dem还包括等高线、三角网等所有表达地面高程的数字表示。在地理信息系统中,dem是建立数字地形模型(digitalterrain model)的基础数据,其它的地形要素可由dem直接或间接导出,称为“派生数据”,如坡度、坡向。
19、空间插值——空间插值常用于将离散点的测量数据转换为连续的数据曲面,以便与其它空间现象的分布模式进行比较,它包括了空间内插和外推两种算法。空间内插算法:通过已知点的数据推求同一区域未知点数据。空间外推算法:通过已知区域的数据,推求其它区域数据。20、泰森多边形——通过数学方法定义、平分点间的空间并以直线相连结,在点状物体间生成多边形的方法。
21、线密度——用所有区域内的线的总长度除以区域的面积。
22、连通性——连通性是衡量网络复杂性的量度,常用γ指数和α指数计算它。其中,γ指数等于给定空间网络体节点连线数与可能存在的所有连线数之比;α指数用于衡量环路,节点被交替路径连接的程度称为α指数,等于当前存在的环路数与可能存在的最大环路数之比。
23、图形叠加——将一个被选主题的图形所表示的专题信息放在另一个被选主题的图形所表示的专题信息之上。
24、栅格自动叠加——基于网格单元的多边形叠加是一个简单的过程,因为区域是由网格单元组成的不规则的块,它共享相同的一套数值和相关的标注。毫无疑问,网格单元为基础的多边形叠加缺乏空间准确性,因为网格单元很大,但是类似于简单的点与多边形和线与多边形叠加的相同部分,由于它的简单性,因此可以获得较高的灵活程度和处理速度。
25、拓扑矢量叠加——如何决定实体间功能上的关系,如定义由特殊线相连的左右多边形,定义线段间的关系去检查交通流量,或依据个别实体或相关属性搜索已选择实体。它也为叠加多个多边形图层建立了一种方法,从而确保连结着每个实体的属性能够被考虑,并且因此使多个属性相结合的合成多边形能够被支持。这种拓扑结果称作最小公共地理单元(lcgu)。
26、矢量多边形叠加——点与多边形和线与多边形叠加使用的主要问题是,线并不总是出现在整个区域内。解决该问题的最强有力的办法是让软件测定每组线的交叉点,这就是所谓的结点。进行矢量多边形的叠加,其任务是基本相同的,除了必须计算重叠交叉点外,还要定义与之相联系的多边形线的属性。
27、布尔叠加——一种以布尔代数为基础的叠加操作。
28、制图建模——用以指明应用命令组合来回答有关空间现象问题的处理。制图模型是针对原始数据也包括导出数据和中间地图数据进行一系列交互有序的地图操作来模拟空间决策的处理。
29、地理模型的类型——类似统计同类的描述性模型和与推理统计技术相关的规则性模型。
30、常见模型——1、注重样式与处理的问题长时间以来用于解释类似农业活动与运输成本间的关系——独立状态模型。2、最初为预测工业位置点的空间分布的样式而设计的weber模型,进行改进后可使参与者寻找最佳商业和服务位置——位置-分配模型。3、建立在吸引力与到潜在市场的距离呈反比这一基础上的经济地理模型——重力模型。4、通过空间验证思想如今广泛用于生态群落,通过地理空间跟踪动植物运动——改进扩散模型。
31、专题地图——以表现某单一属性的位置或若干选定属性之间关系为主要目的的地图。专题图形设计的一般程序包括合适的符号和图形对象的选择、生成和放置,以明确突出研究主题的重要属性和空间关系,同时还要考虑参考系统。gis专题地图输出的规则:不但要有精美的图形,最重要的是去读图、分析地图和理解地图。
32、元数据——关于数据的数据,对数据库内容的全面描述,其目的是促进数据集的高效利用和充分共享。使用元数据的理由:性能上,完整性、可扩展性、特殊性、安全性;功能上,差错功能、浏览功能、程序生成。
33、聚合——将单个数据元素进行分类的大量数字处理过程。
34、克立金法——依靠地球自然表面随距离的变化概率而确定高程的一种精确内插方法。
35、四叉树——一种压缩数据结构,它把地理空间定量划分为可变大小的网格,每个网格具有相同性质的属性。
36、比较工具型地理信息系统和应用型地理信息系统的异同。
工具型地理信息系统:是一种通用型gis,具有一般的功能和特点,向用户提供一个统一的操作平台。一般没有地理空间实体,而是由用户自己定义。具有很好的二次开发功能。如:arcinfo、genamap、mapinfo、mapgis、geostar。
应用型地理信息系统:在较成熟的工具型gis软件基础上,根据用户的需求和应用目的而设计的用于解决一类或多类实际问题的地理信息系统,它具有地理空间实体和解决特殊地理空间分布的模型。如lis、cgis、ugis。
37、详细描述应用型地理信息系统的开发过程
1、系统总体设计:需求和可行性分析、数据模型设计、数据库设计、方法设计
2、系统软件设计:开发语言、用户界面、流程、交互
3、程序代码编写:投影、数据库、输入、编辑
4、系统的调试与运行:α调试、β调试
5、系统的评价与维护:功能评价、费用评价、效益评价
38、空间信息系统:以多媒体技术为依托,以空间数据为基础,以虚拟现实为手段的集空间数据的输入、编辑、存储、分析和显示于一体的巨系统,体由若干个子系统组成。
39、地理数据测量标准——命名(对数据命名,允许我们对把对象叫什么做出声明,但不允许对两个命名的对象进行直接比较)、序数(提供对空间对象进行逻辑对比的结果,但这种对比仅限于所谈论问题的范围内)、间隔(可以对待测项逐个赋值,能够更为精确地估计对比物的不同点)、比率(用途最广的测量数据标准,它是允许直接比较空间变量的惟一标准)。
40、根据样本进行推理的取样原则——未取样位置的数据可以从已取样位置的数据中推测出来;区域边界内的数据可以合并计算;一组空间单元中的数据能够转换成具有不同空间配置的另外一组空间单元数据。常用的方法:内插法:当有数值边界或知道缺失部分两端数值;外推法:当缺失的数据一侧有数值,而另一侧每一数值。
AE开发中矢量图层叠加求交分析:
AE开发中,矢量图层叠加分析需要用到的主要类为BasicGeoprocessor,其主要接口为IBasicGeoprocessor。IBasicGeoprocessor接口提供了基本的空间数据处理的方法和属性,其中包括叠加求交(Interset)和叠加求和(Union)。
下面提供叠加求交的开发实例:
C#+AE9.1叠加求交示例代码:
1 private void M_OverLayer_Click(object sender, System.EventArgs e)
2 {
3 try
4 {
5 //分析层
6 ILayerpLayer=this.axMapControl1.get_Layer(0);
7 IFeatureLayer pInputFeatLayer=pLayeras IFeatureLayer;
8 ITable pInputTable=pLayer asITable;
9 IFeatureClasspInputFeatClass=pInputFeatLayer.FeatureClass;
10
11 //叠加表
12 pLayer=this.axMapControl1.get_Layer(1);
13 ITable pOverlayTable=pLayer asITable;
14
15 //叠加分析表
16 IFeatureClassNamepFeatClassName=new FeatureClassNameClass();
17 pFeatClassName.FeatureType=esriFeatureType.esriFTSimple;
18 pFeatClassName.ShapeFieldName="shape";
19 pFeatClassName.ShapeType=pInputFeatClass.ShapeType;
20
21 //工作空间名称
22 IWorkspaceName pNewWSName=newWorkspaceNameClass();
23 pNewWSName.WorkspaceFactoryProgID= "esriDataSourcesFile.ShapefileWorkspaceFactory";
24 pNewWSName.PathName =@"C:\temp";
25
26 //数据集名称
27 IDatasetNamepDatasetName=pFeatClassName as IDatasetName;
28 pDatasetName.Name="ss";
29 pDatasetName.WorkspaceName=pNewWSName;
30
31 //几何处理
32 IBasicGeoprocessor pBGP=newBasicGeoprocessorClass();
33 IFeatureClasspOutputFeatClass=pBGP.Intersect(pInputTable,false,pOverlayTable,false,0.01,pFeatClassName);
34
35 //输出要素层设置
36 IFeatureLayerpOutputFeatLayer=new FeatureLayerClass();
37 pOutputFeatLayer.FeatureClass=pOutputFeatClass;
38 pOutputFeatLayer.Name=pOutputFeatClass.AliasName;
39
40 this.axMapControl1.AddLayer((ILayer)pOutputFeatClass,0);
41 axMapControl1.Update();
42 }
43 catch(Exception ex)
44 {
45 MessageBox.Show(ex.Message);
46 }
47 }
最近在研究ae中实现overlay的方法,终于发现了2个方法。(针对shapefile)
方法一:利用ITopology接口:
void COverlayDlg::Overlay(ILayerPtrinputLayer, ILayerPtr OverlayLayer,IFeatureClassPtr ipNewClass)
{
intmode=m_modeCombo.GetCurSel();IFeatureLayerPtr ipPutlayer(inputLayer);
IFeatureClassPtr ipPutClass;
ipPutlayer->get_FeatureClass(&ipPutClass);
IFeatureClassPtr ipOutClass;
IFeatureLayerPtr ipOverlayer(OverlayLayer);
ipOverlayer->get_FeatureClass(&ipOutClass);
IQueryFilterPtr ipQF(CLSID_QueryFilter);
long number1,number2;
ipPutClass->FeatureCount(ipQF,&number1);
ipPutClass->FeatureCount(ipQF,&number2);
IActiveViewPtripView=p_View->m_ctrlMap.GetActiveView();ITopologicalOperatorPtr ipTo;
IFeaturePtr ipFeature1,ipFeature2;
IGeometryPtr ipGeo1,ipGeo2,ipNew;
for(long i=0;i<number1;i++)
for(long j=0;j<number2;j++)
{
ipPutClass->GetFeature(i,&ipFeature1);
ipOutClass->GetFeature(j,&ipFeature2);
ipFeature1->get_Shape(&ipGeo1);
ipFeature2->get_Shape(&ipGeo2);
ipTo=ipGeo1;
switch(mode)
{
case 0:
ipTo->Intersect(ipGeo2,esriGeometry2Dimension,&ipNew);
break;
case 1:
ipTo->Union(ipGeo2,&ipNew);
break;
case 2:
ipTo->Difference(ipGeo2,&ipNew);
}
IFeaturePtr ipFeature;
ipNewClass->CreateFeature(&ipFeature);
ipFeature->putref_Shape(ipNew);
ipFeature->Store();
}ipView->Refresh();
}
这种方法是一个一个feature的创建,存入featureclass接口中。
方法二:利用IBasicGeoprocess接口
//把第一个图层和第0个图层叠置
IFeatureLayerPtr ipFeaLay;
IFeatureClassPtr ipFeaCls;
HRESULT hr;
ILayerPtr ipLay;
IMapPtr ipMap(m_ctrlMap.GetMap());
hr=ipMap->get_Layer(0,&ipLay);
ipFeaLay=ipLay;
if(ipFeaLay)
{
hr=ipFeaLay->get_FeatureClass(&ipFeaCls);
if (FAILED(hr)) return;
}
ITablePtr ipInPutTable(ipLay);hr=ipMap->get_Layer(1,&ipLay);
ipFeaLay=ipLay;
if(ipFeaLay!=0)
hr=ipFeaLay->get_FeatureClass(&ipFeaCls);
ITablePtr ipOverlayTable(ipLay);
hr=ipDatasetName->putref_WorkspaceName(ipWSName);
if(FAILED(hr)) return;
IBasicGeoprocessorPtr ipBGP(CLSID_BasicGeoprocessor);
IFeatureClassPtr ipOutputFeaCls;hr=ipBGP->Intersect(ipInPutTable,VARIANT_FALSE,ipOverlayTable,VARIANT_FALSE,double(0),ipFeaClsName,&ipOutputFeaCls);
IFeatureLayerPtripOutputFeaLay(CLSID_FeatureLayer);
ipOutputFeaLay->putref_FeatureClass(ipOutputFeaCls);
BSTR OutFeaClsAliName;
hr=ipOutputFeaCls->get_AliasName(&OutFeaClsAliName);
if(FAILED(hr)) return;
hr=ipOutputFeaLay->put_Name(OutFeaClsAliName);
if(FAILED(hr)) return;
hr=ipMap->AddLayer(ipOutputFeaLay);
if(FAILED(hr)) return;IActiveViewPtripAV(ipMap);
ipAV->Refresh();
地图叠加:将两幅数字化地图的几何形状和属性结合在一起,生成输出地图的一种属性数据。
点与多边形叠加:一种GIS操作,点状地图上的每个点被赋予点所落入的多边形内的属性数据。
线与多边形叠加:一种GIS操作,现状地图被叠加地图上的多边形边界所分割,输出地图上每个弧段结合了来自线状地图和所落入多边形的属性。
多边形与多边形叠加:一种GIS操作,其输出地图结合了来自输入地图和叠加地图的多边形边界,生成一套新的多边形,每个新的多边形携带了两幅地图的属性。
缓冲:一种GIS操作,将落在所选地图要素指定距离之内的区域与之外的区域分开。
相交(Intersect):一种地图叠加方法,仅保留那些落在输入地图和叠加地图共同范围的要素。
联合(Union):保留输入地图和叠加地图全部要素的一种多边形与多边形叠加方法。
层叠置(Identity):一种地图叠加方法,仅保留那些落在由输入地图定义范围内的要素。
模糊容差:用于GIS软件的距离容差,落在这一指定距离内的点和线被强制捕捉到一起。
破碎多边形:在地图叠加中沿着两个输入地图的共同边界出现的极小多边形。破碎多边形往往来自数字化误差。
误差传递:由于输入地图的误差造成地图叠加输出中误差的产生。
最小制图单元:由政府机构或组织所指定的最小面积单元。
www.TeleCarto.com 2001-6-29 远图开发室
地理信息系统(GIS)具有很强的空间信息分析功能,这是区别于计算机地图制图系统的显著特征之一。利用空间信息分析技术,通过对原始数据模型的观察和实验,用户可以获得新的经验和知识,并以此作为空间行为的决策依据。
空间信息分析的内涵极为丰富。作为GIS的核心部分之一,空间信息分析在地理数据的应用中发挥着举足轻重的作用。
叠置分析(OverlayAnalysis)
覆盖叠置分析是将两层或多层地图要素进行叠加产生一个新要素层的操作,其结果将原来要素分割生成新的要素,新要素综合了原来两层或多层要素所具有的属性。也就是说,覆盖叠置分析不仅生成了新的空间关系,还将输入数据层的属性联系起来产生了新的属性关系。覆盖叠置分析是对新要素的属性按一定的数学模型进行计算分析,进而产生用户需要的结果或回答用户提出的问题。
1)多边形叠置
这个过程是将两层中的多边形要素叠加,产生输出层中的新多边形要素,同时它们的属性也将联系起来,以满足建立分析模型的需要。一般GIS软件都提供了三种多边形叠置:
(1)多边形之和(UNION):输出保留了两个输入的所有多边形。
(2)多边形之积(INTERSECT):输出保留了两个输入的共同覆盖区域。
(3)多边形叠合(IDENTITY):以一个输入的边界为准,而将另一个多边形与之相匹配,输出内容是第一个多边形区域内二个输入层所有多边形。
多边形叠置是个非常有用的分析功能,例如,人口普查区和校区图叠加,结果表示了每一学校及其对应的普查区,由此就可以查到作为校区新属性的重叠普查区的人口数。
2)点与多边形叠加
点与多边形叠加,实质是计算包含关系。叠加的结果是为每点产生一个新的属性。例如,井位与规划区叠加,可找到包含每个井的区域。
3)线与多边形叠加
将多边形要素层叠加到一个弧段层上,以确定每条弧段(全部或部分)落在哪个多边形内。
网络分析(NetworkAnalysis)
对地理网络(如交通网络)、城市基础设施网络(如各种网线、电力线、电话线、供排水管线等)进行地理分析和模型化,是地理信息系统中网络分析功能的主要目的。网络分析是运筹学模型中的一个基本模型,它的根本目的是研究、筹划一项网络工程如何按排,并使其运行效果最好,如一定资源的最佳分配,从一地到另一地的运输费用最低等。其基本思想则在于人类活动总是趋向于按一定目标选择达到最佳效果的空间位置。这类问题在生产、社会、经济活动中不胜枚举,因此研究此类问题具有重大意义。
网络中的基本组成部分和属性如下:
(1)链(Links),网络中流动的管线,如街道,河流,水管等,其状态属性包括阻力(Impedence)和需求(Demand)。
(2)障碍(Barriers),禁止网络中链上流动的点。
(3)拐角点(Turns),出现在网络链中所有的分割结点上,状态属性有阻力,如拐弯的时间和限制(如不允许左拐)。
(4)中心(Centers),是接受或分配资源的位置,如水库、商业中心、电站等,其状态属性包括资源容量,如总的资源量;阻力限额,如中心与链之间的最大距离或时间限制。
(5)站点(Stops),在路径选择中资源增减的站点,如库房、汽车站等,其状态属性有要被运输的资源需求,如产品数。
网络中的状态属性有阻力和需求两项,实际的状态属性可通过空间属性和状态属性的转换,根据实际情况赋到网络属性表中。
1)路径分析
(1)静态求最佳路径:由用户确定权值关系后,即给定每条弧段的属性,当需求最佳路径时,读出路径的相关属性,求最佳路径。
(2)动态分段技术:给定一条路径由多段联系组成,要求标注出这条路上的公里点或要求定位某一公路上的某一点,标注出某条路上从某一公里数到另一公里数的路段。
(3)N条最佳路径分析:确定起点、终点,求代价较小的N条路径,因为在实践中往往仅求出最佳路径并不能满足要求,可能因为某种因素不走最佳路径,而走近似最佳路径。
(4)最短路径:确定起点、终点和所要经过的中间点、中间连线,求最短路径。
(5)动态最佳路径分析:实际网络分析中权值是随着权值关系式变化的,而且可能会临时出现一些障碍点,所以往往需要动态地计算最佳路径。
2)地址匹配
地址匹配实质是对地理位置的查询,它涉及到地址的编码(Geocode)。地址匹配与其它网络分析功能结合起来,可以满足实际工作中非常复杂的分析要求。所需输入的数据,包括地址表和含地址范围的街道网络及待查询地址的属性值。
3)资源分配
资源分配网络模型由中心点(分配中心)及其状态属性和网络组成。分配有两种方式,一种是由分配中心向四周输出,另一种是由四周向中心集中。这种分配功能可以解决资源的有效流动和合理分配。其在地理网络中的应用与区位论中的中心地理论类似。在资源分配模型中,研究区可以是机能区,根据网络流的阻力等来研究中心的吸引区,为网络中的每一连接寻找最近的中心,以实现最佳的服务。还可以用来指定可能的区域。
资源分配模型可用来计算中心地的等时区,等交通距离区,等费用距离区等。可用来进行城镇中心,商业中心或港口等地的吸引范围分析,以用来寻找区域中最近的商业中心,进行各种区划和港口腹地的模拟等。
缓冲区分析(BufferAnalysis)
缓冲区分析是针对点、线、面实体,自动建立其周围一定宽度范围以内的缓冲区多边形。缓冲区的产生有三种情况:一是基于点要素的缓冲区,通常以点为圆心、以一定距离为半径的圆;二是基于线要素的缓冲区,通常是以线为中心轴线,距中心轴线一定距离的平行条带多边形;三是基于面要素多边形边界的缓冲区,向外或向内扩展一定距离以生成新的多边形。
缓冲区分析是地理信息系统重要的空间分析功能之一,它在交通、林业、资源管理、城市规划中有着广泛的应用。例如:湖泊和河流周围的保护区的定界,汽车服务区的选择,民宅区远离街道网络的缓冲区的建立等。
空间统计分析(SpacialAnalysis)
1)常规统计分析
常规统计分析主要完成对数据集合的均值、总和、方差、频数、峰度系数等参数的统计分析。
2)空间自相关分析
空间自相关分析是认识空间分布特征、选择适宜的空间尺度来完成空间分析的最常用的方法。目前,普遍使用空间自相关系数——
MoranI指数,其计算公式如下:
其中:N表示空间实体数目;xi表示空间实体的属性值;x是xi的平均值;Wij=1表示空间实体i与j相邻,Wij=0表示空间实体i与j不相邻I的值介于1与I之间,I=1表示空间自正相关,空间实体呈聚合分布;I=1表示空间自负相关,空间实体呈离散分布;I=0则表示空间实体是随机分布的。Wij表示实体i与j的空间关系,它通过拓扑关系获得。
3)回归分析
回归分析用于分析两组或多组变量之间的相关关系,常见回归分析方程有:线性回归、指数回归、对数回归、多元回归等。
4)趋势分析
通过数学模型模拟地理特征的空间分布与时间过程,把地理要素时空分布的实测数据点之间的不足部分内插或预测出来。
5)专家打分模型
专家打分模型将相关的影响因素按其相对重要性排队,给出各因素所占的权重值;对每一要素内部进行进一步分析,按其内部的分类进行排队,按各类对结果的影响给分,从而得到该要素内各类别对结果的影响量,最后系统进行复合,得出排序结果,以表示对结果影响的优劣程度,作为决策的依据。
专家打分模型可分二步实现。第一步——打分:用户首先在每个feature的属性表里增加一个数据项,填入专家赋给的相应的分值;第二步——复合:调用加权符合程序,根据用户对各个feature给定的权重值进行叠加,得到最后的结果。
本小节以Polyline(Polygon类似)为例, 讲解如何判断图形间的逻辑关系,主要用到的接口是IRelationalOperator。
在本例中,使用RelationalOperator 对两个图形进行比较,返回一个布尔值来指出这两个图形间是否存在特定的关系。一些关系的判断是要求两个图形要有相同的维数的(如必须Polyline之间或Polygon之间),而另外一些对图形维数就没有太多限制。大多数已定义的关系操作符是互斥的。RelationalOperator的具体方法有:
Contains:判断一个图形是否包含另外一个图形。
Within:判断一个图形是否被另外一个图形所包含。
Crosses:判断两个图形是否在维数较少的那个图形的内部相交。
Disjoint:判断两个图形间是否没有相同点。
Equals:判断两个图形是否是同一个类型并且在平面上的点是否是相同的位置。如果返回值为真,则它们应该包含(Contains)另外一个图形同时也被另外一个图形所包含(Within)。
Overlaps:判断两个图形的交集是否和其中的一个图形拥有相同的维数,并且他们交集不能和其中任何一个图形相等。该方法只使用与两个Polyline之间或者两个Polygon之间。
Touch:判断两个图形的边界是否相交,如果两个图形的交集不为空,但两个图形内部的交集为空,则返回值为真。
下图为几个图形的边界(Boundary)和内部(Interior)概念的图解:
下面针对较易混淆的两个概念,Crosses和Touch进行举例说明(Polyline/Polyline):
Crossess Touch Crossess Touch |
最近在研究ae中实现overlay的方法,终于发现了2个方法。(针对shapefile)
方法一:利用ITopology接口:
void COverlayDlg::Overlay(ILayerPtrinputLayer, ILayerPtr OverlayLayer,IFeatureClassPtr ipNewClass)
{
intmode=m_modeCombo.GetCurSel();
IFeatureLayerPtr ipPutlayer(inputLayer);
IFeatureClassPtr ipPutClass;
ipPutlayer->get_FeatureClass(&ipPutClass);
IFeatureClassPtr ipOutClass;
IFeatureLayerPtr ipOverlayer(OverlayLayer);
ipOverlayer->get_FeatureClass(&ipOutClass);
IQueryFilterPtr ipQF(CLSID_QueryFilter);
longnumber1,number2;
ipPutClass->FeatureCount(ipQF,&number1);
ipPutClass->FeatureCount(ipQF,&number2);
IActiveViewPtripView=p_View->m_ctrlMap.GetActiveView();
ITopologicalOperatorPtr ipTo;
IFeaturePtr ipFeature1,ipFeature2;
IGeometryPtr ipGeo1,ipGeo2,ipNew;
for(longi=0;i<number1;i++)
for(long j=0;j<number2;j++)
{
ipPutClass->GetFeature(i,&ipFeature1);
ipOutClass->GetFeature(j,&ipFeature2);
ipFeature1->get_Shape(&ipGeo1);
ipFeature2->get_Shape(&ipGeo2);
ipTo=ipGeo1;
switch(mode)
{
case0:
ipTo->Intersect(ipGeo2,esriGeometry2Dimension,&ipNew);
break;
case 1:
ipTo->Union(ipGeo2,&ipNew);
break;
case 2:
ipTo->Difference(ipGeo2,&ipNew);
}
IFeaturePtr ipFeature;
ipNewClass->CreateFeature(&ipFeature);
ipFeature->putref_Shape(ipNew);
ipFeature->Store();
}
ipView->Refresh();
}
这种方法是一个一个feature的创建,存入featureclass接口中。
方法二:利用IBasicGeoprocess接口
//把第一个图层和第0个图层叠置
IFeatureLayerPtr ipFeaLay;
IFeatureClassPtr ipFeaCls;
HRESULT hr;
ILayerPtr ipLay;
IMapPtripMap(m_ctrlMap.GetMap());
hr=ipMap->get_Layer(0,&ipLay);
ipFeaLay=ipLay;
if(ipFeaLay)
{
hr=ipFeaLay->get_FeatureClass(&ipFeaCls);
if (FAILED(hr)) return;
}
ITablePtr ipInPutTable(ipLay);
hr=ipMap->get_Layer(1,&ipLay);
ipFeaLay=ipLay;
if(ipFeaLay!=0)
hr=ipFeaLay->get_FeatureClass(&ipFeaCls);
ITablePtr ipOverlayTable(ipLay);
hr=ipDatasetName->putref_WorkspaceName(ipWSName);
if(FAILED(hr)) return;
IBasicGeoprocessorPtr ipBGP(CLSID_BasicGeoprocessor);
IFeatureClassPtripOutputFeaCls;
hr=ipBGP->Intersect(ipInPutTable,VARIANT_FALSE,ipOverlayTable,VARIANT_FALSE,double(0),ipFeaClsName,&ipOutputFeaCls);
IFeatureLayerPtripOutputFeaLay(CLSID_FeatureLayer);
ipOutputFeaLay->putref_FeatureClass(ipOutputFeaCls);
BSTROutFeaClsAliName;
hr=ipOutputFeaCls->get_AliasName(&OutFeaClsAliName);
if(FAILED(hr)) return;
hr=ipOutputFeaLay->put_Name(OutFeaClsAliName);
if(FAILED(hr)) return;
hr=ipMap->AddLayer(ipOutputFeaLay);
if(FAILED(hr)) return;
IActiveViewPtr ipAV(ipMap);
ipAV->Refresh();
捕捉功能主要使用ArcEngine中的两个接口
1. IHitTest用于作点击测试
2. IFeatureCache 用于建立做缓存
由于数据库中有多个FeatureClass,而每个FeatureClass又可以做多种点击测试
所以这里有会有好几种捕捉方案。
我们称呼每一个可以执行捕捉的对象叫捕捉代理,所有的代理在一个捕捉环境中
方案1:每个代理负责测试一种FeatureClass的一种点击方式
方案2:每个代理负责测试一种FeatureClass的所有点击方式
方案3:一代理负责测试所有的FeatureClass的一种点击方式
方案4:一个代理负责测试所有FeatureClass的所有点击方式
在实际使用过程中 我们使用的是第一种方案。但是我个人认为第二种方案比较好。当然这只是个人推测
没有测试数据证明。
下面给出第一种方案的代码:
/// <summary>
///IFeatureSnapAgent 的摘要说明。
///</summary>
public interface IFeatureSnapAgent:ISnapAgent,ISnapAgentFeedback
{
IFeatureCache FeatureCache
{
get;
}
IFeatureClass FeatureClass
{
get;
set;
}
esriGeometryHitPartType HitPartType
{
get;
set;
}
///<summary>
///为捕捉连接事件,当捕捉发生的时候,就会触发事件。
///</summary>
///<param name="handler"></param>
void AddSnapedEventHandler(GeometrySnapedEventHandler handler);
///<summary>
///不再监听捕捉事件
///</summary>
///<param name="handler"></param>
void RemoveSnapedEventHandler(GeometrySnapedEventHandler handler);
}
///<summary>
/// 默认的要素捕捉代理
///</summary>
public class DefaultFeatureSnapAgent:IFeatureSnapAgent,IEditEvents,ESRI.ArcGIS .esriSystem .IPersistVariant
{
#region 构造函数
///<summary>
///为代理指定别名。注意该代理目前还没有关联到任何目标FeatureClass
///要使得该代理起作用,必须要为他设置FeatureClass.
///</summary>
///<param name="name">名称(请确保唯一)</param>
public DefaultFeatureSnapAgent(string name):this(name,null)
{
}
///<summary>
///将使用该FeatureClass的别名做代理的名称
///</summary>
///<param name="feaClass"></param>
public DefaultFeatureSnapAgent(IFeatureClassfeaClass):this(feaClass.AliasName,feaClass)
{
}
///<summary>
///完全初始化捕捉代理
///</summary>
///<param name="name">名称(请确保唯一)</param>
///<param name="feaClass">目标FeatureClass</param>
public DefaultFeatureSnapAgent(string name,IFeatureClass feaClass)
{
m_snapAgentName=name;
m_bCacheHasCreated=false;
m_hitPartType=esriGeometryHitPartType.esriGeometryPartNone;
this.m_isSnapWorking=true;
this.m_featureClass=feaClass;
this.m_snapFeedbackText="";
}
#endregion
#region IFeatureSnapAgent 成员
private event GeometrySnapedEventHandler m_snapSubsciber;
///<summary>
///FeatureClass缓冲区。
///</summary>
private IFeatureCache m_featureCache;
///<summary>
///该代理将捕捉在该FeatureClass上的Feature.和Geometry
///</summary>
private IFeatureClass m_featureClass;
///<summary>
///点击测试的有效类型。
///</summary>
protected esriGeometryHitPartType m_hitPartType;
///<summary>
///缓冲区对象是否已经被创建了。跟是否建立了缓冲没有关系。
///</summary>
private bool m_bCacheHasCreated;
///<summary>
///缓冲区对象
///</summary>
public IFeatureCache FeatureCache
{
get
{
return m_featureCache;
}
}
///<summary>
///目标FeatureClass。SnapAgent将针对该FeatureClass做捕捉
///</summary>
public IFeatureClass FeatureClass
{
get
{
return m_featureClass;
}
set
{
m_featureClass=value;
}
}
///<summary>
///点击测试类型。哪些点击类型会被测试
///</summary>
public ESRI.ArcGIS.Geometry.esriGeometryHitPartType HitPartType
{
get
{
// TODO: 添加 DefaultFeatureSnapAgent.HitPartTypegetter 实现
return m_hitPartType;
}
set
{
m_hitPartType=value;
}
}
///<summary>
/// 创建缓冲区对象。
///</summary>
private void CreateFeatureCache()
{
m_featureCache=new ESRI.ArcGIS.Carto.FeatureCacheClass();
m_bCacheHasCreated=true;
}
///<summary>
/// 填充缓冲区。如果还没有创建缓冲区对象,就先创建缓冲区对象。
/// 如果已经拥有缓冲区,而且当前点依然在该缓冲区内部,那么不会填充生成新的缓冲。
/// 由于缓冲是在捕捉方法内部被使用的。所以可以保证m_featureClass必然不会为空引用。
///</summary>
///<param name="point">当前点</param>
///<param name="size">缓冲区大小</param>
private void FillCache(IPoint point,double size)
{
if(!m_bCacheHasCreated)
{
CreateFeatureCache();
}
if(!m_featureCache.Contains (point))
{
m_featureCache.Initialize(point,size);
m_featureCache.AddFeatures(this.m_featureClass);
}
}
///<summary>
///添加事件侦听者。捕捉发生后,事件将会被发送到该侦听者。
///</summary>
///<param name="handler"></param>
public void AddSnapedEventHandler(GeometrySnapedEventHandler handler)
{
m_snapSubsciber+=handler;
}
///<summary>
///移去事件侦听者。
///</summary>
///<param name="handler"></param>
public void RemoveSnapedEventHandler(GeometrySnapedEventHandler handler)
{
m_snapSubsciber-=handler;
}
#endregion
#region ISnapAgent 成员
private string m_snapAgentName;
///<summary>
///SnapAgent是否在工作。代表用户是打开还是关闭了SnapAgent
///初始化的时候默认是打开的。
///</summary>
private bool m_isSnapWorking;
public string Name
{
get
{
return m_snapAgentName;
}
}
public bool IsWorking()
{
return this.m_isSnapWorking ;
}
///<summary>
/// 捕捉。
///</summary>
///<param name="metry"></param>
///<param name="snapPoint"></param>
///<param name="tolerance"></param>
///<returns></returns>
public virtual bool Snap(IGeometry metry, IPoint snapPoint, doubletolerance)
{
/*
*捕捉的过程:
*首先使用当前位置、目标图层、和误差的10倍构造一个缓冲区。
*对缓冲区中的每个Feature,找到他包含的每一个Geometry。
*对Geometry做点击测试。
*/
if(!this.m_isSnapWorking)
{
//捕捉代理已经被用户关闭了。不会有任何捕捉动作发生
return false;
}
if(m_featureClass==null)
{
//没有目标图层。不能做捕捉动作。此时应该报错
//但是目前只是返回false。
return false;
}
FillCache(snapPoint,tolerance*10);
//当前被测试的Feature
IFeature feature=null;
//当前被测试的几何图形
IGeometry curMetry=null;
//当前被测试的Feature的索引和缓冲区中拥有的feature的个数。
int featureIndex,featureCount;
featureCount=m_featureCache.Count;
for(featureIndex=0;featureIndex<featureCount;featureIndex++)
{
feature=m_featureCache.get_Feature(featureIndex);
if(feature!=null)
{
curMetry=feature.Shape;
IPoint hitPoint=new ESRI.ArcGIS .Geometry.PointClass ();
double hitDist=0;
int hitPartIndex=-1;
bool bRightSide=false;
int hitSegmentIndex=-1;
IHitTest hitTest=(IHitTest)curMetry;
if(hitTest.HitTest(snapPoint,tolerance,this.m_hitPartType,hitPoint,ref hitDist
,ref hitPartIndex,ref hitSegmentIndex,ref bRightSide))
{
GeometrySnapEventArgs args=new GeometrySnapEventArgs (hitPoint,curMetry,
feature,this.m_featureClass,hitPartIndex,hitSegmentIndex,tolerance,
hitDist,this.m_hitPartType,bRightSide);
SetFeedback("FeatureSnapAgent"+this.Name+"捕捉到了!");
LaunchSnapEvent(args);
snapPoint.X=hitPoint.X;
snapPoint.Y=hitPoint.Y;
return true;
}
}
}
return false;
}
///<summary>
///打开捕捉代理
///</summary>
public void TurnOn()
{
this.m_isSnapWorking=true;
}
///<summary>
///关闭捕捉代理
///</summary>
public void TurnOff()
{
this.m_isSnapWorking =false;
}
private void LaunchSnapEvent(SnapEventArgs args)
{
if(this.m_snapSubsciber!=null&&args!=null)
{
this.m_snapSubsciber(this,args);
}
}
#endregion
#region Object 成员
///<summary>
///名字是一个agent的唯一标志。
///</summary>
///<param name="obj"></param>
///<returns></returns>
public override bool Equals(object obj)
{
if(! (obj is DefaultFeatureSnapAgent))
{
return false;
}
DefaultFeatureSnapAgent agent=(DefaultFeatureSnapAgent)obj;
return this.m_snapAgentName.Equals(agent.m_snapAgentName);
}
public override int GetHashCode()
{
return this.m_snapAgentName.GetHashCode();
}
#endregion
#region IEditEvents 成员
public void AfterDrawSketch(IObject obj)
{
//TODO: 添加 DefaultFeatureSnapAgent.AfterDrawSketch 实现
}
public void OnChangeFeature(IObject obj)
{
//TODO: 添加 DefaultFeatureSnapAgent.OnChangeFeature 实现
}
public void OnConflictsDetected()
{
//TODO: 添加 DefaultFeatureSnapAgent.OnConflictsDetected 实现
}
public void OnCreateFeature(IObject obj)
{
//TODO: 添加 DefaultFeatureSnapAgent.OnCreateFeature 实现
}
public void OnCurrentLayerChanged()
{
//TODO: 添加 DefaultFeatureSnapAgent.OnCurrentLayerChanged 实现
}
publicvoid OnCurrentTaskChanged()
{
//TODO: 添加 DefaultFeatureSnapAgent.OnCurrentTaskChanged 实现
}
public void OnDeleteFeature(IObject obj)
{
//TODO: 添加 DefaultFeatureSnapAgent.OnDeleteFeature 实现
}
public void OnRedo()
{
//TODO: 添加 DefaultFeatureSnapAgent.OnRedo 实现
}
public void OnSelectionChanged()
{
//TODO: 添加 DefaultFeatureSnapAgent.OnSelectionChanged 实现
}
public void OnSketchFinished()
{
//TODO: 添加 DefaultFeatureSnapAgent.OnSketchFinished 实现
}
publicvoid OnSketchModified()
{
//TODO: 添加 DefaultFeatureSnapAgent.OnSketchModified 实现
}
public void OnStartEditing()
{
//TODO: 添加 DefaultFeatureSnapAgent.OnStartEditing 实现
}
public void OnStopEditing(Boolean save)
{
//TODO: 添加 DefaultFeatureSnapAgent.OnStopEditing 实现
}
public void OnUndo()
{
//TODO: 添加 DefaultFeatureSnapAgent.OnUndo 实现
}
#endregion
#region ISnapFeedback 成员
private string m_snapFeedbackText;
public string SnapText
{
get
{
return this.m_snapFeedbackText;
}
}
private void SetFeedback(string feedback)
{
this.m_snapFeedbackText=feedback;
}
#endregion
#region IPersistVariant 成员
public ESRI.ArcGIS .esriSystem .UID ID
{
get
{
ESRI.ArcGIS .esriSystem .UID uid=new ESRI.ArcGIS .esriSystem .UIDClass();
uid.Value="ls.gis.Editor.DefaultFeatureSnapAgent"+this.m_snapAgentName;
return uid;
}
}
public void Load(ESRI.ArcGIS .esriSystem .IVariantStream vs)
{
this.m_snapAgentName =(string)vs.Read ();
this.m_isSnapWorking =(bool)vs.Read ();
string hitPartStr=(string)vs.Read ();
this.m_hitPartType =(esriGeometryHitPartType)Enum.Parse(this.m_hitPartType .GetType (),hitPartStr,false);
bool hasFeatureClass=(bool)vs.Read ();
if(hasFeatureClass)
{
ESRI.ArcGIS .esriSystem .IName name=(ESRI.ArcGIS .esriSystem.IName)vs.Read ();
this.m_featureClass =(IFeatureClass)name.Open ();
}
}
public void Save(ESRI.ArcGIS .esriSystem .IVariantStream vs)
{
vs.Write (this.m_snapAgentName);
vs.Write (this.m_isSnapWorking );
vs.Write (this.m_hitPartType.ToString ());
if(this.m_featureClass !=null)
{
vs.Write (true);
IDataset dataset=(IDataset)this.m_featureClass ;
vs.Write (dataset.FullName );
}
else
{
vs.Write (false);
}
}
#endregion
}
public classDefaultSnapAgentEnvironment:ISnapAgentEnvironment
{
private double m_tolerance;
private SnapToleranceUnit m_snapToleranceUnit;
private ArrayList m_snapAgentArray;
///<summary>
///用于转换误差单位
///</summary>
private IActiveView m_activeView;
///<summary>
///如果误差单位为地图单位,那么可以调用这个构造函数。
///如果误差单位为象素。那么应该调用有参数的构造方法。
///如果在调用时不能确定参数activeView,那么也可以先调用该方法构造对象。
///然后用属性ActiveView来设置该参数的值。
///</summary>
publicDefaultSnapAgentEnvironment():this(null)
{
}
public DefaultSnapAgentEnvironment(IActiveView activeView)
{
m_snapAgentArray=new ArrayList ();
m_tolerance=7;
m_snapToleranceUnit=SnapToleranceUnit.UnitPixels;
this.m_activeView=activeView;
}
///<summary>
/// 用于转换误差的单位。如果没有设置,或者设置为null,
/// 那么误差的单位将不会被转换,而直接被认为是地图单位。
///</summary>
public IActiveView ActivView
{
set
{
this.m_activeView=value;
}
get
{
return this.m_activeView;
}
}
#region ISnapAgentEnvironment 成员
public void AddSnapAgent(ISnapAgent agent)
{
if(agent==null)
{
return;
}
if(this.m_snapAgentArray.Contains(agent))
{
return;
}
this.m_snapAgentArray.Add(agent);
}
public void ClearSnapAgent()
{
this.m_snapAgentArray.Clear();
}
///<summary>
///如果索引越界,那么返回null,而不会抛出异常。
///</summary>
///<param name="index"></param>
///<returns></returns>
public ISnapAgent GetSnapAgent(int index)
{
if(index<this.m_snapAgentArray.Count&&index>=0)
{
return (ISnapAgent)this.m_snapAgentArray[index];
}
else
{
return null;
}
}
///<summary>
///如果不存在,回返回null
///</summary>
///<param name="name"></param>
///<returns></returns>
ISnapAgent ls.gis.Editor.ISnapAgentEnvironment.GetSnapAgent(string name)
{
ISnapAgent retAgent=null;
int retAgentIndex=-1;
for(int index=0; index<this.m_snapAgentArray.Count;index++)
{
retAgent=(ISnapAgent)this.m_snapAgentArray[index];
if(retAgent.Name.Equals(name))
{
retAgentIndex=index;
break;
}
}
return GetSnapAgent(retAgentIndex);
}
public void RemoveSnapAgent(string name)
{
ISnapAgent retAgent=null;
int retAgentIndex=-1;
for(int index=0; index<this.m_snapAgentArray.Count;index++)
{
retAgent=(ISnapAgent)this.m_snapAgentArray[index];
if(retAgent.Name.Equals(name))
{
retAgentIndex=index;
break;
}
}
this.RemoveSnapAgent(retAgentIndex);
}
///<summary>
///
///</summary>
///<param name="index"></param>
public void RemoveSnapAgent(int index)
{
if(index<0||index>=this.m_snapAgentArray.Count)
{
return ;
}
this.m_snapAgentArray.RemoveAt(index);
}
public bool SnapPoint(IPoint point)
{
for(int index=0;index<this.m_snapAgentArray.Count;index++)
{
ISnapAgent agent=(ISnapAgent)this.m_snapAgentArray[index];
if(agent.Snap(null,point,ConvertTolerance(this.m_tolerance)))
{
return true;
}
}
return false;
}
public int SnapAgentCount
{
get
{
// TODO: 添加FeatureSnapAgentEnvironment.SnapAgentCount getter 实现
return this.m_snapAgentArray.Count;
}
}
public double SnapAgentTolerance
{
get
{
// TODO: 添加FeatureSnapAgentEnvironment.SnapAgentTolerance getter 实现
return this.m_tolerance;
}
set
{
this.m_tolerance=value;
}
}
public SnapToleranceUnit SnapToleranceUnit
{
get
{
return this.m_snapToleranceUnit;
}
set
{
this.m_snapToleranceUnit=value;
}
}
#endregion
private double ConvertTolerance(double tolerance)
{
double retValue=tolerance;
if(this.m_activeView ==null)
{
//不能做转换
retValue=tolerance;
}
else
{
if(this.m_snapToleranceUnit.Equals (SnapToleranceUnit.UnitPixels))
{
//需要转换
retValue=ls.gis.Common .CommonCooperation.ConvertPixelsToMapUnits(this.m_activeView ,tolerance);
}
else
{//不需要转换
retValue=tolerance;
}
}
return retValue;
}
private double ConvertTolerance()
{
return this.ConvertTolerance (this.m_tolerance);
}
}
2007-08-13 20:55
'/GR/ 在LAYER(i)上添加缓冲区
Public Function InsertBuffToLayer(pTopo AsITopologicalOperator, iLayer As Integer) As IGeometry
Dim pfeat As IFeature
Dim pFeatClass As IFeatureClass
Dim pFeatLayer As IFeatureLayer
Dim pFeatcursor As IFeatureCursor
'Set g_cllBuffShape = New Collection '清除缓冲区
Set pfeat = New Feature
Set pFeatLayer = g_pActiveView.FocusMap.Layer(iLayer)
Set pFeatClass = pFeatLayer.FeatureClass
Dim str As String
Set pfeat = pFeatClass.createFeature()
Set pfeat.Shape = pTopo.buffer(frmBuffDis.g_BuffDis)
Set InsertBuffToLayer = pfeat.Shape
End Function
Published 2007-9-22 17:13:00 - Program
1. 避免将多个类放在一个文件里面。
2. 一个文件应该只有一个命名空间,避免将多个命名空间放在同一个文件里面。
3. 一个文件最好不要超过500行的代码(不包括机器产生的代码)。
4. 一个方法的代码长度最好不要超过25行。
5. 避免方法中有超过5个参数的情况。使用结构来传递多个参数。
6. 每行代码不要超过80个字符。
7. 不要手工的修改机器产生的代码。
a) 如果需要编辑机器产生的代码,编辑格式和风格要符合该编码标准。
b) Use partial classes whenever possible tofactor out the maintained portions.
8. 避免利用注释解释显而易见的代码。
a) 代码应该可以自解释。好的代码由可读的变量和方法命名因此不需要注释。
9. Document only operational assumptions,algorithm insights and so on.
10. 避免使用方法级的文档。
a) 使用扩展的API文档说明之。
b) 只有在该方法需要被其他的开发者使用的时候才使用方法级的注释。(在C#中就是///)
11. 不要硬编码数字的值,总是使用构造函数设定其值。
12. 只有是自然结构才能直接使用const,比如一个星期的天数。
13. 避免在只读的变量上使用const。如果想实现只读,可以直接使用readonly。
public class MyClass
{
public readonly int Number;
public MyClass(int someValue)
{
Number = someValue;
}
public const int DaysInWeek = 7;
}
14. 每个假设必须使用Assert检查
a) 平均每15行要有一次检查(Assert)
using System.Diagnostics;
object GetObject()
{…}
object obj = GetObject();
Debug.Assert(obj != null);
15. 代码的每一行都应该通过白盒方式的测试。
16. 只抛出已经显示处理的异常。
17. 在捕获(catch)语句的抛出异常子句中(throw),总是抛出原始异常维护原始错误的堆栈分配。
catch(Exception exception)
{
MessageBox.Show(exception.Message);
throw ; //和throw exception一样。
}
18. 避免方法的返回值是错误代码。
19. 尽量避免定义自定义异常类。
20. 当需要定义自定义的异常时:
a) 自定义异常要继承于ApplicationException。
b) 提供自定义的序列化功能。
21. 避免在单个程序集里使用多个Main方法。
22. 只对外公布必要的操作,其他的则为internal。
23. Avoid friend assemblies, as itincreases inter-assembly coupling.
24. Avoid code that relies on an assemblyrunning from a particular location.
25. 使应用程序集尽量为最小化代码(EXE客户程序)。使用类库来替换包含的商务逻辑。
26. 避免给枚举变量提供显式的值。
//正确方法
public enum Color
{
Red,Green,Blue
}
//避免
public enum Color
{
Red = 1,Green = 2,Blue = 3
}
27. 避免指定特殊类型的枚举变量。
//避免
public enum Color : long
{
Red,Green,Blue
}
28. 即使if语句只有一句,也要将if语句的内容用大括号扩起来。
29. 避免使用trinary条件操作符。
30. 避免在条件语句中调用返回bool值的函数。可以使用局部变量并检查这些局部变量。
bool IsEverythingOK()
{…}
//避免
if (IsEverythingOK ())
{…}
//替换方案
bool ok = IsEverythingOK();
if (ok)
{…}
31. 总是使用基于0开始的数组。
32. 在循环中总是显式的初始化引用类型的数组。
public class MyClass
{}
MyClass[] array = new MyClass[100];
for(int index = 0; index < array.Length;index++)
{
array[index] = new MyClass();
}
33. 不要提供public 和 protected的成员变量,使用属性代替他们。
34. 避免在继承中使用new而使用override替换。
35. 在不是sealed的类中总是将public 和 protected的方法标记成virtual的。
36. 除非使用interop(COM+ 或其他的dll)代码否则不要使用不安全的代码(unsafecode)。
37. 避免显示的转换,使用as操作符进行兼容类型的转换。
Dog dog = new GermanShepherd();
GermanShepherd shepherd = dog asGermanShepherd;
if (shepherd != null )
{…}
38. 当类成员包括委托的时候
a) Copy a delegate to a local variablebefore publishing to avoid concurrency race
condition.
b) 在调用委托之前一定要检查它是否为null
public class MySource
{
public event EventHandler MyEvent;
public void FireEvent()
{
EventHandler temp = MyEvent;
if(temp != null )
{
temp(this,EventArgs.Empty);
}
}
}
39. 不要提供公共的事件成员变量,使用事件访问器替换这些变量。
public class MySource
{
MyDelegate m_SomeEvent ;
public event MyDelegate SomeEvent
{
add
{
m_SomeEvent += value;
}
remove
{
m_SomeEvent -= value;
}
}
}
40. 使用一个事件帮助类来公布事件的定义。
41. 总是使用接口。
42. 类和接口中的方法和属性至少为2:1的比例。
43. 避免一个接口中只有一个成员。
44. 尽量使每个接口中包含3-5个成员。
45. 接口中的成员不应该超过20个。
a) 实际情况可能限制为12个
46. 避免接口成员中包含事件。
47. 避免使用抽象方法而使用接口替换。
48. 在类层次中显示接口。
49. 推荐使用显式的接口实现。
50. 从不假设一个类型兼容一个接口。Defensively query for that interface.
SomeType obj1;
IMyInterface obj2;
/* 假设已有代码初始化过obj1,接下来 */
obj2 = obj1 as IMyInterface;
if (obj2 != null)
{
obj2.Method1();
}
else
{
//处理错误
}
51. 表现给最终用户的字符串不要使用硬编码而要使用资源文件替换之。
52. 不要硬编码可能更改的基于配置的字符串,比如连接字符串。
53. 当需要构建长的字符串的时候,使用StringBuilder不要使用string
54. 避免在结构里面提供方法。
a) 建议使用参数化构造函数
b) 可以重裁操作符
55. 总是要给静态变量提供静态构造函数。
56. 能使用早期绑定就不要使用后期绑定。
57. 使用应用程序的日志和跟踪。
58. 除非在不完全的switch语句中否则不要使用goto语句。
59. 在switch语句中总是要有default子句来显示信息(Assert)。
int number = SomeMethod();
switch(number)
{
case 1:
Trace.WriteLine("Case 1:");
break;
case 2:
Trace.WriteLine("Case 2:");
break;
default :
Debug.Assert(false);
break;
}
60. 除非在构造函数中调用其他构造函数否则不要使用this指针。
// 正确使用this的例子
public class MyClass
{
public MyClass(string message )
{}
public MyClass() : this("hello")
{}
}
61. 除非你想重写子类中存在名称冲突的成员或者调用基类的构造函数否则不要使用base来访问基类的成员。
// 正确使用base的例子
public class Dog
{
public Dog(string name)
{}
virtual public void Bark( int howLong)
{}
}
public class GermanShepherd : Dog
{
public GermanShe pherd(string name): base(name)
{}
override public void Bark(int howLong)
{
base .Bark(howLong);
}
}
62. 基于模板的时候要实现Dispose()和Finalize()两个方法。
63. 通常情况下避免有从System.Object转换来和由System.Object转换去的代码,而使用强制转换或者as操作符替换。
class SomeClass
{}
//避免:
class MyClass<T>
{
void SomeMethod(T t)
{
object temp = t;
SomeClass obj = (SomeClass)temp;
}
}
// 正确:
class MyClass<T> where T : SomeClass
{
void SomeMethod(T t)
{
SomeClass obj = t;
}
}
64. 在一般情况下不要定影有限制符的接口。接口的限制级别通常可以用强类型来替换之。
public class Customer
{…}
//避免:
public interface IList<T> where T :Customer
{…}
//正确:
public interface ICustomerList :IList<Customer>
{…}
65. 不确定在接口内的具体方法的限制条件。
66. 总是选择使用C#内置(一般的generics)的数据结构。
' //Deletes all featuresselected on the current layer
Public Sub DeleteAllSelectedFeatures(ByVal pFeatureCursor AsIFeatureCursor, ByVal GeometryTypeStr As String)
Dim pWorkspaceEdit As IWorkspaceEdit
Dim pFeature As IFeature
' If there are no features currentlyselected then nothing to do
If pFeatureCursor Is Nothing ThenExit Sub
Try
DimbResponse As DialogResult
bResponse =MsgBox("您确定删除所有"& GeometryTypeStr & "要素吗?",MessageBoxButtons.YesNo)
If bResponse= Windows.Forms.DialogResult.Yes Then
' Loop over the selected features deleting each in turn
pWorkspaceEdit = pSdeWorkspace
pWorkspaceEdit.StartEditing(True)
pWorkspaceEdit.StartEditOperation()
pFeature = pFeatureCursor.NextFeature
While Not pFeature Is Nothing
pFeature.Delete()
pFeature = pFeatureCursor.NextFeature
End While
pWorkspaceEdit.StopEditOperation()
pWorkspaceEdit.StopEditing(True)
End If
mainForm1.AxMapControl1.ActiveView.Refresh()
Exit Sub
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
1、基于AE获取要素简单信息
Private SubAxMapControl1_OnMouseDown(ByVal sender As Object, ByVal e AsESRI.ArcGIS.MapControl.IMapControlEvents2_OnMouseDownEvent) HandlesAxMapControl1.OnMouseDown
Me.AxMapControl1.MousePointer =ESRI.ArcGIS.SystemUI.esriControlsMousePointer.esriPointerIdentify
Dim pMap As IMap
Dim i AsInteger
DimgroupLayer As IGroupLayer
groupLayer =New GroupLayer
For i = 0 ToMe.AxMapControl1.Map.LayerCount - 1
groupLayer.Add(Me.AxMapControl1.Map.Layer(i))
Next
Dim pPoint AsIPoint
pMap =Me.AxMapControl1.Map
pPoint =Me.AxMapControl1.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x,e.y)
Dim pIdentify As IIdentify
Dim pIDArray As IArray
DimpFeatIdObj As IFeatureIdentifyObj
Dim pIdObjAs IIdentifyObj
pIdentify =groupLayer
Dim pEnv As IEnvelope
pEnv = NewEnvelope
pEnv =Me.AxMapControl1.ActiveView.Extent
pEnv.Height= 100
pEnv.Width =100
pEnv.CenterAt(pPoint)
pIDArray = pIdentify.Identify(pEnv)
If Not pIDArray Is Nothing Then
pFeatIdObj = pIDArray.Element(0)
pIdObj = pFeatIdObj
pIdObj.Flash(Me.AxMapControl1.ActiveView.ScreenDisplay)
'消息显示查询目标的信息
MsgBox("Layer:" & pIdObj.Layer.Name & vbNewLine &"Feature:" & pIdObj.Name)
Else
MsgBox("No feature identified.")
End If
Me.AxMapControl1.MousePointer =ESRI.ArcGIS.SystemUI.esriControlsMousePointer.esriPointerDefault
End Sub
2、基于AO获取要素详细信息
Private SubAxMapControl1_OnMouseDown(ByVal sender As Object, ByVal e AsESRI.ArcGIS.MapControl.IMapControlEvents2_OnMouseDownEvent) HandlesAxMapControl1.OnMouseDown
Me.AxMapControl1.MousePointer =ESRI.ArcGIS.SystemUI.esriControlsMousePointer.esriPointerIdentify
Dim pActiveView As IActiveView
pActiveView= Me.AxMapControl1.ActiveView
Dim pIdentifyDialogAs IIdentifyDialog
DimpIdentifyDialogProps As IIdentifyDialogProps
DimpEnumLayer As IEnumLayer
Dim pLayerAs ILayer
pIdentifyDialog = New IdentifyDialog
pIdentifyDialogProps = pIdentifyDialog 'QI
pIdentifyDialog.Map = Me.AxMapControl1.Map
pIdentifyDialog.Display = pActiveView.ScreenDisplay
'//Clear thedialog on each mouse click
pIdentifyDialog.ClearLayers()
'//Perform an identify on all of the layers the dialog
'//says aresearchable
pEnumLayer =pIdentifyDialogProps.Layers
pEnumLayer.Reset()
pLayer =pEnumLayer.Next
Do While NotpLayer Is Nothing
pIdentifyDialog.AddLayerIdentifyPoint(pLayer, e.x, e.y)
pLayer = pEnumLayer.Next
Loop
pIdentifyDialog.Show()
Me.AxMapControl1.MousePointer =ESRI.ArcGIS.SystemUI.esriControlsMousePointer.esriPointerDefault
End Sub
拓扑(ITopology)的使用包括
1.建立拓扑
2.验证拓扑
3.编辑过程中保证拓扑的正确
4.查询系统中存在的拓扑
1.首先 来看看建立拓扑
Topology实现了ITopology这个接口 但是给类是不能用来创建对象的。
必须要通过调用 ITopologyContainer::CreateTopology这个方法来建立一个Topology
FeatureDataset 实现了ITopologyContainer这个接口。那么 这就是说拓扑只能在一个
FeatureDataset的范围内建立。而不能独立存在于Workspace中。这样做的原因是需要保证
参与同一个拓扑的FeatureClass具有同一个投影坐标系统。 建立拓扑后需要将ObjectClass
加入到拓扑中去。这样这个拓扑就可以用来验证这几个ObjectClass 的对象之间的关系了。
验证关系就要有规则,规则是由ITopologyRule来表达的。ITopologyRule必须要被
加入到一个ITopologyRuleContainer中去。而Topology实现了这个接口。
一个ITopologyRule用来表达两个ObjectClass的对象之间的某个关系。
具体代码参看接口就可以了。
2.验证拓扑
ITopology有一个方法 ValidateTopology 用来验证指定区域内的拓扑。需要注意没有版本
的拓扑可以在 任何时候验证。而有版本的拓扑必须在编辑回话中验证。
3.拓扑编辑
1.移动共用点
1.首先需要打开拓扑 建立拓扑图(ITopologyGraph)
代码如下:
//topoLayer 是一个打开的拓扑图层
ITopologyGraph pTG=topoLayer.Topology.Cache;
pTG.Build(pA.Extent,false);
2.然后 需要获得当前节点或者边 这个操作要使用拓扑图的点击测试
ITopologyElement topeEle
pTG.HitTest(... ref topeEle);
这个方法在点击测试成功的时候返回true.而且会通过topeEle这个ref 参数将选中的元素(点或者边)
返回.
3.还有一种获取节点的方法
首先调用拓扑图的Select方法 选中点击测试的元素(pTG.Select)
然后可以查询拓扑图的选中节点集合 就可以找到该节点(pTG.NodeSelection)
4.为该元素使用一个Feedback.
//其中 pNode 就是当前节点 sr 是参考坐标系可以使用null
//还有给Feedback设置Display
m_pNodeFeedback =pTG.GetSplitMoveNodeFeedback(pNode,false,sr);
m_pNodeFeedback.Display= activeView.ScreenDisplay;
5.在鼠标移动的时候 调用Feedback的MoveTo 方法。
if(m_pNodeFeedback!=null)
{
//activeView 是活动的试图
//首先要把将点坐标转换为地图中的坐标。
//然后调用MoveTo 方法
IPoint pt=activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(X,Y);
m_pNodeFeedback.MoveTo(pt);
}
6.在鼠标释放的时候
//获取拓扑图
ITopologyGraph pTG=topoLayer.Topology.Cache;
//转换坐标
IPoint pt=pA.ScreenDisplay.DisplayTransformation.ToMapPoint(X,Y);
//获得正在做拓扑编辑的元素
ITopologyNode pTN=(ITopologyNode)m_pTopoElement;
//实施拓扑编辑
pTG.SplitMoveNode(pTN,pt,false);
//提交拓扑编辑结果
IEnvelope pE;
pTG.Post(out pE);
4.查询系统中的拓扑
还是ITopologyContainer 这个接口 这个接口有FeatureDataset这个唯一的实现。
CreateTopology 建立一个新的拓扑
DefaultClusterTolerance The default cluster tolerance as per the topologyengine.
MaximumClusterTolerance The maximal cluster tolerance as per the topologyengine.
MinimumClusterTolerance The minimal cluster tolerance as per the topologyengine.
Topology 通过索引打开拓扑.
TopologyByID 通过ID打开拓扑.
TopologyByName 通过名字打开拓扑
TopologyCount 拓扑的数目
1.Feature的基本渲染方法
Feature的常用的绘制方法包括:
1.简单绘制
2.唯一值绘制/多字段唯一值绘制
3.点密度/多字段点密度绘制
4.数据分级绘制
5.质量图(饼图/直方图)
6.按比例尺渲染
7.比例符号渲染
1.简单渲染
简单渲染是ArcEngine的默认渲染,我们打开一个FeatureClass,建立一个FeatureLayer的时候,
如果没有给FeatureLayer设置Renderer那么使用的就是简单渲染。简单渲染对整个图层中的所有Feature
使用同一种方式显示。
简单渲染在ArcEngine中用ISimpleRenderer来表示。
ISimpleRenderer的使用方式如下:
//假设layer是一个IFeatureLayer,获取IGeoFeatureLayer
IGeoFeatureLayer geoLayer=layer as IGeoFeatureLayer;
//构造SimpleRenderer
ISimpleRenderer renderer=new SimpleRendererClass();
renderer.description="简单的渲染一下";
renderer.Label="符号的标签";
//假设sym是一个和该图层中Geometry类型对应的符号;
renderer.Symbol=sym;
//为图层设置渲染,注意需要刷新该图层。
geoLayer.Renderer=renderer;
2.独立值/多字段独立值渲染
独立值/多字段独立值渲染,根据Feature的某一个字段的数据或某几个字段的组合结果来确定符号。
具有相同值或相同组合值的Feature,使用一样的符号。在使用多个字段的使用,每个字段的取值之间
使用分割符来连接。字段的取值顺序和在Renderer中设置的一样。
基本使用方式如下:
//假设layer是一个IFeatureLayer,获取IGeoFeatureLayer
IGeoFeatureLayer geoLayer=layer as IGeoFeatureLayer;
//构造一个UniqueValueRenderer
IUniqueValueRenderer renderer=new UniqueValueRendererClass();
//假设使用两个字段来渲染
renderer.FieldCount=2;
//假设YSLX字段表示要素类型
//假设YSYT字段表示要数用途
renderer.set_Field(0,"YSLX");
renderer.set_Field(1,"YSYT");
//字段之间使用 | 来连接(默认取值)
renderer.FieldDelimiter="|";
//设置默认符号
renderer.DefaultSymbol=defaultSymbol;
renderer.DefaultLabel="默认Label";
//添加值
renderer.addValue("房屋|民居","民居房屋",MJSymbol);
renderer.addValue("房屋|商业用地","商业用地",SYSymbol);
...
//还可以通过set_Symbol,set_Heading、set_Value来修改上述设置。
geoLayer.Renderer=renderer.
3.点密度/多字段点密度
点密度图通过在Feature的图形上打点来表示数据的数多,点越密集表示数据量越大。
还可以使用多字段的点密度图。这个使用同一个Feature上就可以显示几种不同的点。
注意点密度图有一个特殊的地方:
点密度图使用的符号是面状符号。而其中有需要包括点状符号。
接口使用如下:
IDotDensityRenderer renderer=newDotDensityRendererClass ();
IRendererFields flds=(IRendererFields)renderer;
flds.AddField("MJ ","面积");
flds.AddField("RK","人口");
IDotDensityFillSymbol ddSym=new DotDensityFillSymbolClass();
ISymbolArray symArray=(ISymbolArray)ddSym;
symArray.AddSymbol(mjSymbol);
symArray.AddSymbol(rkSymbol);
ddSym.Outline =(ILineSymbol)outlineSymbol ;
ddSym.DotSize =10 ;
ddSym.FixedPlacement=true;
renderer.DotDensitySymbol =ddSym;
renderer.DotValue=20 ;
renderer.MaintainSize=this.m_dotdensityParam .MaintainSize ;
IGeoFeatureLayer geoLayer=(IGeoFeatureLayer)layer ;
geoLayer.Renderer =(IFeatureRenderer)renderer;
4.数据分级绘制(使用IClassBreaksRenderer)
5.饼图/直方图(使用IChartRenderer)
6.按比例尺渲染(使IScaleDependentRenderer)
7.比例符号渲染(使用IProportionalSymbolRenderer )
2.图例的使用
图例的使用通过ILegendInfo接口。每个Renderer都实现了该接口,但是有时候该实现不好用,
所以也可以自己实现该接口。实现过程是比较简单的。
3.渲染层次
使用ILevelRender 接口。该接口可以指定一 当前的Level(-1)表示绘制全部。
然后 提供一个符号数组 ,注意每个符号要指定Level.如果不指定就默认为0。
4.透明度控制
透明度控制使用 ITransparencyRenderer 接口。该接口允许指定一个字段,字段取值用来表示透明度
注意 透明度的取值在0--100之间。
5.数据正规化
数据正规化用 IDataNormalization 接口来表示。该接口提供了几种正规化表示方法。
6.部分渲染
部分渲染通过使用IDataExclusion 来实现。该接口允许提供过滤语句来过滤掉不需要渲染的Feature。
同时也可以给他们制定特殊的符号。同时控制是否显示
7.旋转控制
旋转控制通过使用IRotationRenderer 接口来表示。该接口要求提供旋转角度的字段。同时要求提供旋转的
方法。
8.数据样本
IDataSampling 没有使用过。
9.外表关联
ITable dispTable=((IDisplayTable)feaLayer).DisplayTable ;//图层
ITable attTable;//外表
IMemoryRelationshipClassFactory fac=newMemoryRelationshipClassFactoryClass ();
IRelationshipClass relClass=fac.Open("JZMJ",(IObjectClass)dispTable,"ZDDJH",
IObjectClass)attTable,"G03",
"Forward","Backward",
esriRelCardinality.esriRelCardinalityOneToOne);
IDisplayRelationshipClass dispRelClass=feaLayer asIDisplayRelationshipClass ;
dispRelClass.DisplayRelationshipClass(relClass,esriJoinType.esriLeftInnerJoin);
10.统计分析
ITableHistogram tableHistogram=new BasicTableHistogramClass();
tableHistogram.Table =((IDisplayTable)layer).DisplayTable ;
tableHistogram.Field =fieldName ;
object valueArray=null, freq=null;
IBasicHistogram basicHistogram=(IBasicHistogram)tableHistogram;
basicHistogram.GetHistogram(out valueArray,out freq);
IClassify classify=null;
int breakNum=6;
//分类方法
switch(ClassifyMethod )
{
case ClassifyMethodName.lsClassifyMethodEqualInterval:
{
EqualIntervalClass eq=newEqualIntervalClass ();
eq.Classify (valueArray,freq,ref breakNum);
classify=(IClassify)eq;
break;
}
caseClassifyMethodName.lsClassifyMethodStandardDeviation:
{
StandardDeviationClass sd=newStandardDeviationClass ();
IStatisticsResults stat= histogram asIStatisticsResults ;
classify=sd as IClassify;
classify.SetHistogramData(valueArray,freq);
IDeviationInterval di=sd asIDeviationInterval ;
di.DeviationInterval=1;
di.Mean=stat.Mean;
di.StandardDev=stat.StandardDeviation;
classify.Classify (ref breakNum);
break;
}
case ClassifyMethodName.lsClassifyMethodQuantile:
{
Quantile qc=new QuantileClass ();
qc.Classify (valueArray,freq,ref breakNum);
classify=qc as IClassify ;
break;
}
case ClassifyMethodName.lsClassifyMethodNaturalBreaks:
{
NaturalBreaksClass nb=newNaturalBreaksClass ();
nb.Classify (valueArray,freq,ref breakNum);
classify=nb as IClassify ;
break;
}
caseClassifyMethodName.lsClassifyMethodDefinedInterval:
{
DefinedIntervalClass di=new DefinedIntervalClass();
di.IntervalRange =this.m_classBreaksParam.Interval ;
di.Classify (valueArray,freq,ref breakNum);
classify=di as IClassify ;
break;
}
default:
{
EqualIntervalClass eq=newEqualIntervalClass ();
eq.Classify (valueArray,freq,ref breakNum);
classify=(IClassify)eq;
break;
}
}
object o=classify.ClassBreaks ;
System.Array breakArray= o as System.Array;
现在breakArray中就是统计后的数据了。
一个简单的空间分析例子:vb实现在地图上画一个矩形或者
圆后,计算出该区域内的要素的数目。
创建临时图层
在临时图层上用程序或者让用户手动的创建一个矩形或者圆形
然后使用空间过滤器,spatialfilter
指定一下它的参数,进行查找就行了。
具体的使用在帮助文档里有。
在地图上画矩形或者圆形可以通过INewCircleFeedback接口实现,画矩形同理,只需转换使用的接口就可以了,以下以画圆形为例(该代码是在ArcMap的VBA环境下,建立用户控件使用的):
Private m_pDoc As IMxDocument
Private m_pAV As IActiveView
Private m_pScrD As IScreenDisplay
Private m_pNewCircFeedback AsINewCircleFeedback
Private Function UIToolControl1_Enabled()As Boolean
'Set the ToolControl to enabled (disabled by default if any code ispresent in this event)
UIToolControl1_Enabled = True
'Check that we have a reference to the ActiveView and ScreenDisplay
Ifm_pScrD Is Nothing Then
Set m_pDoc = Application.Document
Set m_pAV = m_pDoc.ActiveView
Set m_pScrD = m_pAV.ScreenDisplay
EndIf
End Function
Private Sub UIToolControl1_MouseDown(ByValbutton As Long, ByVal shift As Long, ByVal x As Long, ByVal y As Long)
DimpPnt As IPoint
'Get the current mouse location in Map Units
SetpPnt = m_pScrD.DisplayTransformation.ToMapPoint(x, y)
'Check that user is not using an existing feedback
Ifm_pNewCircFeedback Is Nothing Then
'Create a NewCircleFeedback object
Set m_pNewCircFeedback = New NewCircleFeedback
'Set the Feedback's Display and StartPoint
Set m_pNewCircFeedback.Display = m_pScrD
m_pNewCircFeedback.Start pPnt
EndIf
End Sub
Private Sub UIToolControl1_MouseMove(ByValbutton As Long, ByVal shift As Long, ByVal x As Long, ByVal y As Long)
'Check if the user is currently using the feedback
IfNot m_pNewCircFeedback Is Nothing Then
Dim pPnt As IPoint
'Move the Feedback to the current mouse location
Set pPnt = m_pScrD.DisplayTransformation.ToMapPoint(x, y)
m_pNewCircFeedback.MoveTo pPnt
EndIf
End Sub
Private Sub UIToolControl1_MouseUp(ByValbutton As Long, ByVal shift As Long, ByVal x As Long, ByVal y As Long)
DimpCircArc As IGeometry
'Check if the user is currently using the feedback
IfNot m_pNewCircFeedback Is Nothing Then
'Get the geometry (ICircularArc) returned from the feedback
Set pCircArc = m_pNewCircFeedback.Stop
'If it is valid then create a CircleElement on the ActiveView using the'AddCreateElement' procedure
If Not pCircArc Is Nothing Then
AddCreateElement pCircArc, m_pAV
m_pAV.Refresh
End If
'Set the feedback to nothing for the next use
Set m_pNewCircFeedback = Nothing
EndIf
End Sub
Private Sub AddCreateElement(pCircArc AsICircularArc, pAV As IActiveView)
' Takes an ICircularArc and IActiveView andcreates a CircleElement in the ActiveView's BasicGraphicsLayer
DimpElemFillShp As IFillShapeElement
DimpElem As IElement
DimpGraCont As IGraphicsContainer
DimpSFSym As ISimpleFillSymbol
DimpRGB As IRgbColor
DimpSegColl As ISegmentCollection
'Create a new Polygon object and access the ISegmentCollection interface to adda segment
SetpSegColl = New Polygon
pSegColl.AddSegment pCircArc
'Create a new circleelement and use the IElement interface to set the itsGeometry
SetpElem = New CircleElement
pElem.Geometry = pSegColl
'QI for the IFillShapeElement interface so that the Symbol property can be set
SetpElemFillShp = pElem
'Create a new RGBColor
SetpRGB = New RgbColor
With pRGB
.Red = 198
.Green = 255
.Blue = 214
EndWith
'Create a new SimpleFillSymbol and set its Color and Style
SetpSFSym = New SimpleFillSymbol
pSFSym.Color = pRGB
pSFSym.Style = esriSFSSolid
pElemFillShp.Symbol = pSFSym
'QI for the IGraphicsContainer interface from the IActiveView, allows access tothe BasicGraphicsLayer
SetpGraCont = pAV
'Add the element at Z order zero
pGraCont.AddElement pElemFillShp, 0
End Sub
至于搜索,只需在取得pCircArc后利用ISpatialFilter即可实现,代码如下:
Dim pFilter As IspatialFilter
Set pFilter = New SpatialFilter
With pFilter
Set .Geometry = pCircArc
.GeometryField = "SHAPE"
.SpatialRel = esriSpatialRelIntersects
EndWith
dim featureCount as Integer
featurecount=pFeatureClass.FeatureCountpFilter
featurecount即为要搜索的pfeatureclass中的实体个数
已知一个要素图层和我们的选择条件,寻找出符合要求的要素并闪烁显示,使用的IfeatureSelection接口的SelectFeatures方法
Public Sub searchSelection(byval sqlfilteras string, byval pFeatLyr as iFeatureLayer)
Dim pFilter As IqueryFilter ‘做一个过滤器
pFilter = New QueryFilter
pFilter.WhereClause = sqlfilter 如"area>100000",ARCGIS中的字段值是区分大小写的,如nevada不能写成Nevada
Dim pFeatureSelection As IFeatureSelection ‘获取图层
pFeatureSelection = pFeatLyr ‘QI
pFeatureSelection.SelectFeatures(pFilter,
esriSelectionResultEnum.esriSelectionResultNew,False) ‘重要方法
Dim pColor As IRgbColor
pColor = New RgbColor
pColor.Red = 220
pColor.Green = 112
pColor.Blue = 60
pFeatureSelection.SelectionColor = pColor ‘将选择集添上颜色
AxMapControl1.CtlRefresh(esriViewDrawPhase.esriViewGeoSelection)
‘控件局部刷新
Dim pFeatSet As IselectionSet ‘新建一个selectionset对象,它用于保存获得的要素
pFeatSet = pFeatureSelection.SelectionSet
Dim pFeatCursor As IFeatureCursor
pFeatSet.Search(Nothing, True, pFeatCursor)‘使用要素游标去获取单个要素
Dim pFeat As IFeature
pFeat = pFeatCursor.NextFeature
Do Until pFeat Is Nothing
If Not pFeat Is Nothing Then
Dim pFillsyl2 As ISimpleFillSymbol
pFillsyl2 = New SimpleFillSymbol
pFillsyl2.Color = getRGB(220, 60, 60)
AxMapControl1.FlashShape(pFeat.Shape, 15,20, pFillsyl2) ‘被选中的要素闪烁
‘将要素的某个字段值写入LISTBOX
ListBox1.Items.Add(pFeat.Value(pFeatCursor.FindField("state_name")))
ListBox1.Refresh() ‘可以使listbox中的项逐个出现
End If
pFeat = pFeatCursor.NextFeature
Loop
End Sub
我们需要注意“将选择集添上颜色”这个语句,在这个过程中,符合要求的要素将呈选择状态,我们可以使用另外一种方法来设置选择集的颜色:
Dim pSelEnv As ISelectionEnvironment
Dim pRgbColor As IRgbColor
Set pSelEnv = New SelectionEnvironment
Set pRgbColor = New RgbColor
pRgbColor.Red = 255
pSelEnv.AreaSelectionMethod =esriSpatialRelIntersects
Set pSelEnv.DefaultColor = pRgbColor
MapControl1.Map.SelectByShape MapControl1.TrackCircle,pSelEnv, False
MapControl1.Refresh esriViewGeography
如上面代码中看到的,SelectionEnvironment能够控件的要素选择集的缺省颜色,缺省symbol等。
'****************************************************************
'函数功能: 将矢量要素导入到指定数据库的数据集中,可以将shapefile,dxf,coverage格式导入倒GEodatabase中
' 参数表:
' pInDatasetNameCol 一个存储要导入的矢量要素(IFeatureClassName类型)的Collection对象
' pOutNameCol 一个存储导入的矢量要素名称(string类型)的Collection对象
' strGDBPath 包含矢量要素数据集名称的GDB路径,如“D:\world\Map3D.mdb”
'****************************************************************
Public FunctionconvFeatureClass(pInDatasetNameCol As Collection, pOutNameCol As Collection,strGDBPath As String)
'获得导入数据的数目
Dim iInFCNum As Integer
iInFCNum = pInDatasetNameCol.Count
'获得输出的数据库名和数据集名
Dim sOutFDSName As String
Dim sOutGDBName As String
sOutFDSName = GetPathName(strGDBPath, 1)
sOutGDBName = GetPathName(strGDBPath, 0)
'获得输出要素集的IFeatureDatasetName
Dim pWSF As IWorkspaceFactory
Set pWSF = New AccessWorkspaceFactory
Dim pWS As IWorkspace
Set pWS = pWSF.OpenFromFile(sOutGDBName, 0)
Dim pOutFeatureWS As IFeatureWorkspace
Set pOutFeatureWS = pWS
'获得输出要素集的Dataset Name
Dim pOutFDSName As IFeatureDatasetName
Dim pOutFDS As IFeatureDataset
Set pOutFDS =pOutFeatureWS.OpenFeatureDataset(sOutFDSName)
Set pOutFDSName = pOutFDS.FullName
Dim i As Integer
For i = 1 To iInFCNum
Dim pOutPropertySet As IPropertySet
Set pOutPropertySet = New PropertySet
pOutPropertySet.SetProperty "DATASET", sOutGDBName
Dim pOutWorkspaceName As IWorkspaceName
Set pOutWorkspaceName = New WorkspaceName
pOutWorkspaceName.ConnectionProperties = pOutPropertySet
pOutWorkspaceName.WorkspaceFactoryProgID ="esriDataSourcesGDB.AccessWorkspaceFactory.1"
'设置输出要素的FeatureClass Name
Dim pOutFCName As IFeatureClassName
Set pOutFCName = New FeatureClassName
Dim pDatasetName As IDatasetName
Set pDatasetName = pOutFCName
Set pDatasetName.WorkspaceName = pOutWorkspaceName
pDatasetName.name = pOutNameCol.Item(i)
'获得输入要素的FeatureClass Name
Dim pInDatasetName As IDatasetName
Set pInDatasetName = pInDatasetNameCol.Item(i)
'判断是否有重名现象
Dim pWS2 As IWorkspace2
Set pWS2 = pWS
'如果名称已存在
If pWS2.NameExists(esriDTFeatureClass, pDatasetName.name) Then
Dim R
R = MsgBox("矢量要素" & pDatasetName.name & "在数据库中已存在!" & Chr(13) &"是否覆盖?",vbExclamation + vbYesNo)
'覆盖原矢量要素
If R = vbYes Then
Dim pFWS As IFeatureWorkspace
Set pFWS = pWS
Dim pDataset As IDataset
Set pDataset = pFWS.OpenFeatureClass(pDatasetName.name)
pDataset.Delete
Set pFWS = Nothing
Set pDataset = Nothing
'不覆盖,则退出for循环,忽略这个要素,转入下一个要素的导入
Else
GoTo NextStep
End If
Set pWS2 = Nothing
End If
'打开Table获得Fields
Dim pname As IName
Dim pInTable As ITable
Set pname = pInDatasetName
Set pInTable = pname.Open
DimpInFields As IFields
Set pInFields = pInTable.Fields
'检查Field Name
Dim pFieldChecker As IFieldChecker
Set pFieldChecker = New FieldChecker
Dim pOutFields As IFields
pFieldChecker.Validate pInFields, Nothing, pOutFields
'对Fields进行循环查,查找Geometry域
Dim j As Integer
Dim pGeoField As IField
For j = 0 To pOutFields.FieldCount - 1
If pOutFields.Field(j).Type = esriFieldTypeGeometry Then
Set pGeoField = pOutFields.Field(j)
Exit For
End If
Next j
'获得Geometry Field的GeometryDef
Dim pOutFCGeoDef As IGeometryDef
Set pOutFCGeoDef = pGeoField.GeometryDef
'设置GeometryDef的GridCount,GridSize,SpatialReference
Dim pOutFCGeoDefEdit As IGeometryDefEdit
Set pOutFCGeoDefEdit = pOutFCGeoDef
pOutFCGeoDefEdit.GridCount = 1
pOutFCGeoDefEdit.GridSize(0) = DefaultIndexGrid(pInTable)
Dim re
'判断空间参考是否一致,全局变量m_SpatialRef是创建的矢量要素集的空间参考
If m_SpatialRef.name <> pGeoField.GeometryDef.SpatialReference.nameThen
re = MsgBox(pInDatasetName.name & "的空间参考与数据库中的矢量要素集空间参考不符!" &Chr(13) _
& "导入后会丢失数据。 是否继续导入?", vbYesNo + vbExclamation)
Set pOutFCGeoDefEdit.SpatialReference = m_SpatialRef
If re = vbNo Then
GoTo NextStep
End If
Else
Set pOutFCGeoDefEdit.SpatialReference =pGeoField.GeometryDef.SpatialReference
End If
'+++++++++++++++++++
'Set pOutFCGeoDefEdit.SpatialReference =pGeoField.GeometryDef.SpatialReference
'进行导入
Dim pConverter As IFeatureDataConverter
Set pConverter = New FeatureDataConverter
pConverter.ConvertFeatureClass pInDatasetNameCol.Item(i), Nothing,pOutFDSName, pOutFCName, pOutFCGeoDef, pOutFields, "", 1000, 0
Set pOutPropertySet = Nothing
Set pOutWorkspaceName = Nothing
Set pOutFCName = Nothing
Set pDatasetName = Nothing
Set pInDatasetName = Nothing
Set pname = Nothing
Set pInTable = Nothing
Set pFieldChecker = Nothing
Set pOutFields = Nothing
Set pGeoField = Nothing
Set pOutFCGeoDef = Nothing
Set pConverter = Nothing
NextStep:
Next i
Set pWSF = Nothing
Set pWS = Nothing
End Function
用AO开发已经有一段时间了,对AO开发的模式也有一定的了解了!AO是ESRI开发的一组COM的集合,利用它用户可以进行二次开发,以快速建立满足自己要求的GIS应用.
AO开发就是利用一些类和这些类的接口进行开发.
1、抽象类,类,和组件对象类
抽象类是不能实例化的,抽象类中是一系列抽象的方法,故是不能实例化的,它只能被继承。不同的类可以继承同一个抽象类,但内部对同一方法的实现可能是不一样的。如AO中的接口都是抽象类。用户可以在类中实现这些接口,也就是继承这些接口。如用户可以在自己的类中实现ICommand接口,生成一个Command,或者实现ICommand、ITool接口,生成一个Tool.
类是不能直接实例化的,它只能作为另一个类的属性或者被其它类的对象实例化。如Sde3Workspace Class、Sde4Workspace Class,FeatureClass,FeatureDataset它们是不能通过New直接实例化的,只能通过SdeWorkspaceFactoryCoClass这个组件对象类所实现的IWorkspaceFactory接口里的Open方法来实例化。FeatureClass,FeatureDataset也是不能直接实例化的,他只能通过IFeatureWorkspace接口里的CreateFeatureClass,CreateFeatureDataset方法来实例化。
组件对象类能够通过New来直接实例化。如 SdeWorkspaceFactory,QueryFilter它们是可以通过New来直接实例化的。
2、继承
3、类和接口的实现
一些类可能实现多个接口,一个接口也可能被多个类所实现,但不同的类实现同一个接口可能内部并不是一样的,这就实现了多态性.如ILayer这个接口被多个接口实现,其中包括FeatureLayer和RasterLayer,但这两个类实现ILayer接口时内部实现肯定是不一样的!但在外部对ILayer的操作是一样的!
4、接口之间的相互查询
一个类可以实现多个接口,每一个接口可能包括一系列的属性和方法,但有时候一个接口里可能没有你想要的方法和属性,可能在这个类所实现接口的另一个接口里,这就涉及到从一个接口转到这个类所实现接口的另一个接口里,对于类所实现的一系列接口里,接口间是可以相互跳转的。如我想对一个feature的属性进行修改,给的就是这个feature的IFeature接口,我们知道对一个feature进行修改必须要把这个feature所在的featureclass的工作空间设为可编辑,且编辑结束后要结束编辑,这就要通过这个IFeatue接口来获得这个这个feature所在的IFeatureClass接口和IWorkspace接口,我们知道IFeatue接口里有一个object属性,这个属性返回的是IObjectClass,而FeatureClass这个类实现了IObjectClass和IFeatureClass这两个接口,这样就可以通过接口跳转从IObjectClass转换成IFeatureClass,这样就可以获得feature的IFeatureClass接口,其代码(c#)如下:
IObjectClass i_objcls=I_FtrCur.Class;
IFeatureClass i_ftrcls=(IFeatureClass)i_objcls;
Feature所在的FeatureClass的IFeatureClass接口有了,还要这个FeatureClass所在的工作空间的IWorkspace接口,获取这个接口可以通过两个方法
一、通过IFeatureClass接口里的FeatureDataset属性来获得IFeatureDataset接口。
IFeatureDataset接口里有一个Workspace属性返回IWorkspace接口,但这种方法有一个特别说明就是这个FeatureClass必须是一个FeatureDataset的成员,如果这个FeatureClass是一个独立,这个FeatureDataset返回的就是一个空值。所以这种方法对FeatureClass是一个FeatureDataset的成员时是适用的,独立时就不适用了。
二、通过接口转换。
FeatureClass实现了多个接口,其中有IDataset接口和IFeatureClass接口,我们已经有了IFeatureClass接口,就可以通过接口跳转来获得IDataset接口,在IDataset接口里有一个Workspace属性返回IWorkspace接口,这种方法对于FeatureClass是一个FeatureDataset的成员和FeatureClass是独立的这两种情况都是可以的。代码如下:
IDataset i_ftrDset=(IDataset)i_ftrcls //接口跳转
IFeatureWorkspacei_wks=(IFeatureWorkspace)i_ftrDset.Workspace
作者:Flyingis
ArcEngine Geometry库定义了基本几何图形的矢量表达形式,顶级的几何图形有Points、Multipoints、Polylines、Polygons、 Multipatches,Geodatabase和绘图系统使用这些几何图形来定义其他各种形状的特征和图形,提供了编辑图形的操作方法和地图符号系统符号化特征数据的途径。
Geometry库中几个核心类和接口构成了Geometry对象的基本框架。
GeometryEnvironment
GeometryEnvironment提供了从不同的输入、设置或获取全局变量来创建几何图形的方法,以便控制geometry方法的行为。GeometryEnvironment对象是一个单例对象。
publicIPolyline TestGeometryEnvironment()
{
ISpatialReferenceFactoryspatialReferenceFactory = new SpatialReferenceEnvironmentClass();
//Create a projected coordinate system anddefine its domain, resolution, and x,y tolerance.
ISpatialReferenceResolution spatialReferenceResolution=spatialReferenceFactory.CreateProjectedCoordinateSystem((int)esriSRProjCSType.esriSRProjCS_NAD1983UTM_11N)as ISpatialReferenceResolution;
spatialReferenceResolution.ConstructFromHorizon();
ISpatialReferenceTolerance spatialReferenceTolerance= spatialReferenceResolution as ISpatialReferenceTolerance;
spatialReferenceTolerance.SetDefaultXYTolerance();
ISpatialReference spatialReference =spatialReferenceResolution as ISpatialReference;
//Create an array of WKSPoint structuresstarting in the middle of the x,y domain of the
//projected coordinate system.
double xMin;
double xMax;
double yMin;
double yMax;
spatialReference.GetDomain(out xMin, outxMax, out yMin, out yMax);
double xFactor = (xMin + xMax) * 0.5;
double yFactor = (yMin + yMax) * 0.5;
WKSPoint[] wksPoints = new WKSPoint[10];
for (int i = 0; i < wksPoints.Length;i++)
{
wksPoints[i].X = xFactor + i;
wksPoints[i].Y = yFactor + i;
}
IPointCollection4 pointCollection = newPolylineClass();
IGeometryBridge2 geometryBridge = newGeometryEnvironmentClass();
geometryBridge.AddWKSPoints(pointCollection, ref wksPoints);
IPolyline polyline = pointCollection asIPolyline;
polyline.SpatialReference =spatialReference;
return polyline;
} new GeometryEnvironmentClass仅仅是创建了一个指向已存在的GeometryEnvironmentClass的引用。注意 IGeometryBridge2接口的使用,addWKSPoints方法将WKSPoint二维点添加到PointCollection中,用于构建 path、ring、polyline、polygon,或增加新点到Multipoint、TriangleFan、TriangleStrip。在 Geometry库中,除了IGeometryBridge2还有IGeometryBridge接口,后者继承了前者,增加了一些编辑功能(添加点、插入点、重置点、分段等)。
GeometryBag
GeometryBag是支持IGeometry接口的几何对象引用的集合,任何几何对象都可以通过IGeometryCollection接口添加到 GeometryBag中,但是在使用拓扑操作的时候,需要注意不同类型的几何类型可能会有相互不兼容的情况。在向GeometryBag中添加几何对象的时候,GeometryBag对象需要指定空间参考,添加到其中的几何对象均拥有和GeometryBag对象一样的空间参考。
privateIPolygon GeometryBag_Example(IFeatureClass featureClass)
{
//Check input objects.
if (featureClass == null)
{
return null;
}
IGeoDataset geoDataset = featureClass asIGeoDataset;
ISpatialFilter queryFilter = newSpatialFilterClass();
//Set the properties of the spatial filterhere.
IGeometry geometryBag = newGeometryBagClass();
//Define the spatial reference of the bagbefore adding geometries to it.
geometryBag.SpatialReference =geoDataset.SpatialReference;
//Use a nonrecycling cursor so eachreturned geometry is a separate object.
IFeatureCursor featureCursor =featureClass.Search(queryFilter, false);
IGeometryCollection geometryCollection =geometryBag as IGeometryCollection;
IFeature currentFeature =featureCursor.NextFeature();
while (currentFeature != null)
{
//Add a reference to this feature'sgeometry into the bag.
//You don't specify the before or aftergeometry (missing),
//so the currentFeature.Shape IGeometryis added to the end of the geometryCollection.
object missing = Type.Missing;
geometryCollection.AddGeometry(currentFeature.Shape, ref missing, refmissing);
currentFeature =featureCursor.NextFeature();
}
// Create the polygon that will be theunion of the features returned from the search cursor.
// The spatial reference of this featuredoes not need to be set ahead of time. The
// ConstructUnion method defines theconstructed polygon's spatial reference to be the same as
// the input geometry bag.
ITopologicalOperator unionedPolygon = newPolygonClass();
unionedPolygon.ConstructUnion(geometryBagas IEnumGeometry);
return unionedPolygon as IPolygon;
}
Points
一个点包括X、Y坐标,同时可以增加M、Z值及ID属性来扩展点的功能。
Multipoints
点的集合,多点组成Multipoint几何类型,使用multipoint对象实现了的IPointCollection接口可以访问所有的点元素,这些点同样可以拥有M、Z值及ID属性来获得更多的地理空间内涵。
下面列举一个例子,通过一个已知的polyline来定义一个新的multipart polyline。
publicIPolyline ConstructMultiPartPolyline(IPolyline inputPolyline)
{
IGeometry outGeometry = newPolylineClass();
//Always associate new, top-levelgeometries with an appropriate spatial reference.
outGeometry.SpatialReference =inputPolyline.SpatialReference;
IGeometryCollection geometryCollection =outGeometry as IGeometryCollection;
ISegmentCollection segmentCollection =inputPolyline as ISegmentCollection;
//Iterate over existing polyline segmentsusing a segment enumerator.
IEnumSegment segments =segmentCollection.EnumSegments;
ISegment currentSegment;
int partIndex = 0;;
int segmentIndex = 0;;
segments.Next(out currentSegment,refpartIndex, ref segmentIndex);
while(currentSegment != null)
{
ILine normal = new LineClass();
//Geometry methods with _Query_ intheir name expect to modify existing geometries.
//In this case, the QueryNormal methodmodifies an existing line
//segment (normal) to be the normalvector to
//currentSegment at the specifiedlocation along currentSegment.
currentSegment.QueryNormal(esriSegmentExtension.esriNoExtension,0.5, true, currentSegment.Length / 3, normal);
//Since each normal vector is notconnected to others, create a new path for each one.
ISegmentCollection newPath = newPathClass();
object missing = Type.Missing;
newPath.AddSegment(normal as ISegment,ref missing, ref missing);
//The spatial reference associated withgeometryCollection will be assigned to all incoming paths and segments.
geometryCollection.AddGeometry(newPathas IGeometry, ref missing, ref missing);
segments.Next(out currentSegment,refpartIndex, ref segmentIndex);
}
//The geometryCollection now contains thenew, multipart polyline.
return geometryCollection as IPolyline;
}
ISegment接口的QueryNormal方法用来在弧段上的某一点生成该弧段的法线,指定其长度,这样就生成了新的segment,并且多个path添加到geometryCollection中,以IPolyline的形式返回。
Polylines
Polylines是有序path组成的集合,可以拥有M、Z和ID属性值。Polyline对象的IPointCollection接口包含了所有节点的复制,IGeometryCollection接口可以获取polyline的paths,ISegmentCollection接口可以获取 polyline的segments。
Polyline结构图
Polygons
Polygon是一系列rings组成的集合,可以拥有M、Z和ID属性值。每一个ring由一个或多个segment组成,Polygon或ring对象的IPointCollection接口包含了所有节点的复制,IGeometryCollection接口可以获取polygon的rings,ISegmentCollection接口可以获取polygon的segments。
Polygon结构图
Multipatch
Multipatch用于描述3D面状几何类型,由一系列的矢量三角形构成,如果其中的part是一个ring,那么它必须是封闭的,第一个节点和最后一个节点相同,另外每个part所包含节点的顺序非常重要,Inner Rings在Outer Rings之后,代表单个表面patch的一系列rings必须由第一个ring开始。
在9.0以后的开发包中,使用IGeneralMultiPatchCreator创建新的Multipatch,IGeometryMaterial进行材质贴图。
publicIMultiPatch CreateMultipatch()
{
//Prepare the geometry material list.
IGeometryMaterial texture = newGeometryMaterialClass();
texture.TextureImage ="C:\\Temp\\MyImage.bmp";
IGeometryMaterialList materialList = newGeometryMaterialListClass();
materialList.AddMaterial(texture);
//Create the multipatch.
IGeneralMultiPatchCreator multiPatchCreator= new GeneralMultiPatchCreatorClass();
multiPatchCreator.Init(4, 1, false, false,false, 4, materialList);
//Set up part.
//Could also use a Ring or a TriangleFan.
multiPatchCreator.SetPatchType(0,esriPatchType.esriPatchTypeTriangleStrip);
multiPatchCreator.SetMaterialIndex(0, 0);
multiPatchCreator.SetPatchPointIndex(0, 0);
multiPatchCreator.SetPatchTexturePointIndex(0, 0);
//Set real-world points.
WKSPointZ upperLeft = new WKSPointZ();
WKSPointZ lowerLeft = new WKSPointZ();
WKSPointZ upperRight = new WKSPointZ();
WKSPointZ lowerRight = new WKSPointZ();
upperLeft.X = 0;
upperLeft.Y = 0;
upperLeft.Z = 0;
upperRight.X = 300;
upperRight.Y = 0;
upperRight.Z = 0;
lowerLeft.X = 0;
lowerLeft.Y = 0;
lowerLeft.Z = -100;
lowerRight.X = 300;
lowerRight.Y = 1;
lowerRight.Z = -100;
multiPatchCreator.SetWKSPointZ(0, refupperRight);
multiPatchCreator.SetWKSPointZ(1, reflowerRight);
multiPatchCreator.SetWKSPointZ(2, refupperLeft);
multiPatchCreator.SetWKSPointZ(3, reflowerLeft);
//Set texture points.
//Set the texture coordinates for a panel.
WKSPoint textureUpperLeft = new WKSPoint();
WKSPoint textureLowerLeft = new WKSPoint();
WKSPoint textureUpperRight = newWKSPoint();
WKSPoint textureLowerRight = newWKSPoint();
textureUpperLeft.X = 0;
textureUpperLeft.Y = 0;
textureUpperRight.X = 1;
textureUpperRight.Y = 0;
textureLowerLeft.X = 0;
textureLowerLeft.Y = 1;
textureLowerRight.X = 1;
textureLowerRight.Y = 1;
multiPatchCreator.SetTextureWKSPoint(0, reftextureUpperRight);
multiPatchCreator.SetTextureWKSPoint(1, reftextureLowerRight);
multiPatchCreator.SetTextureWKSPoint(2, reftextureUpperLeft);
multiPatchCreator.SetTextureWKSPoint(3, reftextureLowerLeft);
IMultiPatch multiPatch =multiPatchCreator.CreateMultiPatch() as IMultiPatch;
return multiPatch;
}
1.连接SDE的方法:
Public FunctionopenSDEWorkspace(Server As String, Instance As String, User As String, _
Password AsString, Optional Database As String = "", _
Optionalversion As String = "SDE.DEFAULT") As IWorkspace
On Error GoToEH
SetopenSDEWorkspace = Nothing
Dim pPropSet AsIPropertySet
Dim pSdeFact AsIWorkspaceFactory
Set pPropSet =New PropertySet
With pPropSet
.SetProperty"SERVER", Server
.SetProperty"INSTANCE", Instance
.SetProperty"DATABASE", Database
.SetProperty"USER", User
.SetProperty"PASSWORD", Password
.SetProperty"VERSION", version
End With
Set pSdeFact =New SdeWorkspaceFactory
SetopenSDEWorkspace = pSdeFact.Open(pPropSet, 0)
Exit Function
EH:
MsgBoxErr.Description, vbInformation, "openSDEWorkspace"
End Function
'///**************************************************************************************\\\
' 功能:
' 连接SDEgeodatabase.
' 参数:
' Server 服务器名称
' Instance SDE事例名称
' User 用户名
' Password 密码
' Database 数据库名称
' version 存放路径
'\\\**************************************************************************************///
'____________________________________________________________________
2.连接Access的即personalGeodataBase的方法:
FunctionOpenPGEO(connString As String) As IWorkspace
On Error GoToEH
Dim pWS AsIWorkspace
DimpWorkspaceFactory As IWorkspaceFactory
Set OpenPGEO =Nothing
Set pWorkspaceFactory= New AccessWorkspaceFactory
Set pWS =pWorkspaceFactory.OpenFromFile(connString, 1)
Set OpenPGEO =pWS
Exit Function
EH:
MsgBoxErr.Description, vbInformation, "openAccessWorkspace"
End Function
示冽:Set WKSpace = OpenPGEO("d:\phk.mdb")
3.
'///***************************************************************************\\\
'从WorkSpace取出一个FeatureClass 并添加到一个 IFeatureLayer 返回
' 2006.1.19 CBH
'\\\***************************************************************************///
Public FunctiongetFCfSDE(FclsName As String ,WKSpace As IWorkspace ) As IFeatureLayer
'///************************************************************************\\\
'此处要改为从SDE中取数据
Dim pFWKSpaceAs IFeatureWorkspace
Dim pFGLayer AsIFeatureLayer
Dim pFGClass AsIFeatureClass
Dim pVersionedObjectAs IVersionedObject
Dim pVersion AsIVersion
Set pFWKSpace =WKSpace
Set pFGClass =pFWKSpace.OpenFeatureClass(Trim(FclsName))
' SetpVersionedObject = pFGClass
'Registering astand alone feature class as versioned
' Set pVersion= pVersionedObject.version
'' MsgBoxpVersion.VersionName
'pVersionedObject.RegisterAsVersioned (True)
Set pFGLayer =New FeatureLayer
SetpFGLayer.FeatureClass = pFGClass
Set getFCfSDE =pFGLayer
'\\\************************************************************************///
End Function
通过上面3个基本方法,那就可以实现一个基本功能了,就是从任意GeodataBase中取出任意一个你需要的矢量数据,并且显示出来.作为GIS的应用开发,我想这写应该是第一步要做的.
那有人就想知道,如何取出一个 珊格的文件,并且显示呢? 我再给出下面2个基本方法,那么就也不是什么难事了:
4.打开一个珊格目录的方法:
Public FunctionOpenArcSDERasterCatalog(pWorks As IWorkspace, sRasterCatalogName As String) AsIRasterCatalog
Dim pWsFact AsIWorkspaceFactory
Dim pWs AsIRasterWorkspaceEx
DimpRasterCatalog As IRasterCatalog
DimpPropertySet As IPropertySet
Set pWs =pWorks
SetpRasterCatalog = pWs.OpenRasterCatalog(sRasterCatalogName)
SetOpenArcSDERasterCatalog = pRasterCatalog
Set pWsFact =Nothing
Set pWs =Nothing
SetpRasterCatalog = Nothing
End Function
5.去出一个珊格目录中的所有项并且作为一个RasterLayer提交:
functiongetRasterLayerFRCatalog( layerPath As String , WKSpace as IworkSpace )as Ilayer
DimpSDERasterCatlg As IRasterCatalog
Dim pLayer AsILayer
DimpGdbRasterCatalogLy As IGdbRasterCatalogLayer
Dim pFeature AsIFeatureLayer
Dim pGEO AsIGeoDataset
SetpGdbRasterCatalogLy = New GdbRasterCatalogLayer
SetpSDERasterCatlg = OpenArcSDERasterCatalog(WKSpace, Trim(layerPath))
pGdbRasterCatalogLy.SetuppSDERasterCatlg
Set player =pGdbRasterCatalogLy
end function
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。