最近GIS开发中遇到两个图层坐标系的对比是否相同。在GIS开发中总会接触到坐标系,如:地理坐标系、投影坐标系等,既然用到了,那就在这里记下一笔。那么当然先要了解一下坐标系的基本概念了。
基本概念
1、坐标系用来表达和确定空间位置。没有坐标系,坐标值就无从谈起,也就无法描述空间位置。
2、在GIS中,我们遇到的坐标系一般有两种:地理坐标系(GCS) 和投影坐标系(PCS)。地理坐标系是球面坐标,参考面是椭球面,坐标单位为经纬度;投影坐标系是平面坐标系,参考平面是水平面,坐标单位为米、千米等。
3、地理坐标系经过投影后变成投影坐标系,投影坐标系因此由地理坐标系和投影组成,投影坐标系必然包括有一个地理坐标系。(投影坐标系=地理坐标系+投影)
4、坐标系是数据或地图的属性,而投影是坐标系的属性。一个数据或一张地图一定有坐标系,而一个坐标系可以有投影也可以没投影。
EPSG:EPSG的英文全称是European Petroleum Survey Group,中文名称为欧洲石油调查组织。这个组织成立于1986年,2005年并入IOGP(International Association of Oil & Gas Producers),中文名称为国际油气生产者协会。EPSG是一个组织,现在改名叫做OGP,它维护了坐标参考系统。在国际上,每个坐标系统都会被分配一个 EPSG 代码,EPSG:4326 就是 WGS84。这个数字代码就叫WKID。
OGC:OGC全称Open Geospatial Consortium,自称是一个非盈利的、国际化的、自愿协商的标准化组织,它的主要目的就是制定与空间信息、基于位置服务相关的标准。这些标准就是OGC的“产品”,而这些标准的用处就在于使不同厂商、不同产品之间可以通过统一的接口进行互操作。
SRID:全称Spatial Reference System Identifier,是指坐标系在OGC标准中的唯一ID,跟EPSG中的code是一致的。是与特定坐标系、容差和分辨率关联的唯一标识符。
常见坐标系:
EPSG:4490是基于CGCS2000椭球的经纬度坐标系(地理坐标系)。
EPSG:4326 (WGS84) 地理坐标系,WGS84 是目前最流行的地理坐标系统。特点:利于存储,可读性高。缺点:会导致页面变形。
EPSG:3857 (Pseudo-Mercator) 伪墨卡托投影,也被称为球体墨卡托,Web Mercator。它是基于墨卡托投影的,把 WGS84坐标系投影到平面上。范围为纬度85度以下,由于google地图最先使用而成为事实标准。至今,大多互联网地图都使用EPSG3857,主要是因为该投影是等角投影,适合地图定向及导航,但是纬度越高,面积变形越大。特点:用于分析,显示数据。缺点:数据的可读性差和数值大存储比较占用内存。
地理坐标系的WKID介绍:Geographic Coordinate Systems
投影坐标系的WKID介绍:Projected Coordinate Systems
一、初识坐标系
例如ArcGIS中某图层有如下坐标系,其全部参数拷贝在下面。
CGCS2000_3_Degree_GK_Zone_38
WKID: 4526 权限: EPSG
Projection: Gauss_Kruger
False_Easting: 38500000.0
False_Northing: 0.0
Central_Meridian: 114.0
Scale_Factor: 1.0
Latitude_Of_Origin: 0.0
Linear Unit: Meter (1.0)
Geographic Coordinate System: GCS_China_Geodetic_Coordinate_System_2000
Angular Unit: Degree (0.0174532925199433)
Prime Meridian: Greenwich (0.0)
Datum: D_China_2000
Spheroid: CGCS2000
Semimajor Axis: 6378137.0
Semiminor Axis: 6356752.314140356
Inverse Flattening: 298.257222101
地理坐标系由三个参数来定义:角度单位(Angular Unit)、本初子午线(Prime Meridian)和大地测量系统(Datum)。地理坐标系“GCS_China_Geodetic_Coordinate_System_2000”使用的角度单位为“度(Degree)”,0.0174532925199433这个数字等于“π/180”,使用的本初子午线为0.0度经线,即格林威治皇家天文台(Greenwich)所在位置的经线,使用的大地测量系统则为“D_China_2000”。
地理坐标系的最重要的参数是“大地测量系统(Datum)”,而大地测量系统的最重要的参数是“椭球(Spheroid)”。椭球相同,大地测量系统不一定相同,因为原点(origin)和方位(orientation)可以不同。想象一下,同一个椭球,首先可以固定在三维空间中的任意一个点,并且在固定于某点后还能以三个自由度任意地旋转其方位(朝向)。当然,具体国家或地区在选择大地测量系统时,总是选择与这一国家或地区的地面最吻合的大地测量系统,而不是拍脑袋随便选的。“D_China_2000”大地测量系统使用的椭球为“CGCS2000”,而“CGCS2000”椭球的“长半轴(Semimajor Axis)”和“短半轴(Semiminor Axis)”分别为6378137.0和6356752.314140356,其“反扁率(Inverse Flattening)”为298.257222101,等于Semimajor Axis/( Semimajor Axis - Semiminor Axis)。
投影的参数对不同的投影方法有一定差别。投影坐标系“CGCS2000_3_Degree_GK_Zone_38”中“GK_Zone_38”这个名称指出,其投影方法是“高斯-克吕格(Gauss-Kruger,GK)”。投影的另一个重要参数是“东偏(False Easting)”为38500000.0,其中38为投影带号,而有些投影会在X坐标值前没有投影带号如:“Xian_1980_GK_CM_117E”的“false_easting”参数为500000.0。
/// <summary>
/// 获取空间参考信息
/// </summary>
/// <param name="pSpatialReference">ISpatialReference继承ISpatialReferenceInfo接口</param>
public static void GetMsgFromSpatialReference(ISpatialReference pSpatialReference)
{
#region ISpatialReferenceInfo接口信息
string spName = pSpatialReference.Name; //该空间参考组件的名称 CGCS2000_3_Degree_GK_Zone_38
string spAlias = pSpatialReference.Alias; //空间参考别名 ""
string sAbbreviation = pSpatialReference.Abbreviation; //该空间参考组件的缩写名称 ""
string Remarks = pSpatialReference.Remarks; //此空间参考组件的注释字符串 ""
int wkid = pSpatialReference.FactoryCode; //空间参考的工厂代码(WKID) 4526
#endregion
bool pXY = pSpatialReference.HasXYPrecision(); //是否定义了(x,y)精度信息 true
bool pZ = pSpatialReference.HasZPrecision(); //是否定义了Z值精度信息 true
bool pM = pSpatialReference.HasMPrecision(); //是否定义了M值精度信息 true
//int spImpl = pSpatialReference.SpatialReferenceImpl; //空间参考接口 106285480
//int preImpl = pSpatialReference.PrecisionExImpl;//精度接口 92924964
//int preExImpl = pSpatialReference.PrecisionExImpl; //精度扩展接口 92924964
ILinearUnit pZCoordinateUnit = pSpatialReference.ZCoordinateUnit; //Z坐标系(ILinearUnit接口提供对控制线性单元属性的成员的访问)
if (pZCoordinateUnit != null)
{ //ILinearUnit继承IUnit接口继承ISpatialReferenceInfo接口
string zName = pZCoordinateUnit.Name; //名称
string zAlias = pZCoordinateUnit.Alias; //别名
string zAbbreviation = pZCoordinateUnit.Abbreviation; //缩写
string zRemarks = pZCoordinateUnit.Remarks; //注释字符串
int zFactoryCode = pZCoordinateUnit.FactoryCode; //WKID
double zConversionFactor = pZCoordinateUnit.ConversionFactor; //单位转换系数,转换到米
double zMetersPerUnit = pZCoordinateUnit.MetersPerUnit; //坐标系单位
}
if (pSpatialReference is IProjectedCoordinateSystem tProCoordSys) //是否为平面坐标系(投影坐标系是地理坐标系的在平面上的投影)
{ //IProjectedCoordinateSystem接口继承ISpatialReference接口
string proName = tProCoordSys.Name; //投影(平面)坐标系名称 CGCS2000_3_Degree_GK_Zone_38
string proAlias = tProCoordSys.Alias; //空间参考别名 ""
string proAbbreviation = tProCoordSys.Abbreviation; //空间参考缩写 ""
string proRemarks = tProCoordSys.Remarks; //注释字符串 ""
int proFactoryCode = tProCoordSys.FactoryCode; //空间参考的工厂代码(WKID) 4526
bool proXY = tProCoordSys.HasXYPrecision(); //是否定义了(x,y)精度信息 true
bool proZ = tProCoordSys.HasZPrecision(); //是否定义了z精度信息 true
bool proM = tProCoordSys.HasMPrecision(); //是否定义了m精度信息 true
double proCentralMeridian = tProCoordSys.CentralMeridian[false]; //投影坐标系的中央子午线 114
double proFalseEasting = tProCoordSys.FalseEasting; //投影坐标系的东偏 38500000
double proFalseNorthing = tProCoordSys.FalseNorthing; //投影坐标系的北偏 0
string proUsage = tProCoordSys.Usage; //投影坐标系的使用说明 ""
int proHorizonCount = tProCoordSys.HorizonCount; //描述ProjCS限制的形状数量 1
double proScaleFactor = tProCoordSys.ScaleFactor; //投影坐标系的比例因子(K0) 1
//double proAzimuth = tProCoordSys.Azimuth; //投影坐标系的方位角 没有方位角并且报异常
//double proParallel = tProCoordSys.CentralParallel; //投影坐标系的中心平行线 没有中心线并且报异常
//double proLatitudeOf1st = tProCoordSys.LatitudeOf1st; //投影坐标系的第一个点(Phi 1)的纬度 没有
//double proLatitudeOf2nd = tProCoordSys.LatitudeOf2nd; //投影坐标系的第二点(Phi 2)的纬度 没有
//double proLongitudeOf1st = tProCoordSys.LongitudeOf1st; //投影坐标系第一个点(Lambda 1)的经度 没有
//double proLongitudeOf2nd = tProCoordSys.LongitudeOf2nd; //投影坐标系第二点(Lambda 2)的经度。 没有
//double proLongitudeOfOrigin = tProCoordSys.LongitudeOfOrigin; //投影坐标系的原点经度(Lambda0) 没有
//double proStandardParallel1 = tProCoordSys.StandardParallel1; //投影坐标系的第一个平行线(Phi 1) 没有
//double proStandardParallel2 = tProCoordSys.StandardParallel2; //投影坐标系的第二个平行线(Phi 2) 没有
//IGeographicCoordinateSystem继承ISpatialReference接口
IGeographicCoordinateSystem pGeographic = tProCoordSys.GeographicCoordinateSystem; //投影坐标系的地理坐标系
ILinearUnit proLinearUnit = tProCoordSys.CoordinateUnit; //投影坐标系的线性单位 ILinearUnit继承IUnit接口继承ISpatialReferenceInfo接口
string proLName = proLinearUnit.Name; //该空间参考组件的名称 Meter
string proLAlias = proLinearUnit.Alias; //此空间参考组件的别名 null
string proLAbbreviation = proLinearUnit.Abbreviation; //该空间参考组件的缩写名称 null
string proLRemarks = proLinearUnit.Remarks; //此空间参考组件的注释字符串 null
int proLFactoryCode = proLinearUnit.FactoryCode; //空间参考的工厂代码(WKID) 9001
double proLConversionFactor = proLinearUnit.ConversionFactor; //单位的换算系数(单位为米)1
double proLMetersPerUnit = proLinearUnit.MetersPerUnit; //坐标系的单位米 1
ILinearUnit proZCoordinateUnit = tProCoordSys.ZCoordinateUnit; //Z坐标系 ILinearUnit继承IUnit接口继承ISpatialReferenceInfo接口
if (proZCoordinateUnit != null)
{
string zName = proLinearUnit.Name; //名称
string zAlias = proLinearUnit.Alias; //别名
string zAbbreviation = proLinearUnit.Abbreviation; //缩写
string zRemarks = proLinearUnit.Remarks; //注释字符串
int zFactoryCode = proLinearUnit.FactoryCode; //WKID
double zConversionFactor = proLinearUnit.ConversionFactor; //单位的换算系数(单位为米)
double zMetersPerUnit = proLinearUnit.MetersPerUnit; //坐标系的单位米
}
IProjection pPro = tProCoordSys.Projection; //投影坐标系的地图投影 IProjection继承ISpatialReferenceInfo接口
string pProName = pPro.Name; //该空间参考组件的名称 Gauss_Kruger
string pProAlias = pPro.Alias; //此空间参考组件的别名 null
string pProAbbreviation = pPro.Abbreviation; //该空间参考组件的缩写名称 null
string pProRemarks = pPro.Remarks; //此空间参考组件的注释字符串 null
int pProFactoryCode = pPro.FactoryCode; //空间参考的工厂代码(WKID) 43005
string pProUsage = pPro.Usage; //地图投影的使用说明 null
string pProClassification = pPro.Classification; //地图投影的分类 null
IParameter pParameter = null;
pPro.GetDefaultParameters(ref pParameter); //返回此投影所需的默认参数集 IParameter继承ISpatialReferenceInfo接口
string pParName = pParameter.Name; //该空间参考组件的名称 False_Easting
string pParAlias = pParameter.Alias; //此空间参考组件的别名 null
string pParAbbreviatio = pParameter.Abbreviation; //该空间参考组件的缩写名称 null
string pParRemarks = pParameter.Remarks; //此空间参考组件的注释字符串 null
int pParFactoryCode = pParameter.FactoryCode; //空间参考的工厂代码(WKID) 100001
double pParValue = pParameter.Value; //投影参数的数值 0
int pParIndex = pParameter.Index; //投影坐标系的参数数组中的投影参数的索引 0
}
else if (pSpatialReference is IGeographicCoordinateSystem pGeographic) //是否为地理坐标系
{
string gName = pGeographic.Name; //该空间参考组件的名称 GCS_China_Geodetic_Coordinate_System_2000
string gAlias = pGeographic.Alias; //此空间参考组件的别名 ""
string gAbbreviation = pGeographic.Abbreviation; //该空间参考组件的缩写名称 ""
string gRemarks = pGeographic.Remarks; //此空间参考组件的注释字符串 ""
int gFactoryCode = pGeographic.FactoryCode; //空间参考的工厂代码(WKID) 4490
bool gXY = pGeographic.HasXYPrecision(); //是否定义了(x,y)精度信息 true
bool gZ = pGeographic.HasZPrecision(); //是否定义了z精度信息 true
bool gM = pGeographic.HasMPrecision(); //是否定义了m精度信息 true
string goUsage = pGeographic.Usage; //使用注意事项 ""
ILinearUnit gZCoordinateUnit = pGeographic.ZCoordinateUnit; //Z坐标系 null
if (gZCoordinateUnit != null)
{
string gzName = gZCoordinateUnit.Name; //名称
string gzAlias = gZCoordinateUnit.Alias; //别名
string gzAbbreviation = gZCoordinateUnit.Abbreviation; //缩写
string gzRemarks = gZCoordinateUnit.Remarks; //注释字符串
int gzFactoryCode = gZCoordinateUnit.FactoryCode; //WKID
double gzConversionFactor = gZCoordinateUnit.ConversionFactor; //单位转换系数,转换到米
double gzMetersPerUnit = gZCoordinateUnit.MetersPerUnit; //坐标系单位
}
//地理坐标系由三个参数来定义:角度单位(Angular Unit)、本初子午线(Prime Meridian)和大地测量系统(Datum)
IDatum gDatum = pGeographic.Datum; //这个地理坐标系的水平基准 IDatum继承ISpatialReferenceInfo接口
string gdName = gDatum.Name; //名称 D_China_2000
string gdAlias = gDatum.Alias; //别名 null
string gdAbbreviation = gDatum.Abbreviation; //缩写 null
string gdRemarks = gDatum.Remarks; //注释字符串 null
int gdFactoryCode = gDatum.FactoryCode; //WKID 1043
ISpheroid gdSpheroid = gDatum.Spheroid; //这个水平基准面的球体 ISpheroid继承ISpatialReferenceInfo接口
string gdspName = gdSpheroid.Name; //名称 CGCS2000
string gdspAlias = gdSpheroid.Alias; //别名 null
string gdspAbbreviation = gdSpheroid.Abbreviation; //缩写 null
string gdspRemarks = gdSpheroid.Remarks; //注释字符串 null
int gdspFactoryCode = gdSpheroid.FactoryCode; //WKID 1024
double gdspSemiMajorAxis = gdSpheroid.SemiMajorAxis; //球体的半长轴长度 6378137
double gdspSemiMinorAxis = gdSpheroid.SemiMinorAxis; //该球体的半短轴长度 6356752.3141403561
double GDSPFlattening = gdSpheroid.Flattening; //这个球体的扁率 0.0033528106811823188
IPrimeMeridian gPrimeMeridian = pGeographic.PrimeMeridian; //这个地理坐标系的本初子午线 IPrimeMeridian继承ISpatialReferenceInfo接口
string gpmName = gPrimeMeridian.Name; //名称 Greenwich
string gpmAlias = gPrimeMeridian.Alias; //别名 null
string gpmAbbreviation = gPrimeMeridian.Abbreviation; //缩写 null
string gpmRemarks = gPrimeMeridian.Remarks; //注释字符串 null
int gpmFactoryCode = gPrimeMeridian.FactoryCode; //WKID 8901
double gpmLongitude = gPrimeMeridian.Longitude; //本初子午线的经度值 0
IAngularUnit gAngularUnit = pGeographic.CoordinateUnit; //这个地理坐标系的角度单位。 IAngularUnit继承IUnit接口继承ISpatialReferenceInfo接口
string gAgulardw = gAngularUnit.Name; //该空间参考组件的名称 Degree
string gAAlias = gAngularUnit.Alias; //此空间参考组件的别名 null
string gAAbbreviation = gAngularUnit.Abbreviation; //该空间参考组件的缩写名称 null
string gARemarks = gAngularUnit.Remarks; //此空间参考组件的注释字符串 null
int gAFactoryCode = gAngularUnit.FactoryCode; //空间参考的工厂代码(WKID) 9102
double gAConversionFactor = gAngularUnit.ConversionFactor; //单位的换算系数(单位为米) 0.017453292519943295
double gARadiansPerUnit = gAngularUnit.RadiansPerUnit; //每角度单位的弧度 0.017453292519943295
}
}
若要获取分度带信息:如果带号和中央经线分别用N和L0表示,3分度:L0=3*N,6度分度:L0=6*N-3,在中国境内3度分度带号25-45,6度分度带号13-23,带号大于24是3度分带,小于24是6度分带。
二、获取坐标系
1、从要素类中获取:
public void GetCoordinateSystem(IFeatureClass targetFClass)
{
IGeoDataset tgeoDataset = targetFClass as IGeoDataset; //通过IGeoDataset接口获取FeatureClass坐标系统
ISpatialReference tSpatialRef = tgeoDataset.SpatialReference;
}
2、从几何字段获取
/// <summary>
/// 由自几何字段获取空间参考信息
/// </summary>
/// <param name="geofield">几何字段</param>
public void GetCoordinateSystemByField(IField geofield)
{
IGeometryDef geoDef = geofield.GeometryDef;
ISpatialReference tSpatialRef = geoDef.SpatialReference;
}
3、重要素集中获取
三、创建坐标系
1、从文件获取创建
/// <summary>
/// 从文件获取坐标系
/// </summary>
/// <returns></returns>
public ISpatialReference GetSpatialReferenceByFile()
{
ISpatialReferenceFactory spatialReferenceFactory = new SpatialReferenceEnvironmentClass();
ISpatialReference spatialReference = spatialReferenceFactory.CreateESRISpatialReferenceFromPRJFile("D:\\CGCS 2000.prj");
return spatialReference;
}
2、创建预定义空坐标系
/// <summary>
/// 空坐标系
/// </summary>
/// <returns></returns>
public ISpatialReference EmptySpatialReference()
{
ISpatialReferenceFactory spatialReferenceFactory = new SpatialReferenceEnvironmentClass();
ISpatialReference spatialReference = new UnknownCoordinateSystemClass();
ISpatialReferenceResolution spatialReferenceResolution = (ISpatialReferenceResolution)spatialReference;
spatialReferenceResolution.ConstructFromHorizon();
ISpatialReferenceTolerance spatialReferenceTolerance = (ISpatialReferenceTolerance)spatialReference;
spatialReferenceTolerance.SetDefaultXYTolerance();
return spatialReference;
}
3、创建预定义的地理坐标系
/// <summary>
/// 创建预定义的地理坐标系 使用esriSRGeoCSType,esriSRGeoCS2Type或esriSRGeoCS3Type枚举中的元素作为gcsType来创建特定的预定义地理坐标系。
/// </summary>
/// <returns></returns>
public ISpatialReference GetGeographicCoordinateSystems()
{
ISpatialReferenceFactory spatialReferenceFactory = new SpatialReferenceEnvironmentClass();
esriSRGeoCS3Type geoSystem = esriSRGeoCS3Type.esriSRGeoCS_Xian1980;
ISpatialReferenceResolution spatialReferenceResolution = spatialReferenceFactory.CreateGeographicCoordinateSystem(Convert.ToInt32(geoSystem)) as ISpatialReferenceResolution;
spatialReferenceResolution.ConstructFromHorizon();
ISpatialReferenceTolerance spatialReferenceTolerance = spatialReferenceResolution as ISpatialReferenceTolerance;
spatialReferenceTolerance.SetDefaultXYTolerance();
ISpatialReference spatialReference = spatialReferenceResolution as ISpatialReference;
return spatialReference;
}
4、创建预定义的投影坐标系
/// <summary>
/// 创建预定义的投影坐标系 使用esriSRProjCSType,esriSRProjCS2Type,esriSRProjCS3Type或esriSRProjCS4Type枚举中的元素作为pcsType来创建特定的预定义投影坐标系
/// </summary>
/// <returns></returns>
public ISpatialReference GetProjectedCoordinateSystems()
{
ISpatialReferenceFactory spatialReferenceFactory = new SpatialReferenceEnvironmentClass();
esriSRProjCS4Type proSystem = esriSRProjCS4Type.esriSRProjCS_Xian1980_3_Degree_GK_Zone_35;
ISpatialReferenceResolution spatialReferenceResolution = spatialReferenceFactory.CreateProjectedCoordinateSystem(Convert.ToInt32(proSystem)) as ISpatialReferenceResolution;
spatialReferenceResolution.ConstructFromHorizon();
ISpatialReferenceTolerance spatialReferenceTolerance = spatialReferenceResolution as ISpatialReferenceTolerance;
spatialReferenceTolerance.SetDefaultXYTolerance();
ISpatialReference spatialReference = spatialReferenceResolution as ISpatialReference;
return spatialReference;
}