ArcGIS Engine基础开发教程(转)
ArcGIS Engine基础开发教程(0)——目录
《ArcEngine9.3 基础开发教程》是面向初中级开发者的一份简单易用,功能全面的学习资料及参考文档。教程首先从如何来创建一个ArcGIS Engine桌面应用程序开始,依据GIS的数据获取(几何对象与空间参考)、显示(地图与地图布局、图层符号化、地图输出)、处理(地图查询)、分析(空间分析)主线来进行详细讲解。每一具体的部分均由目标、准备工作、接口介绍、实例代码、演示效果几方面来阐述。教程图文并茂,条理清晰,是初学者最佳的选择。
讲座题目:ArcGIS Engine基础开发教程
主讲人:fxlcoco
第一讲 创建第一个ArcGIS Engine桌面应用程序... 6
第二讲 学习何对象与空间参考... 15
第三讲 学习地图和地图布局... 44
第四讲 学习图层符号化... 64
第五讲 学习地图查询... 91
第六讲 学习空间分析... 110
第七讲 学习地图输出... 121、
ArcGIS Engine基础开发教程(2)——学习几何对象与空间参考
转载自: http://bbs.esrichina-bj.cn/ESRI/thread-46367-1-1.html
2.1目标
1.熟悉ArcGIS Engine Geometry模型,通过程序构建常用几何对象
2.熟悉空间参考
3.通过野外测量点构建一个polygon shapefile功能开发
2.2准备工作
1.IDE:Visual
2.ArcGIS Engine Developer kit 9.3
3.自造一份包含X,Y坐标的*.txt文本文档数据(即野外测量点)
2.3Geometry主要几何对象模型图
图1
Geometry是ArcGIS Engine中使用最为广泛的对象集之一,用户在创建、删除、编辑和进行地理分析的时候,就是处理一个包含几何形体的矢量对象;除了显示要素意外,控件对象选择,要素符号化,标注要素,编辑要素都需要Geometry参与。图1是Geometry的主要几何对象模型图,接下来将一一介绍这些几何对象
2.4几何对象
2.4.1Point和MultiPoint几何对象
2.4.1.1Point几何对象
Point:是一个0维的几何图形,具有X,Y坐标值,以及一些可选的属性:如高程值(Z值),度量值(M值) 和ID号,点对象用于描述精确定位的对象,例如一个电话亭在一个城市的精确位置以下代码演示如何创建一个Point对象:
- IPoint pPoint = new PointClass();
- pPoint.X = 100;
- pPoint.Y = 100;
复制代码
2.4.1.2MultiPoint几何对象
MultiPoint:点集对象是一系列无序的点的群集,这些点具有相同的属性信息。例如可以用一个点集来表示整个城市天然气调压站。如下图所示:一个Multipoint对象由6个Point对象组成。
图2
以下代码片段演示如何构建Multipoint对象:
//定义第一个点
IPoint pPoint1 = new PointClass();
pPoint1.X = 100;
pPoint1.Y = 100;
//定义第二个点
IPoint pPoint2 = new PointClass();
pPoint2.X = 200;
pPoint2.Y = 200;
……//构建其他点
IPointCollection pMultipoint = new MultipointClass();
object o=Type.Missing;
//添加第一个点,不需要设置点的顺序,参数设置为Type.Missing
pMultipoint.AddPoint(pPoint1, ref o, ref o);
//添加第二个点,不需要设置点的顺序,参数设置为Type.MissingpMultipoint.AddPoint(pPoint2, ref o, ref o);
……//添加其他点
2.4.2Segment几何对象
2.4.3Path和Ring几何对象
2.4.3.1Path几何对象
Path是连续的Segment的集合,除了路径的第一个Segment和最后一个Segment外其余的Segment的起始点都是前一个Segment的终止点,即Path对象的中的Segment不能出现分离,Path可以是任意数的Line,CircularArc,EllipticArc和BezierCurve的组合。
图4
一个或多个Path组成一个Polyline对象。
2.4.3.2Ring几何对象
Ring是一个封闭的Path即起始和终止点有相同的坐标值。它有内部和外部属性。
图5
一个或多个Ring对象组成一个Polygon对象。
2.4.4Polyline和Polygon几何对象
2.4.4.1Polyline几何对象
Polyline对象是由一个或多个相连或者不相连的path对象的有序集合,它可以是单个Path对象组成,也可以是多个相连的Path对象组成,或者是多个分离的Path组成,如下图所示。Polyline通常用来代表线状地物如道路,河流,管线等等。
图6
一个Polyline对象必须满足以下准则:
1.组成Polyline对象的所有Path对象必须是有效的。
2.组成Polyline对象的所有Path对象不能重合,相交或自相交。
3.组成Polyline对象的多个Path对象可以连接与某一点,也可以分离。
4.Path对象的长度不能为0.
IPolyline是Polyline类的主要接口,IPolyline的Reshape方法可以使用一个Path对象为一个Polyline对象整形,IPolyline的SimplifyNetwork方法用于简化网络。
Polyline对象可以使用IGeometryCollection接口添加Path对象的方法来创建,使用该接口需注意以下情况:
1.每一个Path对象必须是有效的,或使用IPath::Simplify方法后有效。
2.由于Polyline是Path对象的有序集合,所以添加Path对象时必须注意顺序和方向。
3.为了保证Polyline是有效的,可以创建完Polyline对象后使用ITopologicalOperator接口的Simplify方法。
以下代码片段为使用IGeometryCollection接口创建一个Polyline对象:
//定义第一个点
IPoint pPoint1 = new PointClass();
pPoint1.X = 100;
pPoint1.Y = 100;
//定义第二个点
IPoint pPoint2 = new PointClass();
pPoint2.X = 200;
pPoint2.Y = 200;
//创建一个Line对象
ILine pLine= new LineClass();
//设置Line对象的起始终止点
pLine.PutCoords(pPoint1,pPoint2);
//QI到ISegment
ISegment pSegment= pLine as ISegment;
//创建一个Path对象
SegmentCollection pPath= new PathClass();
object o=Type.Missing;
//通过ISegmentCollection接口为Path对象添加Segment对象
pPath.AddSegment(pSegment,ref o,ref o);
//创建一个Polyline对象
IGeometryCollection pPolyline = new PolylineClass();
//通过IGeometryCollection为Polyline对象添加Path对象pPolyline.AddGeometry(pPath as IGeometry, ref o, ref o);
2.4.4.2Polylgon几何对象
2Polylgon对象是由一个或多个Ring对象的有序集合,它可以是由单个Ring 对象构成,也可以使用多个Ring组成如下图所示。其中Ring可以分为Outer Ring(外环)和Inner Ring(内环)之分。外环和内环都是有方向的,它们的区别是外环的方向是顺时针的,内环的方向是逆时针。Polygon通常用来代表有面积的多边形矢量对象,如行政区,建筑物等。
图7
以下代码片段演示如何构建一个Polygon:
//创建一个Ring对象,通过ISegmentCollection接口向其中添加Segment对象
ISegmentCollection pSegCollection = new RingClass();
object o = Type.Missing;
pSegCollection.AddSegment(pSegment1, ref o, ref o);
pSegCollection.AddSegment(pSegment2, ref o, ref o);
//QI到IRing接口封闭Ring对象,使其有效
IRing pRing = pSegCollection as IRing;
pRing.Close();
//使用Ring对象构建Polygon对象
IGeometryCollection pGeometryColl = new PolygonClass();pGeometryColl.AddGeometry(pRing, ref o, ref o);
2.4.5Envelope几何对象
Envelope是所有几何对象的外接矩形,用于表示几何对象的最小边框,所有的几何对象都有一个Envelope对象,IEnvelope是Envelope对象的主要接口,通过它可以获取几何对象的XMax,XMin,YMax,YMin,Height,Width属性。通过IEnvelope的Expand方法还可以按比例缩放Envelope对象的范围,如下图所示:
2.4.6Curve对象几何对象
除去Point,MultiPoint和Envelope外,其他所有的几何体都可以看做是Curve(曲线)。Line,Polyline,Polygon,CircularArc,BezierCurve,EllipticArc和CircularArc都是曲线的一种,它们都实现了ICurve接口。
ICurve接口的Length属性用于返回一个Curve对象的长度。
ICurve接口的FromPoint和ToPoint属性可以获得Curve对象的起止点。
ICurve接口的Reverseorientation方法可以改变一个Curve对象的节点次序即调动Curve对象的起始点和终止点互相调换。
ICurve接口的IsClosed属性则可以判断一个Curve对象起始点和终止点是否在一个位置上。
ICurve接口的GetSubcurve方法可以复制一条Curve对象的特定部分,例如一条10千米公路的Curve对象,获取2-5千米处的公路的曲线代码片段如下所示:
//QI到ICurve接口
ICurve pCurve = pPolyline as ICurve;
//创建一个Polyline对象
ICurve pNewCurve = new PolylineClass();
bool btrue= true;
//获取-5千米间的曲线对象pCurve.GetSubcurve(2, 5, btrue, out pNewCurve);
此外ICurve的QueryTangent和QueryNormal方法分别用于获取Curve对象上某一点的曲线的切线和法线。
2.4.7 Triangle Strip和Trangle Fan, Trangle,Ring几何对象
Triangle Strip和Trangle Fan, Trangle,Ring是构成MultiPatch几何对象的构建对象。
2.4.7.1Triangle Strip几何对象
TriangelStrip对象是由一系列点定义的曲面片组成,而曲面片是有若干个三角形所组成,所以这个曲面可以定义为:(0,1,2) ,(2, 1, 3), (2, 3, 4), (4, 3, 5)。
图9
2.4.7.2Trangle Fan几何对象
一个Trangle Fan对象由一系列点定义的曲面片组成,所不同的是所有的三角形共享一个顶点。如下图所示,所以这个曲面可以定义为:(0,1,2) ,(0,2, 3), (0, 3, 4), (0, 4, 5)。
图10
2.4.7.3Triangle几何对象
Triangle由三个点所确定如下图,一个Triangle可定义为(0,1,2)等。
图11
2.4.7.4Ring几何对象
Ring和前边介绍的组成Polygon的Ring一样,例如下边一个房屋组成它的墙是个OutRing对象,而窗户和门是InnerRing对象。
图12
2.4.8Multipatch几何对象
Multipatch几何对象用于描述3D图形,可以由TriangleStrip, TriangleFan, Triangle和ring对象组合构成组成。Multipatch可以通过多种方式创建,一种是通过导入外部3D格式数据文件(3D Studio Max .3ds files, OpenFlight .flt files, COLLADA .dae files, Sketchup .skp files, VRML .wrl files),另外ArcGIS Engine提供了多种创建Multipatch几何对象的方法:
如果创建没有贴图纹理,没有法向,没有组成部分信息的Multipatch时,只需创建好组成的Multipatch的各个部分即可,然后通过MultiPatch的IGeometryCollection接口添加各个组成部分即可。
如果要为Multipatch每个组成部分添加纹理信息,法向信息,属性信息就必须使用GeneralMultiPatchCreator对象来创建,通过其IGeneralMultiPatchInfo接口来为MultiPatch各个组成部分定义法向,材质,属性信息。通过IGeneralMultiPatchInfo接口可以获取这些MultiPatch的各个组成部分的信息。
通过IConstructMultiPatch接口和IExtrude接口操作GeometryEnvironment对象可以通过拉伸Polyline对象(拉伸为墙)和Polygon对象(拉伸为多面体)来创建MultiPatch.
通过访问3D符号库,获取3DSymbol来渲染点,把三维符号放置在点的位置从而生成Multipatch.
下图为MultiPatch对象的贴图原理:
图13
接下来给大家介绍通过GeneralMultiPatchCreator创建一个有纹理MultiPatch的方法:需要使用以下三个对象:
GeometryMaterial:用于构建材质,通过IGeometryMaterial创建的材质可以作为TextureLineSymbol或者 TextureFillSymbol属性用来创建这些符号,也可以把它添加到GeometryMaterialList对象中,用于GeneralMultipatchCreator对象构建Multipatch对象。
GeometryMaterialList:材质对象的容器用于GeneralMultiPatchCreator对象调用Init方法时使用。
GeneralMultiPatchCreator:用于创建有纹理的贴图的Multipatch.。
以下代码片段演示如何创建一个MultiPatch对象
///
<summary>
///
构建Multipatch几何对象
///
</summary>
///
<returns>返回Multipatch几何对象</returns>
public IMultiPatch CreateMultipatch()
{
try
{
//创建图形材质对象
IGeometryMaterial texture = new GeometryMaterialClass();
texture.TextureImage = @"C:\Temp\MyImage.jpg";
//创建材质列表对象
IGeometryMaterialList materialList = new GeometryMaterialListClass();
//向材质列表添加材质
materialList.AddMaterial(texture);
//创建GeneralMultiPatchCreator对象
IGeneralMultiPatchCreator multiPatchCreator = new GeneralMultiPatchCreatorClass();
multiPatchCreator.Init(4, 1, false, false, false, 4, materialList);
//设置Part:可以使三角扇或环
multiPatchCreator.SetPatchType(0, esriPatchType.esriPatchTypeTriangleStrip);
multiPatchCreator.SetMaterialIndex(0, 0);
multiPatchCreator.SetPatchPointIndex(0, 0);
multiPatchCreator.SetPatchTexturePointIndex(0, 0);
//创建真实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, ref upperRight);
multiPatchCreator.SetWKSPointZ(1, ref lowerRight);
multiPatchCreator.SetWKSPointZ(2, ref upperLeft);
multiPatchCreator.SetWKSPointZ(3, ref lowerLeft);
//设置贴图的点
WKSPoint textureUpperLeft = new WKSPoint();
WKSPoint textureLowerLeft = new WKSPoint();
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);
//创建MultiPatch对象
IMultiPatch multiPatch = multiPatchCreator.CreateMultiPatch() as IMultiPatch;
return multiPatch;
}
catch (Exception Err)
{
MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
2.4.9Geometry集合接口
通过前边对于具体的Geometry对象的介绍可知,除了Point对象之外,其他几何对象都是通过其他几何对象集合构建而成。如MultiPoint对象是点的集合,Path对象是Segment对象的集合,Polyline对象是Path对象的集合,Polygon对象是Ring对象的集合,Multipatch对象是Triangle Strip和Trangle Fan, Trangle,Ring对象的集合。
ArcGIS Engine提供了三个主要的几何图形集合接口用于对几何对象的操作,分别是IPointCollection,ISegmentCollection和IGeometryCollection,这些接口揭示出ArcGIS Engine的几何模型的实质——它们是一种组合构成的模式,这种组合并不一定按照严格的层次结构组织。
在前面介绍一些几何对象的时候,也给大家演示了部分使用功能,这三个接口在程序开发中经常使用到,接下来简单阐述以下这三个接口的使用方法。
2.4.9.1IGeometryCollection接口IGeometryCollection接口被Polygon,Polyline, Multipoint, Multipatch, Trangle,T rangle Strip,Trangle Fan和GeometryBag所实现。IGeometryCollection接口提供的方法可以让开发者对一个几何对象的组成元素即子对象进行添加,改变和移除。例如:
组成Polyline对象的子对象是Path对象。
组成Polygon对象的子对象是Ring对象。
组成Multipoint对象的子对象是Point对象。
组成MultiPatch对象的子对象是TrangleFan TrangleStrip,Triangle或Ring对象。
组成GeometryBag对象的是任何类型的几何体对象,实际上GeometryBag是一个可以容纳任何类型几何对象的容器。
IGeometryCollection的Geometry 属性可以通过一个索引值返回一个组成该几何对象的某个子对象,而GeometryCount返回组成该几何对象的子对象的数目。
IGeometry的AddGeometry和AddGeometries方法都用于向一个几何对象添加子对象,它们的区别是前者一次只能添加一个几何对象,而后者可以一次添加一个几何对象数组。除此之外,AddGeometry方法可以将子对象添加到几何的指定索引值的位置,而AddGeometries方法将子对象数组添加到集合的最后。
在使用AddGeometry方法添加子对象到Polygon对象的过程中,如果子对象即Ring出现覆盖现象,那么多边形就没有封闭或出现了包含关系,那么这个Polygon就不是简单Polygon,因此通过IGometryCollection来创建一个Polygon时,需要使用ITopologicalOperator 的Simplify方法保证其有效性。
通过IGeometryCollection创建一个Polygon对象的代码片段如下:
///
<summary>
///
构造Polygon对象
///
</summary>
///
<param name="pRingList">Ring对象集合</param>
///
<returns>返回一个Polygon对象</returns>
private IPolygon ConstructorPolygon(List<IRing> pRingList)
{
try
{
//创建一个Polygon对象
IGeometryCollection pGCollection = new PolygonClass();
object o = Type.Missing;
//遍历Ring集合
for(int i=0;i<pRingList.Count;i++)
{
//通过IGeometryCollection接口的AddGeometry方法向Polygon对象中添加Ring子对象
pGCollection.AddGeometry(pRingList, ref o, ref o);
}
//QI至ITopologicalOperator
ITopologicalOperator pTopological = pGCollection as ITopologicalOperator;
//执行Simplify操作
pTopological.Simplify();
IPolygon pPolygon=pGCollection as IPolygon;
//返回Polygon对象
return pPolygon;
}
catch (Exception Err)
{
MessageBox.Show(Err.Message,"提示",MessageBoxButtons.OK,,MessageBoxIcon.Information);
return null;
}
}
同样可以通过IGeometryCollection的AddGeometryCollection方法可以将一个Polygon中的所有子对象Ring添加到另外一个多边形中,这样就实现了合并两个多边形对象为一个多边形对象的功能,这非常有用。
以下代码片段演示如何合并两个Polygon对象为一个Polgyone对象:
///
<summary>
///
合并两个Polygon
///
</summary>
///
<param name="firstPolygon">第一个Polygon</param>
///
<param name="SecondPolygon">第二个Polygon</param>
///
<returns>返回合并后的Polygon</returns>
private IPolygon MergePolygons(IPolygon firstPolygon, IPolygon SecondPolygon)
{
try
{
//创建一个Polygon对象
IGeometryCollection pGCollection1=new PolygonClass();
IGeometryCollection pGCollection2 = firstPolygon as IGeometryCollection;
IGeometryCollection pGCollection3 = SecondPolygon as IGeometryCollection;
//添加firstPolygon
pGCollection1.AddGeometryCollection(pGCollection2);
//添加SecondPolygon
pGCollection1.AddGeometryCollection(pGCollection3);
//QI至ITopologicalOperator
ITopologicalOperator pTopological = pGCollection1 as ITopologicalOperator;
//执行Simplify操作
pTopological.Simplify();
IPolygon pPolygon=pGCollection1 as IPolygon;
//返回Polygon对象
return pPolygon;
}
catch (Exception Err)
{
MessageBox.Show(Err.Message,"提示",MessageBoxButtons.OK,,MessageBoxIcon.Information);
return null;
}
}
2.4.9.2ISegmentCollection接口
ISegmentCollection接口被Path,Ring,Polyline和Polygon四个类所实现,它们被称作是Segment集合对象,使用这个接口可以处理组成Segment集合对象中的每一个子Segment对象。使用ISegmentCollection接口可以为一个Segment集合对象添加,插入,删除Segment子对象。ISegmentCollection接口SetCircle和SetRectangle方法提供了一种简单不需要添加Segment的情况下构建一个完成的Path,Ring,Polyline和Polygon的方法。
2.4.9.3IPointCollection接口
IPointCollection可以被多个几何对象类所实现,这些对象都是由多个点构成如:Mullipoint,Path,Ring,Polyline,Polygon,TriangleFan,TrangleStrip,Trangle,Multipatch等,它们都可以称作PointCollection对象,通过IPointCollection接口定义的方法可以获取,添加,插入,查询,移除几何对象中的某个顶点。同以上两个接口一样它也定义了操作一个点集合对象的方法,例如通过AddPoint方法可以向PointCollection对象中的特定索引位添加一个点对象,如果不指定位置,则添加到最后。通过IPointCollection的Point属性通过顶点索引可以得到某一顶点。
在本章节最后的Demo 实例将为大家演示IPointCollection提供的功能。
2.4.10几何对象总结
在Geometry模型中的几何对象分为两种类型,一类是用来直接构建要素类的称为高级几何对象,一类用来构建高级几何对象相对低一级的几何对象成为构建几何对象如下表所示:
几何对象名称
所属类别
构成子几何对象
用于创建和编辑的接口
Polyline
高级
Path
IGeometryCollection,
IPointCollection
Polygon
高级
Ring
IGeometryCollection,
IPointCollection
MultiPoint
高级
Point
IGeometryCollection,
IPointCollection
MultiPatch
高级
TrangleFan,Ring TrangleStrip ,Trangle,
IGeometryCollection,
IPointCollection
Ring
低级
Segment
ISegmentCollection,
IPointCollection
Path
低级
Segment
ISegmentCollection,
IPointCollection
Segment
低级
Point
IPoint,ILine, ICurve
TriangleFan
低级
Point
IGeometryCollection,
IPointCollection
TriangleStrip
低级
Point
IGeometryCollection,
IPointCollection
Triangle
低级
Point
IGeometryCollection,
IPointCollection
Point
高级/低级
无
IPoint
2.5 空间参考
2.5.1空间参考简介
空间参考(Spatial Reference)是GIS数据的骨骼框架,能够将我们的数据定位到相应的位置,为地图中的每一点提供准确的坐标。 在同一个地图上显示的地图数据的空间参考必须是一致的,如果两个图层的空间参考不一致,往往会导致两幅地图无法正确拼合,因此开发一个GIS系统时,为数据选择正确的空间参考非常重要。
ArcGIS Engine提供了一系列对象供开发者管理GIS系统的坐标系统。对大部分开发者而言了解ProjectedCoordinateSystem, GeographicCoordinateSystem, SpatialReference Environment这三个组件类是非常有必要的,对于高级开发者而言,可能需要自定义坐标系统可以使用这些对象Projection,Datum,AngularUnit,Spheriod,PrimeMeridian和GeoTransformation等。
2.5.2修改空间参考
以下代码片段演示了如何改变一个图层的空间参考。
- /// <summary>
- /// 改变图层的空间参考
- /// </summary>
- /// <param name="pFeatureLayer">图层</param>
- /// <param name="pGeoType">空间参考类型</param>
- private void ChangeLayerRef(IFeatureLayer pFeatureLayer, int gcsType)
- {
- try
- {
- IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass;
- //QI到IGeoDataset
- IGeoDataset pGeoDataset = pFeatureClass as IGeoDataset;
- //QI到IGeoDatasetSchemaEdit
- IGeoDatasetSchemaEdit pGeoDatasetSchemaEdit = pGeoDataset as IGeoDatasetSchemaEdit;
- if (pGeoDatasetSchemaEdit.CanAlterSpatialReference == true)
- {
- //创建SpatialReferenceEnvironmentClass对象
- ISpatialReferenceFactory2 pSpaRefFactory = new SpatialReferenceEnvironmentClass();
- //创建地理坐标系对象
- IGeographicCoordinateSystem pNewGeoSys = pSpaRefFactory.CreateGeographicCoordinateSystem(gcsType);//4214代表Beijing1954
- pGeoDatasetSchemaEdit.AlterSpatialReference(pNewGeoSys);
- }
- }
- catch (Exception Err)
- {
- MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
- }
- }
ArcGIS Engine基础开发教程(3)——学习地图和地图布局
转载自: http://bbs.esrichina-bj.cn/ESRI/thread-46577-1-1.html
本章是ArcGIS Engine基础开发教程的第三章,主要给大家大致讲解了,地图和地图布局的相关对象。这些对象非常重要,如果这些基本对象都不熟悉就开始搞ArcGIS Engine开发是不科学的也走不远的。
3地图和地图布局
3.1地图
3.1.1Map对象
Map对象是ArcGIS Engine的主要对象,本章将给大家介绍地图组成结构,如何创建地图,如何对组成地图的对象进行操作,在介绍这些内容时尽量结合ArcMap学习效果会更好。
在Map对象上能显示的图形有两类一类是地理数据,一类是元素。地理数据包括矢量类型的要素数据,栅格数据,Tin等表面数据等,这些数据都保存在Geodatabase或数据文件如shapefile中,它们是用于GIS分析制图的源数据;
而元素是另一种可以显示在Map上的对象,它分为两部分一类是图形元素,一类是框架元素,图形元素可以显示出来,而框架元素充当了“容器”的角色。在ArcMap中可以使用“Draw”工具在Map上直接绘制一个矩形,圆形,文本等对象,在布局视图上也可以给地图添加指北针,图例,比例尺等图形对象,这些都是图形元素。
在ArcMap中Map对象是由MXDocument对象的MapFrame对象管理,MapFrame是一个框架元素。
Map对象有双重身份,一方面是数据的管理容器,可以加载地理数据和图形元素,扮演了数据管理器的角色,另一方面它又可以让用户看到这些数据即扮演了数据显示器的角色,当加载数据到Map对象的时候,Map对象是数据的管理者;当改变视图范围,刷新地图的时候它是数据的显示者。
Map对象主要实现的接口由IMap, IGraphicContainer, IActiveView, IMapBookmarks等接口。
IMap接口主要用于管理Map对象中的Layer对象,要素选择集对象,MapSourround对象,空间参考等对象。
Map对象可以显示图形元素(Graphics Element),Map对象通过IGraphicsContainer接口来管理这些元素对象,包括图形元素和框架元素。IGraphicsContainer返回的是Map对象中处于活动状态的Graphics layer引用指针,它可以是一个Basicgraphicslayer,也可以是CompositeGraphicsLayer中的一个图层,或者是一个FDOGraphicsLayer注记图层。
以下代码片段演示如何添加一个Element到Map上:
- ///
- <summary>
- ///添加临时元素到地图窗口上
- ///</summary>
- ///<param name="pMapCtrl">地图控件</param>
- ///<param name="pEle">单个元素</param>
- ///<param name="pEleColl">元素集合</param>
- public static void AddTempElement(AxMapControl pMapCtrl, IElement pEle, IElementCollection pEleColl)
- {
- try
- {
- IMap pMap = pMapCtrl.Map;
- IGraphicsContainer pGCs = pMap as IGraphicsContainer;
- if (pEle != null)
- pGCs.AddElement(pEle, 0);
- if (pEleColl != null)
- if (pEleColl.Count > 0)
- pGCs.AddElements(pEleColl, 0);
- IActiveView pAV = (IActiveView)pMap;
- //需要刷新才能即时显示
- pAV.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, pAV.Extent);
- }
- catch (Exception Err)
- {
- MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
- }
- }
IActiveView接口定义了Map对象的数据显示功能。使用该接口可以改变视图的范围,刷新视图。
IActiveView的PartialRefresh(esriViewGeography, pLayer, null)用于刷新指定图层:
IActiveView的PartialRefresh(esriViewGeography, null, null) 用于刷新刷新所有图层:
IActiveView的PartialRefresh(esriViewGeoSelection, null, null) 用于刷新所选择的对象:
IActiveView的PartialRefresh(esriViewGraphics, null, null) 用于刷新图形元素:
IActiveView的PartialRefresh(esriViewGraphics, pElement, null) 用于刷新指定图形元素
IActiveView的PartialRefresh(esriViewGraphics, null, null) 用于刷新所有图形元素
IActiveView的PartialRefresh(esriViewGraphicSelection, null, null)用于刷新所选择的图元。
IMapBookmark接口用于管理所有的空间书签对象。
3.1.2图层对象
Map对象可以装载地理数据,这些数据是以图层的形式加载到地图对象上的,图层对象Layer作为一个数据的“中介”存在,它本身没有转载地理数据,而仅仅是获得了数据的引用,用于管理数据源的连接。地理数据始终保存在Geodatabase或者地理数据文件中。
由于地理数据的类型多样,所以Layer类也拥有众多子类(具体查看帮助),接下来主要给大家介绍要素图层—FeatureLayer对象。
3.1.3FeatureLayer对象
FeatureLayer类实现的常用主要接口如下图所示:IFeatureLayer,IFeatureLayerDefinition,FeatureSelection,IGeoDataset,IGeoFeatureLayer,IIdentify,ILayerEffects。
IFeatureLayer接口主要用于设置要素图层的数据源(FeatureClass), IFeatureLayer的DataSourceType获取FeatureLayer对象的数据源类型。此外通过IFeatureLayer的Search方法可以查询要素图层上符号某一条件的要素集。
IGeoFeatureLayer接口继承了ILayer和IFeatureLayer两个接口,用于控制要素图层的符号化和标注等。
IGeoDataset接口仅有两个属性,它们用于管理地理要素集。Extent可以返回当前数据集的范围,是一个IEnvelope类型的对象;
SpatialReference属性则可以让用户获得这个数据集的空间参考。
IFeatureSelection接口提供管理一个图层中的要素的选择集的方法和属性。
以下代码片段演示如何获取要素图层符合条件获取选择集
- /// /// <summary>
- /// 获取要素图层符合条件获取选择集
- /// </summary>
- /// <param name="pFeatureLayer">要素图层</param>
- /// <param name="WhereClause">过滤条件</param>
- /// <returns>返回选择集</returns>
- private IFeatureSelection SelectLayersFeatures(IFeatureLayer pFeatureLayer, string WhereClause)
- {
- IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection;
- if (pFeatureSelection == null) return null;
- IQueryFilter pQueryFilter = new QueryFilterClass();
- pQueryFilter.WhereClause = WhereClause;
- pFeatureSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
- return pFeatureSelection;
- }
IFeatureLayerDefinition接口定义了CreateSelectionLayer方法,可以将一个图层选择集中的要素转换为一个单独的要素图层。
3.1.4矢量图层操作实例
以下代码片段演示按行政区加载图层数据的功能,以此理解IFeatureLayerDefinition的CreateSelectionLayer方法的使用。
比方说整个国土资源部有某一类型专题数据有若干图层,每个图层数据的范围是整个中国,这时国土资源部开发一套系统可能有这个需求,每个省只能加载本省的数据。以下函数即为按按行政区范围创建行政区范围的图层。
比方说我想获取河南省的数据只需传入行政区图层中河南省图元的Geometry即可。另外如果如果遇到行政区层必须用esriSpatialRelEnum. esriSpatialRelContains这个参数,否则行政区这个图层就不能只获取河南这个省份,它会把河南省的周围省份,河北,湖北,安徽,陕西,山东,山西等省份的图元也添加创建到新图层。
- /// <summary>
- /// 按行政区范围创建行政区范围的图层
- /// </summary>
- /// <param name="pFeatureLayer">源数据图层</param>
- /// <param name="pGeometry">行政区范围</param>
- /// <param name="bXZQ">图层是否为行政区</param>
- /// <returns>新创建的图层</returns>
- private IFeatureLayer GetSelectionLayer(IFeatureLayer pFeatureLayer, IGeometry pGeometry,bool bXZQ)
- {
- try
- {
- if (pFeatureLayer != null && pGeometry != null)
- {
- IQueryFilter pQueryFilter;
- ISpatialFilter pSpatialFilter = new SpatialFilterClass();
- IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection;
- pSpatialFilter.GeometryField = pFeatureLayer.FeatureClass.ShapeFieldName;
- pFeatureSelection.Clear();
- if (!bXZQ)
- {
- pSpatialFilter.Geometry = pGeometry;
- pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
- pQueryFilter = pSpatialFilter;
- pFeatureSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
- }
- else
- {
- pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;
- pQueryFilter = pSpatialFilter;
- if(pGeometry is IGeometryCollection)
- {
- for (int i = 0; i < (pGeometry as IGeometryCollection).GeometryCount; i++)
- {
- pSpatialFilter.Geometry = (pGeometry as IGeometryCollection).get_Geometry(i);
- pFeatureSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultAdd, false);
- }
- }
- }
- IFeatureLayerDefinition pFLDefinition = pFeatureLayer as IFeatureLayerDefinition;
- IFeatureLayer pNewFeatureLayer = pFLDefinition.CreateSelectionLayer(pFeatureLayer.Name ,true, null, null);
- pNewFeatureLayer.MaximumScale = pFeatureLayer.MaximumScale;
- pNewFeatureLayer.MinimumScale = pFeatureLayer.MinimumScale;
- pNewFeatureLayer.Selectable = pFeatureLayer.Selectable;
- pNewFeatureLayer.Visible = pFeatureLayer.Visible;
- pNewFeatureLayer.ScaleSymbols = pFeatureLayer.ScaleSymbols;
- return pNewFeatureLayer;
- }
- else
- {
- return null;
- }
- }
- catch (Exception Err)
- {
- MessageBox.Show(Err.Message, "获取SelectionLayer", MessageBoxButtons.OK, MessageBoxIcon.Information);
- return null;
- }
- }
IIdentify接口定义了获得要素图层单个要素的属性的
ILayerFields接口可以直接获取一个要素图层的要素类字段集合
ILayerEffects接口用来设置一个要素图层的透明度,对比度,对比度。以下代码片段演示如何设置要素图层特效:
- /// <summary>
- /// 设置图层特效
- /// </summary>
- /// <param name="pFeatureLayer">要素图层</param>
- /// <param name="brightness">亮度</param>
- /// <param name="contrast">对比度</param>
- /// <param name="transparency">透明度</param>
- private static void SetLayerEffects(IFeatureLayer pFeatureLayer, short brightness, short contrast, short transparency)
- {
- ILayerEffects pLayerEffect = pFeatureLayer as ILayerEffects;
- pLayerEffect.Brightness = brightness;
- pLayerEffect.Contrast = contrast;
- pLayerEffect.Transparency = transparency;
- }
3.2地图布局
3.2.1PageLayout对象
PageLayout用以显示地图数据,并通过对地图数据进行整饰以便对地图打印输出满足不同行业对GIS出图功能的需求。PageLayout和Map这两个对象看起来非常相似,它们都是视图对象,可以显示地图;也都是图形元素的容器,可以容纳图形元素(Graphics Element)。但是所能够保存的图形类型却是有差别的。PageLayout除了保存图形元素外,还可以保存诸如MapFrame的框架元素(Frame Element)。PageLayout控件上的Map对象被PageLayout的MapFrame对象所管理的。
PageLayout类主要实现了IPageLayout接口,它定义了用于修改页面版式(layout)的方法和属性。
IPageLayout的方法ZoomToWhole方法可以让PageLayout以最大尺寸显示;
IPageLayout的ZoomToPercent方法可以按照输入的比例显示;
IPageLayout的ZoomToWidth方法可以让视图显示的范围匹配控件对象的宽度。
IPageLayout的Page属性用以获取Page对象
IPageLayout的RulerSettings属性用以获取RulerSettings对象
IPageLayout的HorizontalSnapGuides和VerticalSnapGuides属性用以获取SnapGuides对象
如下图所示:
3.2.2Page对象
Page对象主要来管理PageLayout对象中的页面,它用来加载地理数据,但不提供分析和查询功能。Page类的主要接口是IPage,它除了用于管理Page的颜色,尺寸和方向,还可以管理边框类型和打印区域等。例如通过IPage的FromID可以直接设置纸张大小类型(A4,A3等)。
3.2.3SnapGrid对象
SnapGrid是PageLayout上用于摆放元素而设置的辅助点如图所示,这些点有规则呈网状排列,便于使用者对其元素,它可以直接通过IPageLayout的SnapGrid属性获得当前PageLayout使用的SnapGrid对象的引用。
SnapGrid类主要实现了ISnapGrid接口用于设置SnapGrid对象的属性,ISnapGrid的HorizontalSpacing 和VerticalSpacing属性用于设置网点之间的水平距离和垂直距离,ISnapGrid的Visible属性决定了这些网点是否可见,Draw方法将用于在Page对象上绘制一个SnapGrid对象。
以下代码片段演示如何在设置PageLayout控件上SnapGrid:
- /// <summary>
- /// 设置PageLayout上SnapGrid
- /// </summary>
- /// <param name="pPageLayout">PangeLayout对象</param>
- private void SetwSnapGridOnPageLayout(IPageLayout pPageLayout)
- {
- if(pPageLayout !=null)
- {
- ISnapGrid pSnapGrid=pPageLayout.SnapGrid;
- pSnapGrid.VerticalSpacing =2;
- pSnapGrid.HorizontalSpacing =2;
- pSnapGrid.IsVisible =true;
- IActiveView pActiveView=pPageLayout as IActiveView;
- pActiveView.Refresh();
- }
- }
3.2.4SnapGuides对象
SnapGuides是为了更好的放置地图而在Pagelayout上设置的辅助线如图所示,SnapGuides分为两种类型一种是水平辅助线通过IPageLayout的HorizontalSnapGuides属性获得,另一种是垂直辅助线通过IPageLayout的VerticalSnapGuides属性获得。每个SnapGuides都管理着一个Guide集合,即不同的类型的辅助线可以同时存在多条。
SnapGuides都实现了ISnapGuides接口,它定义了管理SnapGuide的属性和方法。
ISnapGuides的AreVisible设定SnapGuides是否可见。
ISnapGuides的GuideCount属性返回一个SnapGuides对象中的Guide的个数。而使用
ISnapGuides的Guide属性可以按索引值获得某个具体的Guide对象。
ISnapGuides的AddGuide方法将一个Guide放在指定位置上。
ISnapGuides的RemoveAllGuides和RemoveGuide方法分别可以清楚所有的Guide和按索引值清除Guide.
以下代码片段演示如何为PageLayout对象添加辅助线:
- /// <summary>
- /// 向PageLayout上指定位置添加辅助线
- /// </summary>
- /// <param name="pPageLayout">PageLayout对象</param>
- /// <param name="pPoistion">位置</param>
- /// <param name="bHorizontal">true为水平方向辅助线,False为垂直方向辅助线</param>
- private void AddGuideOnPageLayout(IPageLayout pPageLayout,double pPoistion,bool bHorizontal)
- {
- try
- {
- if(pPageLayout !=null)
- {
- ISnapGuides pSnapGuides=null;
- //如果是水平辅助线
- if(bHorizontal)
- {
- pSnapGuides=pPageLayout.HorizontalSnapGuides;
- }
- //如果是垂直辅助线
- else
- {
- pSnapGuides=pPageLayout.VerticalSnapGuides;
- }
- if(pSnapGuides!=null)
- {
- //向PageLayout上添加辅助线
- pSnapGuides.AddGuide(pPoistion);
- }
- }
- }
- catch(Exception Err)
- {
- MessageBox.Show(Err.Message,"提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
- }
- }
3.2.5RulerSettings对象
标尺对象是为了辅助图形元素的放置而出现在PageLayout对象上方和左方的辅助尺如图所示,通过IPageLayout的RulerSettings属性可以获得PageLayout上的RulerSettings对象.
RulerSettings对象主要实现了IRulerSettings接口它只有一个SmallestDivision属性用于设置RulerSettings对象的最小刻度值属性。
3.2.6Element对象
在Map对象和PageLayout对象显示的数据除了地理数据之外,另一种即为元素数据如下图5所示。
Element是一个非常庞大复杂的对象集合如图6所示,它主要分为两大部分:图形元素(GraphicElement)和框架元素(Frame Element)。
图形元素(GraphicElement)包LineElement, MarkerElement, TextElement, GroupElement, FillshapElement,PictureElement,MultiPatchElement等。它们都是作为图形的形式而存在,在地图视图或者PageLayout视图上时可见的。框架元素(Frame Element)包括MapFrameElement, MapSurroundElement等它们是作为不可见的容器而存在的。
Map对象或者PageLayout对象可以通过IGraphicsContainer接口来管理这些元素,使用IGraphicsContainer接口可以添加,删除和更新位于Map或PageLayout上的元素。使用GroupElement对象还可以将多个元素编组为单个实体来给用户使用。
IElement是所有图形元素(GraphicElement)和框架元素(Frame Element)都实现的接口,通过IElement接口可以确定Element对象的Geometry属性,同时IElment接口也提供了用于查找和绘制元素的方法。Element是个抽象类,在开发中必须明确指定使用的Element的类型。另外IElement和ILineElement, ITextElement等并不是父子关系,后者没有Geometry属性。
3.2.7MapGrid对象
MapGrid是布局视图中的一系列参考线和参考点用来帮助地图使用者快速地确定地图要素的位置如图7中的公里格网,MapGridBorder,MapGridLabel。MapGrid等。MapGrid对象由MapGrids来管理,一个MapGrids可以包含多个MapGrid对象。
MapGrid是一个抽象类,它的子类有MeasuredGrid,IndexGrid,MgrsGrid,Graticule和CustomOverlayGrid五种,这些子类的对象由MapGridFactory对象创建。MapGride对象模型图如图8和图9所示
- /// <summary>
- /// 为PageLayout对象添加格网对象
- /// </summary>
- /// <param name="pPageLayout"></param>
- private void AddMeasuredGridToPageLayout(IPageLayout pPageLayout)
- {
- try
- {
- //获取MapFrame对象
- IActiveView pAcitiveView= pPageLayout as IActiveView;
- IMap pMap = pAcitiveView.FocusMap;
- IGraphicsContainer pGraphicsContainer=pAcitiveView as IGraphicsContainer;
- IMapFrame pMapFrame = pGraphicsContainer.FindFrame(pMap) as IMapFrame;
- IMapGrids pMapGrids = pMapFrame as IMapGrids;
- //创建一个MeasuredGrid对象
- IMeasuredGrid pMeasureGrid = new MeasuredGridClass();
- IMapGrid pMapGrid = pMeasureGrid as IMapGrid;
- pMeasureGrid.FixedOrigin = true;
- pMeasureGrid.Units = pMap.MapUnits;
- pMeasureGrid.XIntervalSize = 1000;
- pMeasureGrid.YIntervalSize = 1000;
- pMeasureGrid.XOrigin = -180;
- pMeasureGrid.YOrigin = -90;
- //设置MeasuredGride投影属性
- IProjectedGrid pProGrid = pMeasureGrid as IProjectedGrid;
- pProGrid.SpatialReference = pMap.SpatialReference;
- pMapGrid.Name = "Measured Grid";
- //创建一个CalibratedMapGridBorder对象并设置为pMapGrid的Border属性
- ICalibratedMapGridBorder pCalibratedBorder = new CalibratedMapGridBorderClass();
- pCalibratedBorder.BackgroundColor = GetRgbColor(255, 255, 255);
- pCalibratedBorder.ForegroundColor = GetRgbColor(0, 0, 0);
- pCalibratedBorder.BorderWidth = 0.1;
- pCalibratedBorder.Interval = 72;
- pCalibratedBorder.Alternating = true;
- pMapGrid.Border = pCalibratedBorder as IMapGridBorder;
- //创建一个FormattedGridLabel对象
- IFormattedGridLabel pFormattedGridLabel = new FormattedGridLabelClass();
- IGridLabel pGridLabel = pFormattedGridLabel as IGridLabel;
- stdole.StdFont pFont = new stdole.StdFont();
- pFont.Name = "Arial";
- pFont.Size = 6;
- pGridLabel.Font = pFont as stdole.IFontDisp; ;
- pGridLabel.Color = GetRgbColor(0, 0, 0);
- pGridLabel.LabelOffset = 4;
- pGridLabel.set_LabelAlignment(esriGridAxisEnum.esriGridAxisLeft, false);
- pGridLabel.set_LabelAlignment(esriGridAxisEnum.esriGridAxisRight, false);
- INumericFormat pNumericFormat = new NumericFormatClass();
- pNumericFormat.AlignmentOption = esriNumericAlignmentEnum.esriAlignRight;
- pNumericFormat.RoundingOption = esriRoundingOptionEnum.esriRoundNumberOfSignificantDigits;
- pNumericFormat.RoundingValue = 0;
- pNumericFormat.ShowPlusSign = false;
- pNumericFormat.ZeroPad = true;
- pFormattedGridLabel.Format = pNumericFormat as INumberFormat;
- //设置pMapGrid的LabelFormat属性
- pMapGrid.LabelFormat = pGridLabel;
- //添加格网
- pMapGrids.AddMapGrid(pMapGrid);
- }
- catch(Exception Err)
- {
- MessageBox.Show(Err.Message,"提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
- }
- }
3.2.8MapSurround对象
MapSurround对象是与一个地图对象关联的用于修饰地图的辅助图形元素对象如图所示。它的形状或内容会随着Map属性的变化而自动改变。如Map视图范围改变后比例尺(ScaleBar)也会自动调整比例,比例尺文本(ScaleBarText)也会相应改变它的比例值。
MapSurround对象由MapSurroundFrame 对象管理,所有的MapSurround对象添加在布局视图上,每一个MapSurround对象可以通过IMap接口的MapSurrounds属性的索引值所获取。也可以通过IMap接口的MapSurroundCount来遍历布局视图上的所有MapSurround对象。
所有的MapSurround对象都实现IMapSurround接口,使用IMapSurround接口的Name属性可以获得MapSurround对象的名称,通过IMapSurround的FitToBound方法可以设置一个MapSurround对象的大小。
同时MapSurround类也实现了IMapSurroundEvents接口,可以用来触发MapSounrround相关事件如:AfterDraw,BeforeDraw,ContensChanged。
下图是MapSurround对象模型
如下代码演示如何为PageLayout添加Legend:
- /// <summary>
- /// 为PageLayout对象添加图例对象
- /// </summary>
- /// <param name="pPageLayout">PageLayout对象</param>
- /// <param name="pEnvelope">图例添加的位置</param>
- private void AddLegendToPageLayout(IPageLayout pPageLayout,IEnvelope pEnvelope)
- {
- try
- {
- IActiveView pActiveView=pPageLayout as IActiveView;
- IMap pMap = pActiveView.FocusMap;
- IGraphicsContainer pGraphicsContainer=pActiveView as IGraphicsContainer;
- IMapFrame pMapFrame = pGraphicsContainer.FindFrame(pMap) as IMapFrame;
- UID pUID = new UID();
- pUID.Value = "{7A3F91E4-B9E3-11d1-8756-0000F8751720}";
- ISymbolBackground pSymbolBackground = new SymbolBackgroundClass();
- IFillSymbol pFillSymbol = new SimpleFillSymbolClass();
- ILineSymbol pLineSymbol = new SimpleLineSymbolClass();
- pFillSymbol.Color = GetRgbColor(255, 255, 255);
- pLineSymbol.Color = GetRgbColor(255, 255, 255);
- pFillSymbol.Outline = pLineSymbol;
- pSymbolBackground.FillSymbol = pFillSymbol;
- IMapSurroundFrame pMapSurroundFrame = pMapFrame.CreateSurroundFrame(pUID, null);
- pMapSurroundFrame.Background = pSymbolBackground;
- IElement pElement = pMapSurroundFrame as IElement;
- pElement.Geometry = pEnvelope;
- IMapSurround pMapSurround = pMapSurroundFrame.MapSurround;
- ILegend pLegend = pMapSurround as ILegend;
- pLegend.ClearItems();
- pLegend.Title = "图例";
- ITextSymbol pTextSymbol = new TextSymbolClass();
- pTextSymbol.Size = 10;
- pTextSymbol.HorizontalAlignment = esriTextHorizontalAlignment.esriTHALeft;
- ILegendItem pLegendItem = null;
- for (int i = 0; i < pActiveView.FocusMap.LayerCount; i++)
- {
- ILayer pLayer = pActiveView.FocusMap.get_Layer(i);
- if (pLayer is IFeatureLayer)
- {
- IFeatureLayer pFLayer = pLayer as IFeatureLayer;
- IFeatureClass pFeatureClass = pFLayer.FeatureClass;
- if (pFeatureClass.FeatureType == esriFeatureType.esriFTAnnotation)
- {
- continue;
- }
- else
- {
- pLegendItem = new HorizontalLegendItemClass();
- pLegendItem.Layer = pLayer;
- pLegendItem.Columns = 1;
- pLegendItem.ShowDescriptions = false;
- pLegendItem.ShowHeading = false;
- pLegendItem.ShowLabels = true;
- pLegendItem.LayerNameSymbol = pTextSymbol;
- pLegend.AddItem(pLegendItem);
- }
- }
- }
- }
- catch(Exception Err)
- {
- }
- }
结果如下图所示:
ArcGIS Engine基础开发教程(4)— 学习图层符号化
转载自:http://bbs.esrichina-bj.cn/ESRI/thread-46784-1-1.html
地图符号不仅具有确定的空间位置以及空间地物的性质:例如在一个城市管线系统中不同的线符号表示不同类型的管线,不同的点符号表示不同类型的设备等等,而且地图符号也可以表达与空间位置相关的丰富信息:例如人口密度符号可以直观的表示人口数量的空间分布情况。所以地图数据的符号化决定着地图以何种“面目”展现给地图的使用者,自此空间数据的符号化对GIS开发有非常重要的意义。
ArcGIS Engine9.3提供了丰富的控件和组件库来实现图层符号化的相关功能。ArcGIS Engine9.3提供了SymbologyControl控件用于显示ArcGIS符号库中的符号(关于ArcGIS符号请查找相关文档),而组件库中的组件对象分为Color , Symbol, Renderer三大系列,图层符号化就是通过多个组件对象来合作完成。
4.1目标
1.熟悉ArcGIS Engine符号化之Color(颜色)体系
2.熟悉ArcGIS Engine符号化之Symbol(符号)体系
3.熟悉ArcGIS Engine符号化之Renderer( 渲染)体系
4.利用ESRI自带的符号库进行符号化图层
4.2准备工作
1.IDE:Visual Studio 2005/2008
2.ArcGIS Engine Developer kit 9.3
3.自造一份用于唯一值符号化的点数据(文章内有说明)
4.3符号化Color(颜色)体系
4.3.1ArcGIS颜色模型
ArcGIS提供Color(颜色)的模型有多种分别是:
-
RGB颜色模型:最常用,所有颜色都是通过红色(Red)、绿色(Green)、蓝色(Blue)这三原色的混合来显示。
-
CMY颜色模型:青(Cyan)、洋红(Magenta)和黄(Yellow)三种颜色的简写,是相减混色模式,用这种方法产生的颜色之所以称为相减色,主要用于印刷中。
-
HSV颜色模型:色彩(H),纯度(S),明度(V)。
-
Gray模型:没有彩色的,灰度图像由8位信息组成,并使用256级的灰色来模拟颜色层次。
-
HLS模型: Hue(色相)、Luminance(亮度)、Saturation(饱和度)。
如上图所示Color对象是一个抽象类,它包括5个子类:它有5个颜色子类,即CmykColor、RGBColor、HSVColor、HLSColor和GrayColor,它们可以使用IColor接口定义的方法设置颜色对象的基本属性。在ArcGIS engine中最常使用的两种颜色模型是RGB和HSV,RGB类实现IRgbColor接口,而HSV类则实现IHsvColor接口,两个接口分别定义了设置一个RGBColor对象和RGBColor对象需传递的值。
接下来以一个函数来通过R,G,B值来构建一个RGBColor对象
private IRgbColor GetRGB(int r,int g,int b)
{
IRgbColor pRgbColor= new RgbColorClass();//构建一个RgbColorClass
pRgbColor.Red = r;//设置Red属性
pRgbColor.Green = g;//设置Green属性pRgbColor.Blue = b;//设置Blue属性
return pRgbColor;
}
4.3.2ColorRamp对象
在地图符号化的过程中,需要的颜色常常不是一种,而是随机或有序产生的一组颜色。如果对某一个图层进行符号化需要上百种颜色如图2所示,程序开发者肯定不能逐个产生出来。ArcGIS Engine提供了ColorRamp对象:
ColorRamp类的对象可以产生颜色带,这个类实现了IColorRamp接口,它定义了一系列颜色带的属性,如 Size(产生多少种颜色),Colors(颜色带 IEnumColor)。
ColorRamp类是一个抽象类,它包括4个子类分别是:RandomColorRamp(随机颜色带)、PresetColorRamp(预设颜色带)、AlgorithmicColorRamp(起止颜色带)、MultiPartColorRamp(叠加颜色带),它们的说明如表一所示。
表一
RandomColorRamp
使用HSV颜色模型来确定一串颜色
PresetColorRamp
预设的颜色模式,可存储13种颜色
AlgorithmicColorRamp
用起始颜色、终止颜色确定一个颜色带,起始、终止颜色使用HSV模型
MultiPartColorRamp
叠加产生颜色带
在GIS应用开发中用到比较多得是RandomColorRamp(随机颜色带)和AlgorithmicColorRamp(起止颜色带)接下来详细介绍一下这两个颜色带。
AlgorithmicColorRamp是通过起止颜色来确定多个在这两个颜色之间的色带。AlgorithmicColorRamp类实现了两个接口:IColorRamp和IAlgorithmicColorRamp,两个接口之间是接口继承关系,后者包含了前者所有的方法和属性。
4.3.3生成颜色带实例
接下来制作一个实例演示AlgorithmicColorRamp(起止颜色带)的Demo:
1.创建一个窗体,在窗体上添加5个Picturebox用于分别显示产生的包含5个颜色的起始颜色带中的颜色,如图3所示
2.在“生成颜色带”Button的Click事件中生成颜色带,代码片段如下所示:
private void button1_Click(object sender, EventArgs e)
{
//创建一个新AlgorithmicColorRampClass对象
IAlgorithmicColorRamp algColorRamp = new AlgorithmicColorRampClass();
//创建起始颜色对象
IRgbColor startColor = new RgbColor();
startColor.Red = 255;
startColor.Green = 0;
startColor.Blue = 0;
//创建终止颜色对象
IRgbColor endColor = new RgbColor();
endColor.Red = 0;
endColor.Green = 255;
endColor.Blue = 0;
//设置AlgorithmicColorRampClass的起止颜色属性
algColorRamp.ToColor = startColor;
algColorRamp.FromColor = endColor;
//设置梯度类型
algColorRamp.Algorithm = esriColorRampAlgorithm.esriCIELabAlgorithm;
//设置颜色带颜色数量
algColorRamp.Size = 5;
//创建颜色带
bool bture = true;
algColorRamp.CreateRamp(out bture);
//使用IEnumColors获取颜色带
IEnumColors pEnumColors = null;
pEnumColors = algColorRamp.Colors;
//设置5个picturebox的背景色为产生颜色带的5个颜色
this.pictureBox1.BackColor = ColorTranslator.FromOle(pEnumColors.Next().RGB);
this.pictureBox2.BackColor = ColorTranslator.FromOle(pEnumColors.Next().RGB);
this.pictureBox3.BackColor = ColorTranslator.FromOle(pEnumColors.Next().RGB);
this.pictureBox4.BackColor = ColorTranslator.FromOle(pEnumColors.Next().RGB);
this.pictureBox5.BackColor = ColorTranslator.FromOle(pEnumColors.Next().RGB);
}
运行点击Button 结果如图4所示:
RandomColorRamp对象产生随机颜色带,RandomColorRamp也需要设定一个范围,但是这个范围是HSV颜色模型的,颜色将在这个范围内随机出现。 RandomColorRamp类实现了IRandomColorRamp接口
以下是生成RandomColorRamp的代码片段
IRandomColorRamp pRandomColorRamp = new RandomColorRampClass();
//** 制作一系列介于橘黄色和蓝绿色之间的随机颜色
pRandomColorRamp.StartHue = 40;
pRandomColorRamp.EndHue = 120;
pRandomColorRamp.MinValue = 65;
pRandomColorRamp.MaxValue = 90;
pRandomColorRamp.MinSaturation = 25;
pRandomColorRamp.MaxSaturation = 45;
pRandomColorRamp.Size = 20;
pRandomColorRamp.Seed = 23;
bool bture = true;
pRandomColorRamp.CreateRamp(out bture);
IEnumColors pEnumColors = pRandomColorRamp.Colors
//** 对pEnumColors进行操作
4.4符号化Symbol(符号)体系
ArcGIS Engine9.3为开发人员提供了32种符号,主要分为三大类符号MarkerSymbol(点符号)、 LineSymbol(线符号)和FillSymbol(填充符号)来绘制地理要素的几何图形。此外还有两种特殊类型的符号:一种是TextSymbol用于文字标注;另一种是3D Chart符号,用于显示饼图等三维对象,如需详细了解请查找帮助文档。
4.4.1MarkerSymbol对象
MarkerSymbol用于修饰点对象的符号,它拥有十三个子类如表2所示,其中不同的子类可以产生不同类型的点符号。所有的MarkerSymbol类都实现了IMarkerSymbol接口,这个接口定义了标记符号的公共方法和属性,如角度、颜色、大小和X,Y偏移量等。
表二
点符号类型
描述
ArrowMarkerSymbol
预定义的肩头符号
BarChartSymbol
柱状图符号
CharacterMarker3DSymbol
三维字体符号
CharacterMarkerSymbol
字体符号
Marker3DSymbol
3D 符号
MultiLayerMarkerSymbol
多个符号叠加产生新点符号
PictureMarkerSymbol
图片符号(bmp或emf)
PiechartSymbol
饼图符号
SimpleMarker3DSymbol
简单3D符号
SimpleMarkerSymbol
简单符号
StackedChartSymbol
堆叠符号
TextMarkerSymbol
文字符号用来符号化点
常用的有以下5种 类型:
如何创建MarkerSymbol?接下来以SimpleMarkerSymbol构建为例演示如何创建一个点符号:
//创建SimpleMarkerSymbolClass对象
ISimpleMarkerSymbol pSimpleMarkerSymbol = new SimpleMarkerSymbolClass();
//创建RgbColorClass对象为pSimpleMarkerSymbol设置颜色
IRgbColor pRgbColor = new RgbColorClass();
pRgbColor.Red = 255;
pSimpleMarkerSymbol.Color = pRgbColor as IColor;
//设置pSimpleMarkerSymbol对象的符号类型,选择钻石
pSimpleMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSDiamond;
//设置pSimpleMarkerSymbol对象大小,设置为5
pSimpleMarkerSymbol.Size = 5;
//显示外框线
pSimpleMarkerSymbol.Outline = true;
//为外框线设置颜色
IRgbColor pLineRgbColor = new RgbColorClass();
pLineRgbColor.Green = 255;
pSimpleMarkerSymbol.OutlineColor = pLineRgbColor as IColor;
//设置外框线的宽度
pSimpleMarkerSymbol.OutlineSize = 1;
如何使用这个符号,在接下来介绍Renderer对象的时候将为大家演示如何用创建的点符号去符号化一个图层。
4.4.2LineSymbol对象
LineSymbol对象是用于修饰线型几何对象的符号,它拥有八个子类如表3所示,其中不同的子类可以产生不同类型的线符号,所有的LineSymbol类都实现了ILineSymbol接口, ILineSymbol定义了两个公共属性:Color和Width。
表三
线符号类型
描述
CartographicLineSymbol
实心或者虚线线符号
HashLineSymbol
离散线符号
MarkerLineSymbol
点线符号
MultiLayerLineSymbol
多符号叠加产生新线符号
PictureLineSymbol
图片线符号
SimpleLine3DSymbol
3D 线符号
SimpleLineSymbol
预定义风格的线符号
TextureLineSymbol (3DAnalyst)
纹理贴 图线符号
常用的LineSymbol如下图所示:
如何创建LineSymbol?接下来以MarkerLineSymbol构建为例演示如何创建一个线符号:
IArrowMarkerSymbol pArrowMarker = new ArrowMarkerSymbolClass();
IRgbColor pRgbColor = new RgbColorClass();
pRgbColor.Red = 255;
pArrowMarker.Color = pRgbColor as IColor;
pArrowMarker.Length = 10;
pArrowMarker.Width = 8;
pArrowMarker.Style = esriArrowMarkerStyle.esriAMSPlain;
IMarkerLineSymbol pMarkerLine = new MarkerLineSymbolClass();
pMarkerLine.MarkerSymbol = arrowMarker;
IRgbColor pLineColor = new RgbColorClass();
pLineColor.Blue = 255;
pMarkerLine.Color = pLineColor as IColor;
4.4.3FillSymbol对象
FillSymbol是用来修饰如多边形等具有面积的几何形体的符号对象,它拥有十一个子类如表4所示它实现了IFillSymbol,这个接口定义了两个属性Color和OutLine,以满足所有类型的FillSymbol对象的公共属性设置。
表四
填充符号类型
描述
ColorRampSymbol (Carto)
用于渲染Raster数据的颜色带
ColorSymbol (Carto)
用于渲染Raster数据的颜色符号
DotDensityFillSymbol
点密度填充符号
GradientFillSymbol
渐变填充符号
LineFillSymbol
包含线符号的填充符号
MarkerFillSymbol
包含点符号的填充符号
MultiLayerFillSymbol
多符号叠加产生新填充符号
PictureFillSymbol
图片填充符号
RasterRGBSymbol
用于渲染Raster数据 RGBSymbol
SimpleFillSymbol
简单填充符号
TextureFillSymbol
纹理贴图填充符号
常用的FillSymbol如下图所示:
如何创建FillSymbol?接下来以MarkerLineSymbol构建为例演示如何创建一个线符号:
//为填充符号创建外框线符号
IColor pLineColor = new RgbColorClass();
ICartographicLineSymbol pCartoLineSymbol = new CartographicLineSymbolClass();
pCartoLineSymbol.Width = 2;
pCartoLineSymbol.Color = pLineColor;
//创建一个填充符号
ISimpleFillSymbol pSmplFillSymbol = new SimpleFillSymbol();
//设置填充符号的属性
IColor pRgbClr = new RgbColorClass();
IFillSymbol pFillSymbol = pSmplFillSymbol;
pFillSymbol.Color = pRgbClr;
pFillSymbol.Outline = pCartoLineSymbol;
如果没有ArcGIS Desktop使用经验的开发看了以上代码片段会一头雾水,不明白填充符号的创建为什么还要创建线符号等等,如果有ArcGIS Desktop使用经验就会非常容易理解这些符号的创建的机制,如图8是SimpleFillSymbol设置信息。所以熟悉ArcGIS Desktop的使用对开发人员进行ArcGIS Engine开发非常有用。
4.4.4TextSymbol对象
TextSymbol对象是用于修饰文字元素的,文字元素在要素标注等方面很有用处。TextSymbol符号最重要的设置对象是它的字符,它实现了三个主要的接口来设置字符:ITextSymbol 、 ISimpleTextSymbol 和 IFormattedTextSymbol 。
ITextSymbol接口是定义文本字符样式的主要接口,它定义的ITextSymbol::Font属性是产生一个TextSymbol符号的关键。可以使用IFontDisp接口来设置字体的大小和是否是粗体、倾斜等属性。使用ITextSymbol接口还可以定义TextSymbol对象的颜色、角度、水平排列方式、垂直排列方式和文本等内容。
以下是一个构建TextSymbol的函数:
///<summary>
///生成文本符号
///</summary>
///<param name="pTxtSymbol">文本符号</param>
///<param name="sFontName">字体名称</param>
///<param name="iFont">字体大小</param>
///<param name="iColor">字体颜色</param>
public static void MakeTextSymbol(ref ITextSymbol pTxtSymbol, string sFontName, int iFont, int iColor)
{
try
{
pTxtSymbol.Font.Name = sFontName;
pTxtSymbol.Font.Size = (decimal)iFont;
IRgbColor pRGBColor = new RgbColorClass();
pRGBColor.RGB = iColor;
pTxtSymbol.Color = (IColor)pRGBColor;
pTxtSymbol.Angle = 0;
pTxtSymbol.RightToLeft = false;
pTxtSymbol.HorizontalAlignment = esriTextHorizontalAlignment.esriTHACenter;
pTxtSymbol.VerticalAlignment = esriTextVerticalAlignment.esriTVABaseline;
}
catch (Exception Err)
{
MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
4.4.5 3DChartSymbol对象
3DChartSymbol是一个抽象类,它拥有三个子类:BarChart、PieChart和StackedChart。如图9所示:
BarChartSymbol是最常用的三维着色符号,它使用不同类型的柱子来代表一个要素类中不同的属性,而柱子的高度取决于属性值的大小。
PieChartSymbol符号进行着色的方法是使用一个饼图来显示不同要素类中的不同属性,不同的属性按照它们的数值大小占有一个饼图中的不同比例的扇形区域。
PieChartSymbol符号进行着色的方法是使用一个饼图来显示不同要素类中的不同属性,不同的属性按照它们的数值大小占有一个饼图中的不同比例的扇形区域。
至于如何创建这些3DChartSymbol符号这里不再提供代码片段演示,读者可以根据前边学习的知识,自己操作ArcGIS Desktop使用3DChartSymbol制作专题图,然后根据ArcGIS Engine的帮助文档开发创建3DChartSymbol。
4.5使用ServerStyle
如果熟悉ArcGIS Desktop的使用,就会对Style符号库文件有所了解,相对应的在ArcGIS Engine开发中对应的是ServerStyle符号库,它的结构体系如图10所示。可以通过专门的转换程序把ArcGIS Desktop Style符号库转换为ArcGIS Engine所能够使用的ServerStyle符号库。
用于获取ServerStyle符号库中的符号主要涉及到以下接口如表所示:
表
接口名称
功能描述
IStyleGallery
用于管理Style Gallery
IStyleGalleryStorage
管理Style Gallery中的符号库文件
IStyleGalleryClass
控制符号库中Style Gallery Class
IEnumStyleGalleryItem
枚举一组Style Gallery items
IStyleGalleryItem
定义Style Galle ry itme
4.5.1获取符号库中符号
如何获取到一个符号库中符号?接下来以获取ESRI符号库中名称为Rose的符号的流程:
1.首先构建一个ServerStyleGallery对象
2.其次使用IStyleGalleryStorage接口的AddFile方法加载ServerStyle文件
3.遍历ServerGallery中的Class,如果是FillSymbol使用IStyleGallery的GetItems方法返回一个可枚举的包含一系列StyleGalleryItem的EnumStyleGalleryItem对象。
4.遍历EnumServerStyleGalleryItme枚举对象中的StylegalleryItme如果名称是Rose即可获取ESRI符号库中名称为Rose的StylegalleryItme,然后通过IStyleGalleryItem的Item属性即可转换为ISymbol。
整个流程图如图11所示:
4.6SymbologyControl控件
SymbologyControl用来显示ServerStyle符号库中的符号样式,可以选择在该控件上选择一个符号用来符号化一个图层或者作为一个Element的符号。使用SymbologyControl可以再设计的模式下在其属性页中加载ServerStyle符号库文件,同样也可以使用的LoadStyleFile和RemoveFile方法加载和移除Serverstyle符号库文件。运行效果如图12所示:
4.7符号化之Renderer( 渲染)体系
ArcGIS Engine9.3对GIS数据的符号化分为矢量数据渲染和栅格数据渲染两大类。接下来分别介绍FeatureRender和RasterRender。
4.7.1FeatureRender对象
FeatureRenderer是一个抽象类,它有15个子类负责进行不同类型的着色运算。它们都实现了IFeatureRenderer接口,这个接口定义了进行要素图层符号化的公共属性和方法。
可以通过IGeoFeatureLayer::Renderer属性获得一个要素图层的符号化对象
表四
要素符号化类型
描述
SimpleRender
简单符号化
UniqueValueRender
唯一值符号化
BiUniqueValueRender
双变量唯一值符号化
ChartRender
图表符号化
ClassBreaksRenderer
分类等级符号化
DotDensityRenderer
点密度符号化
ProportionalSymbolRenderer
根据属性值设置符号大小进行符号化
ScaleDependentRenderer
依比例尺符号化
RepresentationRenderer
制图表达符号化
CoTrackSymbologyRenderer(TrackingAnalyst)
轨迹符号化(应用于TrackingAnaylyst扩展模块)
EnhancedInfoRenderder(TrackingAnalyst)
增强信息符号化(应用于TrackingAnaylyst扩展模块)
UniqueValueTextRenderer(TrackingAnalyst)
唯一值文本符号化(应用于TrackingAnaylyst扩展模块)
NAStopRenderer(NetworkAnalyst)
停止符号化(应用于网络分析扩展模块)
FeatureVertexRenderer(SurveyExt)
要素定点符号化(应用于测量分析扩展模块)
SharedEdgeRenderer(EditorExt)
用于绘制拓扑元素
常用的要素符号化类型主要有以下6种类型,如图13所示:
由于篇幅有限不再对每一种符号化类型的使用进行讲解,在后边的实例中将为读者演示如何进行唯一值符号化。
4.7.2RasterRender对象
RasterRender是一个抽象类,它有15个子类负责进行不同类型的着色运算。它们都实现了IRasterRender接口,这个接口定义了栅格图层符号化的公共属性和方法。可以通过IRasterLayer::Renderer属性获得一个栅格图层的符号化对象。
要素符号化类型
描述
RasterRGBRenderer
栅格RGB符号化
RasterUniqueValueRenderer
唯一值符号化
RasterColormapRenderer
双变量唯一值符号化
RasterClassifyColorRampRenderer
图表符号化
RasterStretchColorRampRenderer
分类等级符号化
RasterDiscreteColorRenderer
点密度 符号化
栅格符号化类型结构图如图14所示:
以下代码片段是对一个RasterLayer进行RasterStretchColorRampRenderer符号化操作:
///<summary>
/// StretchColorRamp符号化RasterLayer
///</summary>
///<param name="pRasterLayer">RasterLayer</param>
public void SetStretchColorRampRenderer(IRasterLayer pRasterLayer)
{
try
{
//创建RasterStretchColorRampRendererClass对象
IRasterStretchColorRampRenderer pRStretchRender= new RasterStretchColorRampRendererClass();
//QI到IRasterRenderer
IRasterRenderer pRasterRender=pRStretchRender as IRasterRenderer;
pRasterRender.Raster = pRasterLayer as IRaster;
pRasterRender.Update();
//创建两个起始颜色
IRgbColor pFromRgbColor = new RgbColorClass();
pFromRgbColor.Red = 255;
IRgbColor pToRgbColor = new RgbColorClass();
pToRgbColor.Blue = 255;
//创建起止颜色带
IAlgorithmicColorRamp pAlgorithmicColorRamp = new AlgorithmicColorRampClass();
pAlgorithmicColorRamp.Size = 255;
pAlgorithmicColorRamp.FromColor = pFromRgbColor as IColor;
pAlgorithmicColorRamp.ToColor = pToRgbColor as IColor;
bool btrue= true;
pAlgorithmicColorRamp.CreateRamp(out btrue);
//选择拉伸颜色带符号化的波段
pRStretchRender.BandIndex = 0;
//设置拉伸颜色带符号化所采用的颜色带
pRStretchRender.ColorRamp = pAlgorithmicColorRamp as IColorRamp;
pRasterRender.Update();
//符号化RasterLayer
pRasterLayer.Renderer = pRasterRender;
}
catch(Exception Err)
{
MessageBox.Show(Err.Message,"提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
}
}
转载自: http://bbs.esrichina-bj.cn/ESRI/thread-46784-1-1.html
4.8利用ESRI自带的符号库进行唯一值符号化一图层开发实例
4.8.1目的
学会开发唯一值符号化要素图层功能
4.8.2步骤
1.准备点数据,添加属性字段“类别”;
2.并为要素“类别”属性值分别设置为“Hospital2”,“School 1”,“Airport”三种属性值。
3.实现唯一值符号化功能
4.运行程序实现效果
4.8.3功能开发
实现唯一值符号化功能代码如下:
///<summary>
///获取符号库中符号
///</summary>
///<param name="sServerStylePath">符号库全路径名称</param>
///<param name="sGalleryClassName">GalleryClass名称</param>
///<param name="symbolName">符号名称</param>
///<returns>符号</returns>
private ISymbol GetSymbol(string sServerStylePath, string sGalleryClassName, string symbolName)
{
try
{
//ServerStyleGallery对象
IStyleGallery pStyleGaller = new ServerStyleGalleryClass();
IStyleGalleryStorage pStyleGalleryStorage = pStyleGaller as IStyleGalleryStorage;
IEnumStyleGalleryItem pEnumSyleGalleryItem=null;
IStyleGalleryItem pStyleGallerItem = null;
IStyleGalleryClass pStyleGalleryClass = null;
//使用IStyleGalleryStorage接口的AddFile方法加载ServerStyle文件
pStyleGalleryStorage.AddFile(sServerStylePath);
//遍历ServerGallery中的Class
for (int i = 0; i < pStyleGaller.ClassCount; i++)
{
pStyleGalleryClass = pStyleGaller.get_Class(i);
if (pStyleGalleryClass.Name != sGalleryClassName)
continue;
//获取EnumStyleGalleryItem对象
pEnumSyleGalleryItem = pStyleGaller.get_Items(sGalleryClassName, sServerStylePath, "");
pEnumSyleGalleryItem.Reset();
//遍历pEnumSyleGalleryItem
pStyleGallerItem = pEnumSyleGalleryItem.Next();
while (pStyleGallerItem != null)
{
if (pStyleGallerItem.Name == symbolName)
{
//获取符号
ISymbol pSymbol = pStyleGallerItem.Item as ISymbol;
System.Runtime.InteropServices.Marshal.ReleaseComObject(pEnumSyleGalleryItem);
System.Runtime.InteropServices.Marshal.ReleaseComObject(pStyleGalleryClass);
return pSymbol;
}
pStyleGallerItem = pEnumSyleGalleryItem.Next();
}
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(pEnumSyleGalleryItem);
System.Runtime.InteropServices.Marshal.ReleaseComObject(pStyleGalleryClass);
return null;
}
catch (Exception Err)
{
MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
}
///<summary>
///设置要素图层唯一值符号化
///</summary>
///<param name="pFeatureLayer"></param>
private void UniqueValueRenderFlyr(IFeatureLayer pFeatureLayer)
{
try
{
//创建UniqueValueRendererClass对象
IUniqueValueRenderer pUVRender = new UniqueValueRendererClass();
List<string> pFieldValues= new List<string>();
pFieldValues.Add("Hospital 2");
pFieldValues.Add("School 1");
pFieldValues.Add("Airport");
for(int i=0;i<pFieldValues.Count;i++)
{
ISymbol pSymbol= new SimpleMarkerSymbolClass();
pSymbol =GetSymbol(@"C:\Program Files\ArcGIS\Styles\ESRI.ServerStyle","Marker Symbols",pFieldValues【i】);
//添加唯一值符号化字段值和相对应的符号
pUVRender.AddValue(pFieldValues,pFieldValues,pSymbol);
}
//设置唯一值符号化的字段个数和字段名
pUVRender.FieldCount = 1;
pUVRender.set_Field(0, "类别");
IGeoFeatureLayer pGFeatureLyr = pFeatureLayer as IGeoFeatureLayer;
//设置IGeofeatureLayer的Renderer属性
pGFeatureLyr.Renderer = pUVRender as IFeatureRenderer;
}
catch (Exception Err)
{
MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void button1_Click(object sender, EventArgs e)
{
IFeatureLayer pFeatureLayer = this.axMapControl1.get_Layer(0) as IFeatureLayer;
UniqueValueRenderFlyr(pFeatureLayer);
this.axMapControl1.Refresh();
}
4.9设计GIS系统符号化模块
大家首先有个观念:用ArcEngine开发C/S应用程序时,一个成熟的GIS项目在加载数据这方面是不允许直接把SDE里边的数据以MXD的形式组织起来这是不科学的,原因如下:
1.从数据安全性考虑
一个MXD文档包含了SDE数据库里与MXD数据的详细信息,通常对于数据拥有者来说是不希望外部能够获取这些信息的。
2.从系统灵活性考虑
通过程序动态加载所需同层,动态符号化相关图层能够为程序带来很大的灵活性,例如根据不同的用户的权限从数据库加载不同的数据,符号化不同的图层等等。习惯直接在MapControl上Load MXD File的就会有疑问,不通过MXD怎么展现图层的符号化。
接下来我将从两种途径给大家介绍一下如果动态符号化图层:
使用ArcEngine开发C/S应用程序数据加载一个重要的功能模块,在数据加载模块符号图层是其技术核心之一:
4.9.1通过系统符号化配置表存储图层符号化信息符号化图层。
首先在关系型数据库中创建一个图层符号化配置表详细记录每一个图层的符号化信息,如下表(我只列出简单符号化的配置表设计,至于唯一值等大家可以自己根据需求设计):
图层ID
符号化类型
符号库ID
符号名称
符号类型
点图层1
简单符号化
1
火车站
点
线图层1
简单符号化
2
铁路线
线
面图层1
简单符号化
3
绿色面
面
然后使用ArcEngine提供的每种符号化类型的接口对图层进行符号化渲染。
4.9.2通过ArcEngine提供的Represatation存储要素符号化
Representation是ArcGIS9.3的新特性,能够通过Representation制作更精美,更复杂的地图操作过程,下图是ArcGIS Desktop中Repre sentation工具条。
通过一下操作可以把通过Representation工具条制作出来的地图效果存储在要素类中(只能是Geodat abase类型的)。
从以上可以看出每一个要素的符号化信息都以Blob方式存储在相对应的数据表中,这样就不需要通过配置表的设置进行动态符号化,直接通过Engine中提供的与Representation相关的接口和类符号化每一个图层。
转载自: http://bbs.esrichina-bj.cn/ESRI/thread-47411-1-1.html
地图查询
地图查询、统计是一个GIS系统的基本的功能模块,实际上统计功能的前提也是通过查询获取结果以文字或者图表等报表的形式展现查询结果数据。
地图查询有两种类型的查询:
1.空间查询:在地图上设置一定范围,查询这一范围内的要素。例如在地图上画一范围查询这一区域内的所有消防栓,这一范围的所有消防栓高亮显示(或者其他显示方式)并展现出所有的消防栓的属性信息。
2.属性查询:通过一定的查询条件获取目标要素。例如我们需要查询中国行政区上人口大于5000万,同时GDP大于1万亿的省份,通过执行查询,符号条件的省份高亮显示(或者其他显示方式)并展现出这些省份的属性信息。
ArcGIS Engine9.3为开发者提供了无需写代码即可进行查询功能的Identify工具,但是这个工具是一个通用的信息查询新工具。而开发者通常需要自己开发一套符合自己业务需求更加灵活的查询功能模块,甚至一些功能不仅仅是查询信息,很多编辑编辑功能以及和业务相结合的功能开发都用到查询功能。所以很有必要了解ArcGIS Engine的查询机制。
5.1目标
1.熟悉Cursor,FeatureCursor对象,使用IFeatureCursor接口
2.熟悉QueryFilter, SpatialFilter对象使用IQueryFilter,ISpatialFilter接口
3.熟悉要素选择集SelectionSet对象,会使用IFeatureSelection,ISelectionSet接口
4.开发一个属性查询小功能Demo, 获取符号查询条件的Feature,并IFeatureLayerDefinition接口创建一个新的要素图层加载到Mapcontrol上
5.开发一个空间多边形查询功能的小Demo, 学会创建内存半透明图层用于显示选择范围
5.2准备工作
1.IDE:Visual Studio 2005/2008
2.ArcGIS Engine Developer kit 9.3
3.准备一份用于查询的的矢量数据(文章内有说明)
5.3Cursor对象
Cursor(游标)本质上是一个指向数据的指针,本身并不包含数据内容,它是连接到Row对象或要素对象的桥梁。
游标有三种类型,即查询游标、插入游标和更新游标。每一种游标都是通过与之相适应的方法来获得的,如Search、Insert和Update方法。更新和插入游标都需要使用一个过滤器(Filter)对象,因为它们首先必须获得需要进行操作的要素。
Cursor对象支持的接口是ICursor,它定义了操作一个Row集合或一个Row对象的属性和方法,下面是获得插入型、更新型和查询型游标的方法:
pCursor = IFeatureClass.Insert()
使用IFeatureClass的Insert方法返回一个插入型游标,它通常用于往表中插入一条记录。
pCursor = IFeatureClass.Update()
使用IFeatureClass的Update方法会返回一个更新型游标,它用于更新或者删除一条记录。
pCursor= IFeatureClass.Search()
使用IFeatureClass的Sarch方法对表进行查询后,可以得到一个查询型Cursor对象,它指向一个或多个Row对象。
以我们这章的内容主要使用查询游标。
FeatureCursor是Cursor的一个子类,指向一个或多个要素,它实现了IFeatureCursor接口,ArcGIS Engine开发所对矢量图层实现查询功能都是实行IFeatureCursor。
5.4QueryFilter对象与SpatialFilter对象
在关系型数据库中,查询条件是通过SQL语句的Where子语句来完成的。在ArcGIS Engine中不能直接使用SQL语句,但ArcGIS Engine提供了QueryFilter和SpatialFilter两个过滤器对象来配合完成查询条件的设置,从而查询到想要的数据。
QueryFilter过滤器主要用于对属性数据查询条件的设置,它主要实现IQueryFilter接口从而实现属性查询功能。
- IQueryFilter pQueryFilter = new QueryFilterClass();
- //设置过滤器对象的属性
- pQueryFilter.WhereClause = "人口> 10000000";
复制代码
SpatialFilter过滤器主要用于空间范围查询条件的设置,它主要实现ISpatialFilter(继承 IQueryFilter接口)接口从而实现空间查询功能。
- ISpatialFilter pSpatialFilter = new SpatialFilterClass();
- //设置空间过滤器的范围(多边形)
- pSpatialFilter.Geometry = pGeometry;
- //设置空间过滤器空间关系类型
- pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;
复制代码
空间过滤器空间关系类型主要有以下几种类型如表一所示:
表1
空间过滤器空间关系类型
描述(A是待查询图形,B是过滤条件图形)
esriSpatialRelUndefined
未定义
esriSpatialRelIntersects
A与B图形相交
esriSpatialRelEnvelopeIntersects
A的Envelope和B的Envelope相交
esriSpatialRelIndexIntersects
A与B索引相交
esriSpatialRelTouches
A与B边界相接
esriSpatialRelOverlaps
A与B相叠加
esriSpatialRelCrosses
A与B相交(两条线相交于一点,一条线和一个面相交)
esriSpatialRelWithin
A在B内
esriSpatialRelContains
A包含B
esriSpatialRelRelation
A与B空间关联
5.5SelectionSet要素选择集对象
熟悉ArcGIS Desktop使用的开发者一定会知道当在ArcMap中显示查询结果的时,所有的符号查询调教的要素都以蓝色高亮的形式显示在地图控件上,蓝色高亮显示表示高亮选中,这些高亮显示选中的要素对应一个要素选择集对象中。通过IFeatureSelection的SelectionSet属性可以获取选择集,FeatureLayer对象实现了IFeatureSelection接口。
实现代码如下:
IFeatureLayer pFeatureLayer = this.axMapControl1.get_Layer(0) as IFeatureLayer;
//QI至IFeatureSelection
IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection;
//创建过滤器
IQueryFilter pQueryFilter = new QueryFilterClass();
//设置过滤器对象的查询条件
pQueryFilter.WhereClause = "人口> 10000000";
//选择要素
pFeatureSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew,false);
//获取选择集对象
ISelectionSet pSelectinSet=pFeatureSelection.SelectionSet;
//设置选择集的符号
pFeatureSelection.SelectionSymbol = pSymbol;
5.6属性查询实例
5.6.1程序实现目标:
查询人口大于5000000的城市,并把查询结果创建为一个新的图层,如图1-3所示:
代码片段如下:
- private void button1_Click(object sender, EventArgs e)
- {
- IFeatureLayer pFeatureLayer = this.axMapControl1.get_Layer(0) as IFeatureLayer;
- //QI到FeatureSelection
- IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection;
- //创建过滤器
- IQueryFilter pQueryFilter = new QueryFilterClass();
- //设置过滤器对象的查询条件
- pQueryFilter.WhereClause = "人口> 5000000";
- //根据查询条件选择要素
- pFeatureSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
- //QI到ISelectionSet
- ISelectionSet pSelectionSet = pFeatureSelection.SelectionSet;
- if (pSelectionSet.Count > 0)
- {
- IFeatureLayerDefinition pFDefinition = pFeatureLayer as IFeatureLayerDefinition;
- //创建新图层
- IFeatureLayer pNewFeatureLayer = pFDefinition.CreateSelectionLayer("newlayerName", true, null, null);
- pNewFeatureLayer.Name = "查询结果城市";
- axMapControl1.AddLayer(pNewFeatureLayer as ILayer);
- }
- }
ArcGIS Engine基础开发教程(5)下——学习地图查询
- 5.7空间查询实例
- 5.7.1目标
- 实现多边形查询功能
- 5.7.2功能开发
- 代码片段如下:
- 引用的命名空间:
- [code]
- using System;
- using System.Drawing;
- using System.Collections;
- using System.ComponentModel;
- using System.Windows.Forms;
- using System.Data;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Collections.Generic;
- using ESRI.ArcGIS.esriSystem;
- using ESRI.ArcGIS.Carto;
- using ESRI.ArcGIS.Controls;
- using ESRI.ArcGIS.ADF;
- using ESRI.ArcGIS.SystemUI;
- using ESRI.ArcGIS.Display;
- using ESRI.ArcGIS.Geodatabase;
- using ESRI.ArcGIS.Geometry;
- using ESRI.ArcGIS.DataSourcesGDB;
- ///<summary>///
- 在程序运行时的内存中创建矢量要素层,并加到地图控件最顶端
- ///</summary> ///
- <param name="pMapCtrl">地图控件</param>
- ///<returns>IFeatureLayer 新加的要素层</returns>
- private IFeatureLayer AddFeatureLayerByMemoryWS(AxMapControl pMapCtrl,ISpatialReference pSReference)
- {
- try
- {
- if (pMapCtrl == null) return null;
- #region
- 创建新的内存工作空间
- IWorkspaceFactory pWSF = new InMemoryWorkspaceFactoryClass();
- IWorkspaceName pWSName = pWSF.Create("", "Temp", null, 0);
- IName pName = (IName)pWSName;
- IWorkspace pMemoryWS = (IWorkspace)pName.Open();
- #endregion
- IField oField = new FieldClass();
- IFields oFields = new FieldsClass();
- IFieldsEdit oFieldsEdit = null;
- IFieldEdit oFieldEdit = null;
- IFeatureClass oFeatureClass = null;
- IFeatureLayer oFeatureLayer = null;
- try
- {
- FieldsEdit = oFields as IFieldsEdit;
- oFieldEdit = oField as IFieldEdit;
- oFieldEdit.Name_2 = "OBJECTID";
- oFieldEdit.Type_2 = esriFieldType.esriFieldTypeOID;
- oFieldEdit.IsNullable_2 = false;
- oFieldEdit.Required_2 = false;
- oFieldsEdit.AddField(oField);
- oField = new FieldClass();
- oFieldEdit = oField as IFieldEdit;
- IGeometryDef pGeoDef = new GeometryDefClass();
- IGeometryDefEdit pGeoDefEdit = (IGeometryDefEdit)pGeoDef;
- pGeoDefEdit.AvgNumPoints_2 = 5;
- pGeoDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolygon;
- pGeoDefEdit.GridCount_2 = 1;
- pGeoDefEdit.HasM_2 = false;
- pGeoDefEdit.HasZ_2 = false;
- pGeoDefEdit.SpatialReference_2 = pSReference;
- oFieldEdit.Name_2 = "SHAPE";
- oFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
- oFieldEdit.GeometryDef_2 = pGeoDef;
- oFieldEdit.IsNullable_2 = true;
- oFieldEdit.Required_2 = true;
- oFieldsEdit.AddField(oField);
- oField = new FieldClass();
- oFieldEdit = oField as IFieldEdit;
- oFieldEdit.Name_2 = "Code";
- oFieldEdit.Type_2 = esriFieldType.esriFieldTypeSmallInteger;
- oFieldEdit.IsNullable_2 = true;
- oFieldsEdit.AddField(oField);
- //创建要素类
- oFeatureClass = (pMemoryWS as IFeatureWorkspace).CreateFeatureClass("Temp", oFields, null, null, esriFeatureType.esriFTSimple, "SHAPE", "");
- oFeatureLayer = new FeatureLayerClass();
- oFeatureLayer.Name = "TransTemp";
- oFeatureLayer.FeatureClass = oFeatureClass;
- //创建唯一值符号化对象
- IUniqueValueRenderer pURender = new UniqueValueRendererClass();
- pURender.FieldCount = 1;
- pURender.set_Field(0, "Code");
- pURender.UseDefaultSymbol = false;
- ISimpleFillSymbol pFillSym = new SimpleFillSymbolClass();
- pFillSym.Style = esriSimpleFillStyle.esriSFSSolid;
- //半透明颜色
- IRgbColor pColor = new RgbColorClass();
- pColor.Red = 255;
- pColor.Green = 255;
- pFillSym.Color = pColor;
- pURender.AddValue("1", "", pFillSym as ISymbol);
- pFillSym = new SimpleFillSymbolClass();
- pFillSym.Style = esriSimpleFillStyle.esriSFSSolid;
- //唯一值符号化内存图层
- (oFeatureLayer as IGeoFeatureLayer).Renderer = pURender as IFeatureRenderer;
- ILayerEffects pLyrEffect = oFeatureLayer as ILayerEffects;
- //透明度
- pLyrEffect.Transparency = 80;
- }
- catch(Exception Err)
- {
- MessageBox.Show(Err.Message);
- }
- finally
- {
- try{
- ystem.Runtime.InteropServices.Marshal.ReleaseComObject(oField);
- System.Runtime.InteropServices.Marshal.ReleaseComObject(oFields);
- System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldsEdit);
- System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldEdit);
- System.Runtime.InteropServices.Marshal.ReleaseComObject(pName);
- System.Runtime.InteropServices.Marshal.ReleaseComObject(pWSF);
- System.Runtime.InteropServices.Marshal.ReleaseComObject(pWSName);
- System.Runtime.InteropServices.Marshal.ReleaseComObject(pMemoryWS);
- System.Runtime.InteropServices.Marshal.ReleaseComObject(oFeatureClass);
- }
- catch
- {
- }
- GC.Collect();
- }
- return oFeatureLayer;
- }
- catch (Exception Err)
- {
- MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
- return null;}
- }
- /// <summary> 在地图控件上添加透明临时图元/// </summary>
- /// <param name="pMapCtrl">地图控件</param>
- /// <param name="pGeo">Envelope或Polygon几何实体</param>
- /// <param name="bAutoClear">是否清除原有内容</param>
- public void AddTransTempEle(AxMapControl pMapCtrl, IGeometry pGeo, bool bAutoClear)
- {
- try
- {
- if (pMapCtrl == null) return;
- if (pGeo == null) return;
- if (pGeo.IsEmpty) return;
- IGeometry pPolygon = null;
- if (pGeo is IEnvelope)
- {
- object Miss = Type.Missing;
- pPolygon = new PolygonClass();
- IGeometryCollection pGeoColl = pPolygon as IGeometryCollection;
- pGeoColl.AddGeometry(pGeo, ref Miss, ref Miss);
- }
- else if (pGeo is IPolygon)
- {
- (pGeo as ITopologicalOperator).Simplify();
- pPolygon = pGeo;
- }
- else
- {
- MessageBox.Show( "几何实体类型不匹配","提示" ,MessageBoxButtons.OK, MessageBoxIcon.Information);
- return;
- }
- //获取透明要素层
- IFeatureLayer pFlyr = null;
- for (int i = 0; i < pMapCtrl.LayerCount; i++)
- {
- if (pMapCtrl.get_Layer(i).Name == "TransTemp")
- {
- pFlyr = pMapCtrl.get_Layer(i) as IFeatureLayer;
- break;
- }
- }
- //透明临时层不存在需要创建
- if (pFlyr == null)
- {
- pFlyr = AddFeatureLayerByMemoryWS(pMapCtrl,pMapCtrl.SpatialReference);
- if (pFlyr == null)
- {
- MessageBox.Show("创建透明临时图层发生异常", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
- return;
- }
- }
- IFeatureClass pFC = pFlyr.FeatureClass;
- if (bAutoClear)
- {
- if (pFC.FeatureCount(null) > 0)
- {
- IFeatureCursor pFCursor = pFC.Search(null, false);
- if (pFCursor != null)
- {
- IFeature pFeature = pFCursor.NextFeature();
- if (pFeature != null)
- {
- while (pFeature != null)
- {
- pFeature.Delete();
- pFeature = pFCursor.NextFeature();
- }
- }
- System.Runtime.InteropServices.Marshal.ReleaseComObject(pFCursor);
- }
- }
- }
- //创建要素
- IFeature pNFeature = pFC.CreateFeature();
- pNFeature.Shape = pPolygon;
- pNFeature.set_Value(pFC.FindField("Code"),"1");
- pNFeature.Store();
- pMapCtrl.Refresh(esriViewDrawPhase.esriViewGeography, pFlyr, pFlyr.AreaOfInterest);
- }
- catch (Exception Err)
- {
- MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
- }
- }
- /// <summary>
- /// 获取查询要素
- /// </summary>
- /// <param name="pFeatureLayer">要素图层</param>
- /// <param name="pGeometry">图形范围参数</param>
- /// <returns>符号条件要素集合</returns>
- private List<IFeature> GetSeartchFeatures( IFeatureLayer pFeatureLayer,IGeometry pGeometry)
- {
- try
- {
- List<IFeature> pList = new List<IFeature>();
- //创建SpatialFilter空间过滤器对象
- ISpatialFilter pSpatialFilter = new SpatialFilterClass();
- IQueryFilter pQueryFilter = pSpatialFilter as ISpatialFilter;
- //设置过滤器的Geometry
- pSpatialFilter.Geometry = pGeometry;
- //设置空间关系类型
- pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;
- //获取FeatureCursor游标
- IFeatureCursor pFeatureCursor = pFeatureLayer.Search(pQueryFilter, false);
- //遍历FeatureCursor
- IFeature pFeature = pFeatureCursor.NextFeature();
- while (pFeature != null)
- {
- //获取要素对象
- pList.Add(pFeature);
- pFeature = pFeatureCursor.NextFeature();
- }
- System.Runtime.InteropServices.Marshal.ReleaseComObject(pFeatureCursor);
- return pList;
- }
- catch (Exception Err)
- {
- MessageBox.Show(Err.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
- return null;
- }
- }
- bool bSearch = false; //定义bool变量用于启动多边形查询功能
- private void button1_Click(object sender, EventArgs e)
- {
- try
- {
- //向地图控件添加内存图层
- IFeatureLayer pFeatureLayer = this.AddFeatureLayerByMemoryWS(this.axMapControl1,this.axMapControl1.SpatialReference);
- this.axMapControl1.AddLayer(pFeatureLayer);
- //设置鼠标样式为十字丝
- this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair;
- //启动范围查询功能
- bSearch = true;
- }
添加一个新的Form在Form上添加一个DataGridView控件用于显示查询结果信息。如图4所示:
- private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
- {
- if (bSearch)
- {
- //设置鼠标样式为十字丝
- this.axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair;
- //获取画定范围的Geometry
- IGeometry pGeometry = this.axMapControl1.TrackPolygon();
- //添加半透名临时图形
- this.AddTransTempEle(this.axMapControl1, pGeometry, false);
- IFeatureLayer pFeatureLayer=this.axMapControl1.get_Layer(1) as IFeatureLayer;
- //执行查询获取符号条件的要素
- List<IFeature> pFList = this.GetSeartchFeatures(pFeatureLayer, pGeometry);
- attribute pAttribute = new attribute();
- //设置信息显示窗体中DataGridView的属性
- //设置行数pFList.Count+1包括字段名哪一行即表头
- pAttribute.dataGridView1.RowCount = pFList.Count+1;
- //设置边界风格
- pAttribute.dataGridView1.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Sunken;
- //设置列数
- pAttribute.dataGridView1.ColumnCount = pFList[0].Fields.FieldCount;
- //遍历第一个要素的字段用于给列头赋值(字段的名称)
- for(int m=0;m<pFList[0].Fields.FieldCount;m++)
- {
- pAttribute.dataGridView1.Columns[m].HeaderText = pFList[0].Fields.get_Field(m).AliasName;
- }
- //遍历要素
- for (int i = 0; i < pFList.Count; i++)
- {
- IFeature pFeature=pFList;
- for(int j=0;j<pFeature.Fields.FieldCount;j++)
- {
- //填充字段值
- pAttribute.dataGridView1[j, i].Value = pFeature.get_Value(j).ToString();
- }
- }
- pAttribute.Show();
- }
- }
5.7.3功能演示
1.单击按钮向地图控件上添加一内存图层,并启动多边形查询功能如图5示:
2.点击鼠标左键在地图上画以多边形范围,双击结束,将看到在所画的范围以半透明的形式添加在地图之上,并显示出查询结果的属性信息如图所示:
5.7.4 Demo总结:
1.使用IWorkspaceFactory,IWorkspaceName,IName,IWorkspace等接口以及InMemoryWorkspaceFactoryClass对象创建在程序运行时的内存中的矢量要素层
2.复习IUniqueValueRenderer等接口以及UniqueValueRendererClass对象唯一值符号化要素图层
3.使用ILayerEffects接口创建半透明效果要素图层
4.使用ISpatialFilter,IQueryFilter 等接口以及SpatialFilterClass对象获取符号条件的FeatureCursor,并学会通过遍历整个FeatureCursor中Feature对象,获取符号查询条件的Feature集合
5.使用IFeatureLayerDefinition根据要素选择集创建新要素图层
5.8附IFeatureClass.Search(IQuery Filter,bool Recycling)参数说明
FeatureClass的Search方法大家经常用到,很多人对Search方法的其中一个参数bool Recycling不是很理解。先做以下解释:
1.pFeatureCursor存储的是所有符合条件的Feature对象的引用,
2.Recycling的意思是回收,参数Recycling为True的时当执行这个方法IFeature pFeature=pFeatureCursor.NextFeature()上一条记录的图形值在内存中所占的地址就会被销毁回收,为False的时候当执行这个方法IFeature pFeature=pFeatureCursor.NextFeature()上一条记录的图形值依然存在在内存中。
1.参数Recycling设置为True
IFeatureClass pFeatureClass = (this.axMapControl1.get_Layer(0) as IFeatureLayer).FeatureClass;
IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, true);
//IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, false);
List<IFeature> pFeatures = new List<IFeature>();
IFeature pFeature = pFeatureCursor.NextFeature();
while (pFeature != null)
{
pFeatures.Add(pFeature);
pFeature = pFeatureCursor.NextFeature();
}
for (int i = 0; i < pFeatures.Count; i++)
{
MessageBox.Show(((pFeatures.Shape as IPolygon) as IArea).Area.ToString());
}
分析:pFeatures集合存储了指向FeatureClass上所有Feature的引用,但是由于Recycling参数设置为TRUE也就是说每执行一个NextFeautre方法上一条记录的Feature值在内存中被回收,所以到最后遍历pFeatures集合的时候所有的IFeature引用指向的Feature对象都为Null。所以会引发一下错误(如下图7所示):
.参数Recycling设置为False
IFeatureClass pFeatureClass = (this.axMapControl1.get_Layer(0) as IFeatureLayer).FeatureClass;
//IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, true);
IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, false);
List<IFeature> pFeatures = new List<IFeature>();
IFeature pFeature = pFeatureCursor.NextFeature();
while (pFeature != null)
{
pFeatures.Add(pFeature);
pFeature = pFeatureCursor.NextFeature();
}
for (int i = 0; i < pFeatures.Count; i++)
{
MessageBox.Show(((pFeatures.Shape as IPolygon) as IArea).Area.ToString());
}
分析:pFeatures集合存储了指向FeatureClass上所有Feature的引用,但是由于Recycling参数设置为False也就是说每执行一个NextFeautre方法上一条记录的Feature值在内存中依然存在,所以到最后遍历pFeatures集合的时候所有的IFeature引用指向的Feature对象都依然存在。所以会执行的很Happy(如下图8所示):