1.15k likes | 2.08k Views
GIS 应用开发 Developing GIS Applications with ArcObjects using C#.NET 江西省研究生优质课程 主讲: 兰小机 GIS 博士、教授 Email : landcom8835@163.com QQ : 305333315 课件: ftp://218.87.136.94/. 兰小机简历. 兰小机,男, 1965 年 12 月生,博士,教授,硕士生导师, 江西省百千万人才工程人选,江西省高校中青年学科带头人,江西省优秀研究生指导教师 ; 地理 学 学科带头人、负责人 。
E N D
GIS应用开发 • Developing GIS Applications with ArcObjects using C#.NET • 江西省研究生优质课程 • 主讲:兰小机 GIS博士、教授 • Email : landcom8835@163.com • QQ :305333315 • 课件: ftp://218.87.136.94/
兰小机简历 • 兰小机,男,1965年12月生,博士,教授,硕士生导师,江西省百千万人才工程人选,江西省高校中青年学科带头人,江西省优秀研究生指导教师 ;地理学学科带头人、负责人。 • 主要经历 • 1988年7月毕业于南方冶金学院工程测量专业,获学士学位,并留校任教 • 1994年6月毕业于武汉测绘科技大学工程测量专业,获硕士学位,回校任教 • 2005年6月毕业于南京师范大学地图学与地理信息系统专业,获理学博士学位,回校任教
主要研究方向 • GIS应用开发 • 物联网、无线传感器网络与GIS • 分布式并行计算环境下空间数据的存储管理 • 空间数据库理论与空间数据挖掘
在研项目 • 江西省安监局科技项目--江西省重大危险源在线监控及应急救援信息系统,150万元,主持 • 国家自然科学基金项目--面向GML的时空关联规则及序列模式挖掘研究(编号:40971234) ,35万元,主持 • 国家自然科学基金项目--本原GML空间数据库理论及GMLGIS与传统GIS集成研究(编号:40761017) ,16万元,主持 • 江西省自然科学基金项目--分布式海量GML 空间数据并行存取与处理关键问题研究,2万元,兰小机主持 • 江西省教育厅科技项目--云计算环境下海量GML空间数据分布式存储管理关键问题,2万元,兰小机主持 • 萍乡市基础地理信息系统研究与开发,22万元,主持 • 城市公众地理信息服务系统研究与开发,10万元,主持
Chap.4 几何对象与空间参考 (3学时) • 几何对象概述 • 使用几何对象 • 空间参考 • 地理变换(Geotransformation)
4.1 几何对象概述 • Geometry对象用于表达要素(Feature)或图形元素(GraphicElement)的几何形状。 • ArcGIS(ArcObjects)的几何对象被分为两个层次 • 高级几何对象:用于定义要素的几何形状; • 构件几何对象:用于构建高级几何对象。 • GeometryObjectModel.pdf
高级几何对象包括以下类型: • Point:具有X、Y坐标值,以及可选的属性,如高程(Z值),度量值(M)和ID号。 • Multipoint:是无序点的群集,它用于表示具有相同属性的同一组点。 • Polyline:是一个有序路径(Path)的集合,这些路径既可以是连续的,也可以是离散的。 • Polygon:是环(Ring)的集合,环是一种封闭的路径。Polygon可以由一个或者多个环组成,甚至环内套环,形成岛环的情况,但是内外环之间不能重叠。 • MultiPatch:用于描述三维几何形体表面。
几何构件:用于构建高级几何对象。 • 路径(Path)用于构建多段线(polyline); • 环( Ring)用于构建多边形(polygon)或多面(MultiPatch; • 三角形带( TriangleStrip)、三角形扇( TriangleFan)及三角形,用于构建多面(MultiPatch),多面包含三角形带、三角形扇、三角形或环。 • 路径和环是由线段( Segment)相连的顶点序列。线段是参数化的函数,用于定义连接顶点的几何形状。 • 线段的类型包括: CircularArc(圆弧),Line(直线), EllipticArc(椭圆弧)和BezierCurve(贝塞尔曲线)四种类型
Envelope:用于描述其他几何对象的空间范围,它是一个矩形(仅考虑x、y坐标时)。它覆盖了几何对象的最小坐标和最大坐标、Z值和M值的变化范围Envelope:用于描述其他几何对象的空间范围,它是一个矩形(仅考虑x、y坐标时)。它覆盖了几何对象的最小坐标和最大坐标、Z值和M值的变化范围 • GeometryBag:是任何类型的几何体对象的集合,实际上GeometryBag是一个可以容纳任何类型几何对象的容器,可以同时容纳多种不同类型的几何对象。
一个几何对象的每个顶点,除了有XY坐标值外,还可以有其它可选属性,如Z值、M值和ID。一个几何对象的每个顶点,除了有XY坐标值外,还可以有其它可选属性,如Z值、M值和ID。 • IZAware • IMAware • IPointIDAware IPoint pnt = new PointClass() as IPoint; pnt.PutCoords(1, 1); IZAware zAware = pnt as IZAware; zAware.ZAware = true; pnt.Z = 11.1;
Multipoint、polyline、polygon和 MultiPatch几何对象在它们的几何形状上都有约束条件, • 多边形的内部必须明确定义,且必须与之外部分开,即多边形不能自重叠。 • 线不能自相交 • 当几何对象上的所有约束条件都满足时,我们说这个几何对象是简单的几何对象;当有一个约束条件未满足或不知道约束条件是否满足时,我们说这个几何对象是非简单(non-simple)的几何对象。 • ITopologicalOperator、IPolygon2~IPolygon4和IPolyline2~IPolyline5接口中提供了检测和强化几何对象简单性的操作。
几何对象,特别是线段类型,有一套丰富的方法用于定义它们的空间位置。几何对象,特别是线段类型,有一套丰富的方法用于定义它们的空间位置。 • 例如,IConstructCircularArc接口中有不同的方法定义圆弧线段。典型情况下,名字中包含“construct”的接口或方法使用多个输入参数来完全定义目标几何对象。
高级几何对象支持经典的集合运算来产生新的几何对象,这些集合运算包括集合的并(union)、交( intersection)、差( difference)和对称差分(symmetric difference,也即异或运算)。这些操作定义在ITopologicalOperator接口中,且通常情况下这些运算一次操作两个几何对象,但其中的ConstructUnion运算可作用于多于两个几何对象。 • 高级几何对象还支持IRelationalOperator 接口,其中定义了用于检测两个几何对象之间的空间关系方法,如检测两个几何对象是否相离(disjoint)、是否相接(touch)、是否包含(contain)等,这些方法返回布尔类型的值。
Polyline(多段线)对象 • Polyline(多段线)对象是相连或不相连的路径对象的有序集合,它可以分别是单个路径、多个不相连的路径和多个相连路径的集合。
路径(Path)是连续Segment对象的集合,除了路径的第一个和最后一个Segment外,每一个Segment的起始点都是前一个Segment的终止点,即路径对象中的Segment不能出现分离的情况。路径可以是任意数目的Line、CircularArc、EllipticArc和BezierCurve的组合。一个或多个路径对象组成一个Polyline对象。路径(Path)是连续Segment对象的集合,除了路径的第一个和最后一个Segment外,每一个Segment的起始点都是前一个Segment的终止点,即路径对象中的Segment不能出现分离的情况。路径可以是任意数目的Line、CircularArc、EllipticArc和BezierCurve的组合。一个或多个路径对象组成一个Polyline对象。
Geometry Curve PolyCurve Polyline Is composed of Paths Paths Are composed of Segments Segments Segments can be of 4 different Types Line CircularArc EllipticArc BezierCurve Points are used to build Segments or Polyline Points 图4-32 Polyline及相关对象结构图
Polygon对象 • Polygon(多边形)对象是一个有序环对象的集合,这些环可以是一个或者多个。多边形对象通常可以用于描述具有面积的多边形离散矢量对象。
Geometry Curve PolyCurve Polygon Is composed of Rings Rings Are composed of Segments Segments Segments can be of 4 different Types Line CircularArc EllipticArc BezierCurve Points are used to build Segments or Polygon Points 图4-34 Polygon及相关对象结构图
MultiPatch • MultiPatch描述具有带纹理的三维几何对象表面,三维几何对象还可以存储顶点法线(vertex normal)、顶点ID、顶点的M值及基于部分的属性(part-level attributes)。 • 可以通过导入多种不同文件格式(3D Studio Max的 .3ds 文件, OpenFlight的 .flt 文件, Sketchup的 .skp 文件, VRML的 .wrl 文件)的数据来创建MultiPatch.
还可以通过编程以多种不同的方式来创建MultiPatch. • (1) 不带纹理、法线和部分属性的MultiPatch可以与构建多边形相似的方式来定义:创建部分(parts),然后创建MultiPatch,再使用MultiPatch的IGeometryCollection接口将创建的部分添加到MultiPatch中。 • (2) 带纹理、法线和部分属性的MultiPatch需要使用GeneralMultiPatchCreator (需要3D Analyst许可)来创建。可以使用IGeneralMultiPatchInfo接口来获得已经存在的MultiPatch 的法线和材质信息。
MultiPatch支持IRelationalOperator3D接口(9.3新增的),其中提供了Disjoint3D方法,用于判断是否相离。MultiPatch还支持IProximityOperator3D接口,其中提供了方法ReturnDistance3D用于获得从查询的几何对象到MultiPatch的最近距离,及方法ReturnNearestPoint3D用于获得从查询的几何对象到MultiPatch上的最近点,QueryNearestPoint3D查询从输入点到MultiPatch 上最近的点。 • IRelationalOperator3D和IProximityOperator3D都是将MultiPatch看作是没有内部的表面的集合,所以如果有一个立方体形状的MultiPatch且有一个点明显在立方体内部,这个点被视为与该MultiPatch相分离,因为该点没有和MultiPatch的任何面相交。
MultiPatch包含多个部分:TriangleStrips, TriangleFans, Triangles和rings。MultiPatch中的每一部分有几个附加属性: • (1) 部分的类型(Type ):如TriangleStrip, TriangleFan, Triangle, Outer Ring等; • (2) 部分的优先级(Priority):用于控制重叠部分绘制的顺序; • (3) 部分使用的材质的索引号:该部分使用的材质在整个材质数组中的序号。 • MultiPatch可以包含材质(指定颜色、纹理、透明度信息)和纹理坐标(指定每部分上面纹理的放置)。ArcScene提供的样式库中包含MultiPatch模型,如三维的建筑物、树、车辆、街道设施及其他主题。
Triangle Strips(条、带) • Triangle Fans(扇)
4.2 使用几何对象 • Working with the geometry environment • Create a multipoint • Create a polyline • Create a polygon • Modify a specific vertex of a polyline • Modify a specific segment of a polyline • Create a multipatch • IGeometryBag vs. IGeometryCollection • Simplifying a geometry
4.2.1使用GeometryEnvironment对象 • GeometryEnvironment是一个单实例对象(singleton object),所以多次调用new GeometryEnvironmentClass()时,并不是每次都创建一个新的对象,而是返回对已经存在的GeometryEnvironment 对象的引用;也就是说,只有第一次调用new时,才创建一个新的GeometryEnvironment 对象;以后调用new时,不会创建新的GeometryEnvironment 对象,而仅是返回第一次调用new时创建的对象的引用。
GeometryEnvironment 提供了根据不同的输入创建几何对象的方法,及设置或获取全局变量(用于控制创建几何对象的行为)。GeometryEnvironment还提供了原本定义在其他几何对象上的方法的Java 和.NET 的友好版本(参阅IGeometryBridge 、IGeometryBridge2 接口)。 • GeometryEnvironmentClass 实现了IGeometryBridge 和IGeometryBridge2接口,主要是为了绕过COM 对象在Java 和.NET 环境中的限制。在Java 和.NET 环境中,不可能直接调用某些接口上定义的某些方法,因为某些接口的实现使用了C-语言样式的数组;在Java 和.NET 支持的语言中,不支持C-语言样式的数组,只有安全数组才允许在这些语言中使用。
IGeometryBridge2 pGeomBridge = new GeometryEnvironmentClass(); IPointCollection4 pPointCollection = new MultipointClass(); IPoint[] pPoints = new IPoint[3]; for (int i = 0; i < 3; i++) { pPoints[i] = new PointClass(); pPoints[i].PutCoords(i, 2 * i); } pGeomBridge.AddPoints(pPointCollection, ref pPoints);
4.2.2创建Multipoint对象 • Buildinga multipoint using points • Creating a multipoint using existing geometries • Creating a multipoint from the vertices of a polyline • Creating a multipoint using the ConstructIntersectionEx method
使用点(points)构建Multipoint • public void SetWKSPoints() { int length = 10; WKSPoint[] pointArray = new WKSPoint[length]; for (int i = 0; i < length; i++) { pointArray[i] = new WKSPoint(); pointArray[i].X = i * 10; pointArray[i].Y = i * 10; } IPointCollection4 pointCollection = new MultipointClass(); //add points to pointCollection IGeometryBridge2 geometryBridge = new GeometryEnvironmentClass(); geometryBridge.AddWKSPoints(pointCollection, ref pointArray); }
说明:任何几何对象都可以看作是点的集合,所以都可以使用点集来构建各种几何对象。IPointCollection4接口中的AddWKSPoints方法,不能在C#.NET中使用,而需要使用IGeometryBridge2中的替代方法AddWKSPoints;说明:任何几何对象都可以看作是点的集合,所以都可以使用点集来构建各种几何对象。IPointCollection4接口中的AddWKSPoints方法,不能在C#.NET中使用,而需要使用IGeometryBridge2中的替代方法AddWKSPoints; • WKSPoint是ArcObjects中定义的结构类型(Structure),其语法为: • public WKSPoint { double X, double Y }
使用已有的几何对象创建Multipoint • public void CreateMultipointFromExistingGeometry(IPolyline pPoly) {ITopologicalOperator2 pTopoOp2 = pPoly as ITopologicalOperator2; pTopoOp2.IsKnownSimple_2 = false; pTopoOp2.Simplify(); IPolygon pBufferedPoly = pTopoOp2.Buffer(5) as IPolygon; IPointCollectionpPointCollPoly = pBufferedPoly as IPointCollection; IGeometry pMultipoint = new MultipointClass(); pMultipoint.SpatialReference = pPoly.SpatialReference; IPointCollection pPointCollMultipoint = pMultipoint as IPointCollection; pPointCollMultipoint.AddPointCollection(pPointCollPoly); }
根据多段线的顶点创建Multipoint • private void TransformPoint (IPolyline polyline) { IPointCollection polylinePoints = polyline as IPointCollection; IGeometry multipoint = new MultipointClass(); multipoint.SpatialReference = polyline.SpatialReference; IPointCollection multipointPoints = multipoint as IPointCollection; multipointPoints.AddPointCollection(polylinePoints); IAffineTransformation2D affineTransformation = new AffineTransformation2DClass(); affineTransformation.Move(5, 0); ITransform2D transformee = multipoint as ITransform2D; transformee.Transform(esriTransformDirection.esriTransformForward, affineTransformation); transformee.Move(0, 5); transformee.Transform(esriTransformDirection.esriTransformForward, affineTransformation); }
使用ConstructIntersectionEx方法创建Multipoint • private void ConstructIntersectionEx1(ILine line0, ILine line1, String title) { IConstructMultipoint constructMultipoint = new MultipointClass(); double param0; double param1; int bits; constructMultipoint.ConstructIntersectionEx(line0 as ISegment, esriSegmentExtension.esriExtendEmbedded, line1 as ISegment, esriSegmentExtension.esriExtendEmbedded, out param0, out param1, out bits); …………… } public void ConstructIntersectionEx ( ISegment segment1, esriSegmentExtension extension1, ISegment segment2, esriSegmentExtension extension2, ref double params1, ref double params2, ref int tangentBits);
4.2.3 Create a polyline • Building a polyline using points • Building a polyline using segments • Creating a polyline using existing geometries • Creating a multipart polyline
Building a polyline using points • public void CreatePolylineByPoints() { int length = 10; WKSPoint[] pointArray = new WKSPoint[length]; for (int i = 0; i < length; i++) { pointArray[i] = new WKSPoint(); pointArray[i].X = i * 10; pointArray[i].Y = i * 10; } IPointCollection4 pointCollection = new PolylineClass(); IGeometryBridge2 geometryBridge = new GeometryEnvironmentClass(); geometryBridge.SetWKSPoints(pointCollection, ref pointArray); }
Building a polyline using segments • public void CreatePolylineBySegments() {IPolylinepSegPoly = new PolylineClass(); ICircularArc cArc = new CircularArcClass(); IBezierCurve bCur = new BezierCurveClass(); ILine line = new LineClass(); ISegmentCollection path1 = new PathClass(); ISegmentCollection path2 = new PathClass(); object obj=Type.Missing; path1.AddSegment(cArc as ISegment,ref obj,ref obj); path2.AddSegment(bCur as ISegment, ref obj, ref obj); path2.AddSegment(line as ISegment, ref obj, ref obj); IGeometryCollection pGeoColl = pSegPoly as IGeometryCollection; pGeoColl.AddGeometry(path1 as IGeometry ,ref obj,ref obj); pGeoColl.AddGeometry(path2 as IGeometry, ref obj, ref obj);
IPoint pPnt = new PointClass(); pPnt.X = -10; pPnt.Y = 0; cArc.PutCoordsByAngle(pPnt, 0, 3.14159265358979, 10.0); IPoint[] pntArray = new IPoint[4]; for (int i = 0; i <= 4; i++) pntArray[i] = new PointClass(); pntArray[0].X = 10; pntArray[0].Y = 0; pntArray[1].X = 10; pntArray[1].Y = 10; pntArray[2].X = 20; pntArray[2].Y = 10; pntArray[3].X = 20; pntArray[3].Y = 0; bCur.PutCoords(4,ref pntArray[0]); line.FromPoint.PutCoords(20, 0); line.ToPoint.PutCoords(30, 0); pGeoColl.GeometriesChanged(); }
Creating a polyline using existing geometries • public void CreatePolylineFromExistingGeometries(IPolygon pPolygon1, IPolygon pPolygon2) { //Build a new polyline by intersecting two existing polygons. ITopologicalOperator2 pTopoOp2 = pPolygon1 as ITopologicalOperator2; pTopoOp2.IsKnownSimple_2 = false; pTopoOp2.Simplify(); IPolyline pPoly = pTopoOp2.Intersect(pPolygon2, esriGeometryDimension.esriGeometry1Dimension) as IPolyline; }
Creating a multipart polyline • 使用已有的线对象创建一个多部分线对象. • 要求:创建的多部分线对象的每一线段与已有线对象垂直,且位于已有线段的中点处,长度为已有线段的1/3.
public IPolyline ConstructMultiPartPolyline( IPolyline inputPolyline) { IGeometry outGeometry = new PolylineClass(); outGeometry.SpatialReference = inputPolyline.SpatialReference; IGeometryCollection geometryCollection = outGeometry as IGeometryCollection; ISegmentCollection segmentCollection = inputPolyline as ISegmentCollection; IEnumSegment segments = segmentCollection.EnumSegments; ISegmentcurrentSegment; int partIndex = 0; int segmentIndex = 0; segments.Next(out currentSegment, ref partIndex, ref segmentIndex);
while (currentSegment != null) { ILine normal = new LineClass(); currentSegment.QueryNormal(esriSegmentExtension.esriNoExtension, 0.5, true, currentSegment.Length / 3, normal); ISegmentCollection newPath = new PathClass(); object missing = Type.Missing; newPath.AddSegment(normal as ISegment, ref missing, ref missing); geometryCollection.AddGeometry(newPath as IGeometry, ref missing, ref missing); segments.Next(out currentSegment, ref partIndex, ref segmentIndex); } return geometryCollection as IPolyline; } public voidQueryNormal ( esriSegmentExtension extension, double DistanceAlongCurve, bool asRatio, Double Length, ILine normal);
4.2.4 Create a polygon • Building a polygon using points • Building a polygon using segments • Creating a polygon using existing geometries • Creating a union of several polygons
Building a polygon using points • public void CreatePolygonByPoints() { int length = 10; WKSPoint[] pointArray = new WKSPoint[length]; for (int i = 0; i < length; i++) { pointArray[i] = new WKSPoint(); pointArray[i].X = i * 10; pointArray[i].Y = i * 10; } IGeometryBridge2 pGeoBrg = new GeometryEnvironmentClass(); IPointCollection4 pPointColl = new PolygonClass(); //add points to pointCollection pGeoBrg.SetWKSPoints(pPointColl, ref pointArray); }
Building a polygon using segments • public void CreatePolygonBySegments() { IPolygon pSegPoly = new PolygonClass(); ICircularArc cArc = new CircularArcClass(); IBezierCurve bCur = new BezierCurveClass(); ISegmentCollection ring1 = new RingClass(); ISegmentCollection ring2 = new RingClass(); object obj = Type.Missing; ring1.AddSegment(cArc as ISegment, ref obj, ref obj); ring2.AddSegment(bCur as ISegment, ref obj, ref obj); IGeometryCollection pGeoColl = pSegPoly as IGeometryCollection; pGeoColl.AddGeometry(ring1 as IGeometry, ref obj, ref obj); pGeoColl.AddGeometry(ring2 as IGeometry, ref obj, ref obj);
IPoint pPnt = new PointClass(); pPnt.X = -10; pPnt.Y = 0; cArc.PutCoordsByAngle(pPnt, 0, 2 * 3.14159265358979, 10.0); IPoint[] pntArray = new IPoint[4]; for (int i = 0; i <= 4; i++) pntArray[i] = new PointClass(); pntArray[0].X = 10; pntArray[0].Y = 0; pntArray[1].X = 10; pntArray[1].Y = 10; pntArray[2].X = 20; pntArray[2].Y = 10; pntArray[3].X = 20; pntArray[3].Y = 0; bCur.PutCoords(4, ref pntArray[0]); pGeoColl.GeometriesChanged(); }
Creating a polygon using existing geometries • public void CreatePolygonFromExistingGeometries(IPolygon pPolygon1, IPolygon pPolygon2) { ITopologicalOperator2 pTopoOp2 = pPolygon1 as ITopologicalOperator2; pTopoOp2.IsKnownSimple_2 = false; pTopoOp2.Simplify(); IPolygon pPoly = pTopoOp2.Union(pPolygon2) as IPolygon; }