GIS开发中的坐标系统3(转帖整理)
空 间参考(Spatial Reference)是GIS数据的骨骼框架,能够将我们的数据定位到相应的位置,为地图中的每一点提供准确的坐标。 在同一个地图上显示的地图数据的空间参考必须是一致的,如果两个图层的空间参考不一致,往往会导致两幅地图无法正确拼合,因此开发一个GIS系统时,为数 据选择正确的空间参考非常重要。
在 ArcGIS 中,每个数据集都具有一个坐标系,该坐标系用于将数据集与通用坐标框架(如地图)内的其他地理数据图层集成。通过坐标系可在地图中集成数据集,以及执行各种集成的分析操作,例如叠加不同的源和坐标系中的数据图层。
相关知识大地水准面
大地水准面是由静止海水面并向大陆延伸所形成的不规则的封闭曲面。它是重力等位面,即物体沿该面运动时,重力不做功(如水在这个面上是不会流动的)。因为地球的质量并非在各个点均匀分布,因此重力的方向也会相应发生变化,所以大地水准面的形状是不规则的,如下图:
与平均海水面相吻合的称为大地水准面
地球椭球体由 定义可以知大地水准面的形状也是不规则的,仍不能用简单的数学公式表示,为了测量成果的计算和制图的需要,人们选用一个同大地水准面相近的可以用数学方法 来表达的椭球体来代替,简称地球椭球体,它是一个规则的曲面,是测量和制图的基础,因地球椭球体是人们选定的跟大地水准面很接近的规则的曲面,所以地球椭 球体就可以有多个,地球椭球体是用长半轴、短半轴和扁率来表示的。
基准面
基准面是在特定区域内与地球表面极为吻合的椭球体。椭球体表面上的点与地球表面上的特定位置相匹配,也就是对椭球体进行定位,该点也被称作基准面的原点。原点的坐标是固定的,所有其他点由其计算获得。
|
基准面 | 经度 | 纬度 |
NAD 1927 | -122.46690368652 | 48.7440490722656 |
NAD 1983 | -122.46818353793 | 48.7438798543649 |
WGS 1984 | -122.46818353793 | 48.7438798534299 |
3 个不同基准面时华盛顿州贝灵厄姆市的地理坐标
下图来自ArcGIS 说明了基准面是基于椭球体的:
地图投影
简单的说地图投影就是把地球表面的任意点,利用一定数学法则,转换到地图平面上的理论和方法。
两种坐标系地理坐标系地理坐标系也可称为真实世界的坐标系,是用于确定地物在地球上位置的坐标系,它用经纬度来表示地物的位置,经度和纬度是从地心到地球表面上某点的测量角,通常以度或百分度为单位来测量该角度。下图将地球显示为具有经度和纬度值的地球。
地理坐标系 (GCS) 是基于基准面的使用三维球面来定义地球上的位置,GCS 往往被误称为基准面,而基准面仅是 GCS 的一部分,GCS 包括角度测量单位、本初子午线和基准面。下图来自ArcGIS说明了了地理坐标系的组成:
|
投影坐标系
投影坐标系是基于地理坐标系的,它使用基于X,Y值的坐标系统来描述地球上某个点所处的位置,可以这样认为投影坐标系=地理坐标系(如:北京54、西安80、WGS84)+投影方法(如:高斯-克吕格、Lambert投影、Mercator投影)+线性单位。下图来自ArcGIS说明了投影坐标系的组成:
ArcGIS Engine提 供了一系列对象供开发者管理GIS系统的坐标系统。对大部分开发者而言了解ProjectedCoordinateSystem, GeographicCoordinateSystem, SpatialReference Environment这三个组件类是非常有必要的,对于高级开发者而言,可能需要自定义坐标系统可以使用这些对象 Projection,Datum,AngularUnit,Spheriod,PrimeMeridian和GeoTransformation等。在 ArcGIS中除了我们上面介绍的两种坐标系,还有一种称之为Unknown的坐标系,这种坐标系是当我们的数据没有坐标(jpg等文件)或者坐标文件丢 失的时候ArcMap不能识别数据的投影信息而赋予的,在ArcGIS Engine中下面三个类分别对应了三个坐标系:
利用ArcGIS Engine创建一个坐标系或者基准面用的是SpatialReferenceEnvironmentClass类,该类实现了ISpatialReferenceFactory接口,该接口定义了创建坐标系,基准面等方法和属性,如下图:
在利用ISpatialReferenceFactory创建坐标系的时候往往需要一个int类型的参数,这个int其实就是这些坐标系的代号,如我们熟悉的4326就是WGS1984,下面为部分截图:
同一基准面的坐标转换
对于同一基准面,我们可以肯定一点就是同一位置经纬度坐标是一样的,而不同的就是计算成平面坐标的时候可能有所不同,因为算法不一样,在这里我只是将经纬度坐标转成平面的坐标。
- private IPoint GetpProjectPoint(IPoint pPoint, bool pBool)
- {
- ISpatialReferenceFactory pSpatialReferenceEnvironemnt = new SpatialReferenceEnvironment();
- ISpatialReference pFromSpatialReference = pSpatialReferenceEnvironemnt.CreateGeographicCoordinateSystem((int)esriSRGeoCS3Type.esriSRGeoCS_Xian1980);// 西安80
- ISpatialReference pToSpatialReference = pSpatialReferenceEnvironemnt.CreateProjectedCoordinateSystem((int)esriSRProjCS4Type.esriSRProjCS_Xian1980_3_Degree_GK_Zone_34);// 西安80
- if (pBool == true)//球面转平面
- {
- IGeometry pGeo = (IGeometry)pPoint;
- pGeo.SpatialReference = pFromSpatialReference;
- pGeo.Project(pToSpatialReference);
- return pPoint;
- }
- else //平面转球面
- {
- IGeometry pGeo = (IGeometry)pPoint;
- pGeo.SpatialReference = pToSpatialReference;
- pGeo.Project(pFromSpatialReference);
- return pPoint;
- }
- }
不同基准面的坐标转换
通 过前面的介绍,我们知道地球上同一位置的坐标在不同的基准面上是不一样的,而基准面是构成坐标系的一个部分,因为基准面在定位的时候牵扯到了相对地心的平 移或旋转等,所以对于这样的转换我们无法直接进行,需要一个转换参数,而这些参数也是基于不同的模型的,常用的有三参数和7参数,三参数是比较简单的也是比较容易理解的,三参数是在两个基准面之间进行了X,Y,Z轴的平移,通过下面的图我们很清楚的看到三参数之间两个基准面的关系:
如果知道了这三个平移的参数
外加个基准面上的点,那么另外一个点的坐标就是
而7参数的模型比较复杂,这种复杂的同时让精度大为提高,7参数不仅仅考虑了两个基准面之间的平移,还考虑了旋转外加一个比例因子(椭球体的大小可能不一样),从下面的图我们可以清楚看到这种关系:
对于7参数,我们知道了平移三参数
旋转三参 数以及比例因子 外加一个基准面上的坐标就可按照下面的公式求出另外一个基准面上的坐标:
对于不同基准面之间的转换,ArcGIS Engine提供了一个用来控制转换参数的接口IGeoTransformation,该接口被以下类实现
着每一个接口对应了一种转换方法,比如GeocentricTranslationClass类就实现了三参数,而CoordinateFrameTransformationClass类实现了7参数,要实现3参数或者7参数需要IGeometry2或更新接口的ProjectEx方法,下面我们用代码实现一个不同基准面之间的坐标转换。
-
- public void ProjectExExample()
- {
- ISpatialReferenceFactory pSpatialReferenceFactory = new SpatialReferenceEnvironmentClass();
- // ISpatialReference pFromCustom = pSpatialReferenceFactory.CreateESRISpatialReferenceFromPRJFile(@"E:\arcgis\Engine\zidingyi.prj");
- IPoint pFromPoint = new PointClass();
- pFromPoint.X = 518950.788;
- pFromPoint.Y = 4335923.97;
- IZAware pZAware = pFromPoint as IZAware;
- pZAware.ZAware = true;
- pFromPoint.Z = 958.4791;
- // ((IGeometry)pFromPoint).SpatialReference = pFromCustom;
- //自定义投影WGS84下的北京6度19带。
- ((IGeometry)pFromPoint).SpatialReference = CreateCustomProjectedCoordinateSystem();
- //目标投影
- IProjectedCoordinateSystem projectedCoordinateSystem = pSpatialReferenceFactory.CreateProjectedCoordinateSystem((int)esriSRProjCS4Type.esriSRProjCS_Xian1980_GK_Zone_19);
- //因为目标基准面和原始基准面不在同一个上,所以牵扯到参数转换,我用7参数转换
- ICoordinateFrameTransformation pCoordinateFrameTransformation = new CoordinateFrameTransformationClass();
- pCoordinateFrameTransformation.PutParameters(7个参数);
- pCoordinateFrameTransformation.PutSpatialReferences(CreateCustomProjectedCoordinateSystem(), projectedCoordinateSystem as ISpatialReference);
- //投影转换
- IGeometry2 pGeometry = pFromPoint as IGeometry2;
- pGeometry.ProjectEx(projectedCoordinateSystem as ISpatialReference, esriTransformDirection.esriTransformForward, pCoordinateFrameTransformation, false, 0, 0);
- }
- private IProjectedCoordinateSystem CreateCustomProjectedCoordinateSystem()
- {
- ISpatialReferenceFactory2 pSpatialReferenceFactory = new SpatialReferenceEnvironmentClass();
- IProjectionGEN pProjection = pSpatialReferenceFactory.CreateProjection((int) esriSRProjectionType.esriSRProjection_GaussKruger) as IProjectionGEN;
- IGeographicCoordinateSystem pGeographicCoordinateSystem = pSpatialReferenceFactory.CreateGeographicCoordinateSystem((int)esriSRGeoCSType.esriSRGeoCS_WGS1984);
- ILinearUnit pUnit = pSpatialReferenceFactory.CreateUnit((int)esriSRUnitType.esriSRUnit_Meter) as ILinearUnit;
- IParameter[] pParameters = pProjection.GetDefaultParameters();
- IProjectedCoordinateSystemEdit pProjectedCoordinateSystemEdit = new ProjectedCoordinateSystemClass();
- object pName = "WGS-BeiJing1954";
- object pAlias = "WGS-BeiJing1954";
- object pAbbreviation = "WGS-BeiJing1954";
- object pRemarks = "WGS-BeiJing1954";
- object pUsage = "Calculate Meter From lat and lon";
- object pGeographicCoordinateSystemObject = pGeographicCoordinateSystem as object;
- object pUnitObject = pUnit as object;
- object pProjectionObject = pProjection as object;
- object pParametersObject = pParameters as object;
- pProjectedCoordinateSystemEdit.Define(ref pName, ref pAlias, ref pAbbreviation, ref
- pRemarks, ref pUsage, ref pGeographicCoordinateSystemObject, ref pUnitObject,ref pProjectionObject, ref pParametersObject);
- IProjectedCoordinateSystem5 pProjectedCoordinateSystem = pProjectedCoordinateSystemEdit as IProjectedCoordinateSystem5;
- pProjectedCoordinateSystem.FalseEasting = 500000;
- pProjectedCoordinateSystem.LatitudeOfOrigin = 0;
- pProjectedCoordinateSystem.set_CentralMeridian(true,111);
- pProjectedCoordinateSystem.ScaleFactor=1;
- pProjectedCoordinateSystem.FalseNorthing=0;
- return pProjectedCoordinateSystem;
- }