原文:ArcGIS Engine开发之旅10--空间参考及坐标转换

空间参考(Spatial Reference)是 GIS 数据的骨骼框架,能够将我们的数据定位到相应的位置,为地图中的每一点提供准确的坐标。 在同一个地图上显示的地图数据的空间参考必须是一致的,如果两个图层的空间参考不一致,往往会导致两幅地图无法正确拼合,因此开发一个 GIS 系统时,为数据选择正确的空间参考非常重要。

1 相关知识 

1.1大地水准面 

大地水准面是由静止海水面并向大陆延伸所形成的不规则的封闭曲面。

1.2地球椭球体 

由定义可以知大地水准面的形状也是不规则的,仍不能用简单的数学公式表示,为了测量成果的 计算和制图的需要,人们选用一个同大地水准面相近的可以用数学方法来表达的椭球体来代替, 简称地球椭球体,它是一个规则的曲面,是测量和制图的基础,因地球椭球体是人们选定的跟大 地水准面很接近的规则的曲面,所以地球椭球体就可以有多个,地球椭球体是用长半轴、短半轴 和扁率来表示的。

1.3基准面 

基准面是在特定区域内与地球表面极为吻合的椭球体。椭球体表面上的点与地球表面上的特定位 置相匹配,也就是对椭球体进行定位,该点也被称作基准面的原点。原点的坐标是固定的,所有其他点由其计算获得

基准面的坐标系原点往往距地心有一定偏移(有的也在地心,如 WGS1984),如西安 80 的基准面和北京 54的基准面.因为椭球体通过定位以便能更好的拟合不同的地区,所以同一个椭球体可以拟合好几个基准面.因为原点不同,所以不同的基准面上,同一个点的坐标是不相同的,这点我们应该清楚.下面以华盛顿州贝灵厄姆市为例来说明。使用 NAD27、NAD83 和 WGS84 以十进制为单位比较贝灵厄姆的坐标。显而易见,NAD83 和 WGS84 表示的坐标几乎相同,但 NAD27 表示的坐标则大不相同,这是因为所使用的基准面和旋转椭球体对地球基本形状的表示方式不同。

1.4 地图投影 

简单的说地图投影就是把地球表面的任意点,利用一定数学法则,转换到地图平面上的理论和方法.2.

 2. 两种坐标系 

2.1 地理坐标系 

地理坐标系也可称为真实世界的坐标系,是用于确定地物在地球上位置的坐标系,它用经纬度来表示地物的位置,经度和纬度是从地心到地球表面上某点的测量角,通常以度或百分度为单位来测量该角度。

2.2投影坐标系 

投影坐标系是基于地理坐标系的,它使用基于 X,Y 值的坐标系统来描述地球上某个点所处的位置,可以这样认为投影坐标系=地理坐标系(如:北京 54、西安 80、WGS84)+投影方法(如:高斯-克吕格、Lambert 影、Mercator 投影)+线性单位。

2.3ArcGIS Engine 对空间参考的支持 

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,下面为部分截图:

2.4 同一基准面的坐标转换 

对于同一基准面,我们可以肯定一点就是同一位置经纬度坐标是一样的,而不同的就是计算成平面坐标的时候可能有所不同,因为算法不一样,在这里我只是将经纬度坐标转成平面的坐标。

 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)//球面转平面
{
Geometry pGeo = (IGeometry)pPoint;
pGeo.SpatialReference = pFromSpatialReference;
pGeo.Project(pToSpatialReference);
return pPoint;
}
else //平面转球面
{
IGeometry pGeo = (IGeometry)pPoint;
pGeo.SpatialReference = pToSpatialReference;
pGeo.Project(pFromSpatialReference);
return pPoint;
}
}

2.5不同基准面的坐标转换 

通过前面的介绍,我们知道地球上同一位置的坐标在不同的基准面上是不一样的,而基准面是构成坐标系的一个部分,因为基准面在定位的时候牵扯到了相对地心的平移或旋转等,所以对于这样的转换我们无法直接进行,需要一个转换参数,而这些参数也是基于不同的模型的,常用的有三参数和 7 参数,三参数是比较简单的也是比较容易理解的,三参数是在两个基准面之间进行了 X,Y,Z 轴的平移,通过下面的图我们很清楚的看到三参数之间两个基准面的关系:

而 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\z idingyi.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.esr iSRProjCS_Xian1980_GK_Zone_19); //因为目标基准面和原始基准面不在同一个上,所以牵扯到参数转换,我用7参数 转换 ICoordinateFrameTransformation pCoordinateFrameTransformation = new CoordinateFrameTransformationClass();
pCoordinateFrameTransformation.PutParameters(-112.117, 4.530, 21.89, -0.00058702, -0.00476421, 0.00009358, 0.99998006411);
pCoordinateFrameTransformation.PutSpatialReferences(CreateCustomProjectedCoordinate System(), projectedCoordinateSystem as ISpatialReference);
//投影转换 IGeometry2 pGeometry = pFromPoint as IGeometry2;
pGeometry.ProjectEx(projectedCoordinateSystem as ISpatialReference, esriTransformDirection.esriTransformForward, pCoordinateFrameTransformation, false, , );
}
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 = ;
pProjectedCoordinateSystem.LatitudeOfOrigin = ;
pProjectedCoordinateSystem.set_CentralMeridian(true,);
pProjectedCoordinateSystem.ScaleFactor=;
pProjectedCoordinateSystem.FalseNorthing=;
return pProjectedCoordinateSystem;
}

ArcGIS Engine开发之旅10--空间参考及坐标转换的更多相关文章

  1. ArcGIS Engine开发之旅09--几何对象和空间参考

    原文:ArcGIS Engine开发之旅09--几何对象和空间参考 1.Geometry  Geometry 是 GIS 中使用最为广泛的对象集之一,用户在创建.删除.编辑和进行地理分析的时候,就是处 ...

  2. ArcGIS Engine开发之旅05---空间数据库

    原文:ArcGIS Engine开发之旅05---空间数据库 1  Geodatabase概念 Geodatabase是ArcInfo8引入的一种全新的面向对象的空间数据模型,是建立在DBMS之上的统 ...

  3. ArcGIS Engine开发之旅04---ARCGIS接口详细说明

    原文:ArcGIS Engine开发之旅04---ARCGIS接口详细说明 ArcGIS接口详细说明... 1 1.      IField接口(esriGeoDatabase)... 2 2.    ...

  4. ArcGIS Engine开发之旅02--ArcGIS Engine中的类库

    原文:ArcGIS Engine开发之旅02--ArcGIS Engine中的类库 System类库 System类库是ArcGIS体系结构中最底层的类库.System类库包含给构成ArcGIS的其他 ...

  5. ArcGIS Engine开发之旅08--和查询相关的对象和接口

    原文:ArcGIS Engine开发之旅08--和查询相关的对象和接口 查询在GIS领域应该是一个很频繁的操作,在GIS中除了具有属性查询(和其他关系型数据库的查询类似),还提供了空间查询.在介绍查询 ...

  6. ArcGIS Engine开发之旅01---产品组成、逻辑体系结构

    原文:ArcGIS Engine开发之旅01---产品组成.逻辑体系结构 ArcGIS Engine 由两个产品组成:  面向开发人员的软件开发包(ArcGIS Engine Developer k ...

  7. ArcGIS Engine开发之旅07---文件地理数据库、个人地理数据库和 ArcSDE 地理数据库中的栅格存储加以比较 、打开栅格数据

    原文:ArcGIS Engine开发之旅07---文件地理数据库.个人地理数据库和 ArcSDE 地理数据库中的栅格存储加以比较 .打开栅格数据 对文件地理数据库.个人地理数据库和 ArcSDE 地理 ...

  8. ArcGIS Engine开发之旅03--ArcGIS Engine中的控件

    原文:ArcGIS Engine开发之旅03--ArcGIS Engine中的控件 制图控件,如MapControl.PageLayoutControl,其中MapControl控件主要用于地理数据的 ...

  9. arcgis engine 开发之QI

    ArcGIS Engine开发基础之QI AO开发中QI(接口查询)非常重要,从某种意义上说不会QI就不会做AO开发. 在讲ArcGIS Engine开发QI实例操作之前,以一个现实生活例子以方便大家 ...

随机推荐

  1. CodeForces Round 194 Div2

    A. Candy Bagstime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputs ...

  2. BZOJ4310 : 跳蚤

    首先求出后缀数组,得到本质不同的子串的个数. 然后二分答案,每次先通过后缀数组求出第$mid$小的子串,然后贪心进行检验. 检验的时候,从后往前贪心,每次加入一个后缀,如果不能加了,那就划为一段. 时 ...

  3. AndroidのUI体验之ImmersiveMode沉浸模式

    4.4带来了新的api——ImmersiveMode,可以使用户进入沉浸模式,享受更好的用户体验. 打开沉浸模式: /** * Detects and toggles immersive mode ( ...

  4. Myeclipse10 + JBPM4.4 环境搭建图文教程

    一.软件环境 IDE:Myeclipse10.0 (jbpm4.0以上版本好像只能与Myeclipse7.5以上版本集成) JBPM:4.4 与Myeclipse集成 1.解压jbpm-4.4.zip ...

  5. lightning mdb 源代码分析(1)

    lighting mdb(lmdb) 是一个高性能mmap kv数据库,基本介绍和文档参见symas官网,本文将尝试分析其源代码结构以理解数据库设计的关键技术. 本系列文章将尝试从以下几个方面进行分析 ...

  6. Lucene搜索方法总结

    转自:summerbell http://www.iteye.com/topic/569358 1.多字段搜索 使用 multifieldqueryparser 可以指定多个搜索字段. query q ...

  7. Hadoop配置文件解析

    Hadoop源码解析 2 --- Hadoop配置文件解析 1 Hadoop Configuration简介    Hadoop没有使用java.util.Properties管理配置文件, 也没有使 ...

  8. 【应用笔记】【AN001】VC#开发环境下基于以太网的4-20mA电流采集(基于modbus tcp 协议)

    版本:第一版 作者:毛鹏 杨帅 日期:20151108 简介 4-20mA电流环具有广泛的应用前景,在许多行业中都发挥着重要作用.本文主要介绍了以太网接口的4-20mA电流采集模块在VC#环境下进行温 ...

  9. 关于java文件扩展名认识

    ☆ 写在前面 一名新手在历经千辛万苦写好Java程序,怀揣激动的心情去编译和执行java程序时,结果出现错误,什么找不到文件,什么不存在,找不到main方法等等.我在这里就文件后扩展名,也叫文件后缀名 ...

  10. 前端编码规范(4)—— CSS 和 Sass (SCSS) 规范

    CSS and Sass (SCSS) style rules ID and class naming ID和class(类)名总是使用可以反应元素目的和用途的名称,或其他通用名称.代替表象和晦涩难懂 ...