坐标详解与PROJ.4使用说明
sf2gis
2013年11月18日
2014年10月23日抽取坐标系统为单独文档
The European Petroleum Survey Group:欧洲石油调查组织http://www.epsg.org/。维护空间参考系统,OGC以其为标准。其中所有的独立内容都有相应的ID。
参考:http://hi.baidu.com/liongg/item/318820d21fa73fe6b2f7776d。
参见:..\GIS\投影系统坐标系统大地测量DATUM基准面详解.docx
Proj.4是开源GIS最著名的地图投影库,许多GIS开源软件的投影都直接使用Proj.4的库文件。该项目遵循MIT license,用C语言编写,由USGS的Gerald I. Evenden在1980年代创立并一直维护到退休,后转手到Frank Warmerdam手中。Warmerdam现任OSGeo主席,于2008年5月把Proj.4纳入成为MetaCRS的一部分。需要自己编译安装才可使用。
功能主要有经纬度坐标与地理坐标的转换,坐标系的转换,包括基准变换等,下面以命令行方式和编程方式来说明经纬度坐标与地理坐标转换功能的使用。
1. 球面坐标与投影坐标
proj [-control] [+control] [files]
-:表示输出控制。
+:表示设定投影参数。
CTRL+Z退出。
正常情况:从球面坐标到投影坐标。
-I:从投影坐标到球面坐标。
1) 正常情况
输入:X(经度),Y(纬度)
输出:X(水平方向坐标) Y(垂直方向坐标)
2) 反向转换
输入:X(水平方向坐标) Y(垂直方向坐标)
输出:X(经度),Y(纬度)
2. 坐标与距离
geod –control +control
-:表示输出控制。
+:表示设定投影参数。
CTRL+Z退出。
正常情况:根据起点,以及距离起点的角度和距离,确定终点的坐标以及终点到起点的角度。
-I:根据起点和终点的坐标,确定起点到终点的角度,终点到起点的角度、距离。
1) 正常情况
输入:X(起点纬度) Y(起点经度) A(起点到终点角度) D(起点到终点距离)
输出:X(终点纬度) Y(终点经度) A(终点到起点角度)
2) 反向转换
输入:X(起点纬度) Y(起点经度) X(终点纬度) Y(终点经度)
输出:A(起点到终点角度) A(终点到起点角度) D(起点到终点距离)
+proj=name:定义投影坐标系统名称
+ellips=name:定义椭球体。
+lon_0=n:定义中央经线。
+lat_1=n:定义标准纬线1。
+lat_2=n:定义标准纬线2。
+x_0=n:定义东移距离。
+y_0=n:定义南移距离。
+k=n:定义缩放倍数。
+init=文件路径<关键字>:文件路径是存放坐标系统定义的文件,关键字用于标识坐标系统。
自定义坐标系统:<坐标系统关键字>……(坐标定义)<>(结束标识)。就可以将定义的坐标系统保存到文件中,
http://hi.baidu.com/liongg/item/838f7c9e8e6ae1dc1e42716d
#define RAD_TO_DEG 57.29577951308232//1弧度转换为角度
#define DEG_TO_RAD .0174532925199432958//1角度转换为弧度
projPJ:void *型指针,用于表示一个投影类型,对于地理坐标,也使用这个类型,定义时使用’+proj=name +ellps’定义。
projPJ pj_init_plus(const char *);//用于生成projPJ类型的指针。成功返回指针,失败返回NULL
int pj_transform(src,des,count,offset,x,y,z);//src:源坐标系统,des:目标坐标系统,count:点数目,offset:起始索引,x,y,z:经度,纬度,高度的数组地址。成功返回0,失败返回错误代码。
void pj_free(projPJ pj);//释放当前的坐标系统。
int pj_is_latlong(projPJ pj);//如果定义时使用+proj=latlong,则返回TRUE(在Windows下)。
int pj_is_geocent(projPJ pj);//如果定义时使用+proj=geocent,则返回TRUE(在Windows下)。
projPJ pj_latlong_from_proj(projPJ pj);//返回pj投影对应的地理坐标系。
char *pj_get_def(projPj pj,int option);// option是保留参数。返回pj的定义。
char *pj_strerrno(int errno);//返回errno对应的错误号的详细内容。
int *pj_get_errno_ref(void);//返回当前的错误号。
const char*pj_get_release();//返回当前版本信息。
//以下内容未使用
void pj_set_finder( const char *(*)(const char *) );//设置一个自定义函数指针用于查找偏移文件。
void pj_set_searchpath ( int count, const char **path );//设置偏移文件查询目录
void pj_deallocate_grids(void);//释放偏移文件相关的资源
voidpj_set_finder( const char *(*new_finder)(const char *) );
Install a customfunction for finding init and grid shift files.
voidpj_set_searchpath ( int count, const char **path );
Set a list ofdirectories to search for init and grid shift files.
voidpj_deallocate_grids( void );
Frees all resourcesassociated with loaded and cached datum shift grids.
#include
#include
#include
#pragma comment(lib,"proj_i.lib")
intmain()
{
projPJ pjAlbers,pjGeog;
pjAlbers = pj_init_plus("+proj=aea +ellps=krass +lon_0=105E +lat_1=25N+lat_2=47N");
//pjGeog =pj_init_plus("+proj=latlong +ellps=krass");
pjGeog = pj_latlong_from_proj(pjAlbers);//与上面进行定义是一样的
char *def =pj_get_def(pjGeog,0);
BOOL bGeocCS = pj_is_geocent(pjGeog);//if(proj==geocent)
BOOL bLatLon = pj_is_latlong(pjGeog);//if(proj==latlong)
if(pjGeog ==NULL)
{
printf("GeographicCS ERROR.\n");
}
doublex,y,z;
x=115*DEG_TO_RAD;
y=25*DEG_TO_RAD;
z=0;
pj_transform(pjGeog,pjAlbers,1,1,&x,&y,&z);
printf("x=%f,y=%f,z=%f",x,y,z);//output:x=1007811.777087,y=2664818.734406,z=0.000000
const char *strRelease = pj_get_release();
char*strError = pj_strerrno(2);
int iErrorNo= *pj_get_errno_ref();
pj_free(pjAlbers);//release
return 0;
}
http://trac.osgeo.org/proj/wiki/ProjAPI
在OGR中,使用两个类进行坐标相关操作,OGRSpatialReference和OGRCoordinateTransformation。都使用WKT进行坐标表示。
封装了所有坐标系统的信息。主要使用两种坐标系统:地理坐标系统(GEOGCS)和投影坐标系统(PROJCS)。投影坐标系统依赖一个地理坐标系统。
需要参数:DATUM,中央经线,角度单位。
DATUM(大地基准面,由椭球(椭球由长半轴及扁率确定)及其调整确定),prime median(中央经线,一般是Greenwich),angleunit(角度单位,一角度代表多少弧度)。
有三种方法:SetGeogCS()、SetWellKnownGeogCS()、importFromWkt()。
1. SetGeogCS():生成一种地理坐标系统,或用于生成投影系统的地理坐标系统。
SetGeogCS(坐标系统名称,DATUM名称,椭球体名称,长半轴,扁率,中央经线名称,中线经线偏离Greenwich的度数,单位,单位与弧度的转换)。
示例:
OGRSpatialReference *pMySR = new OGRSpatialReference;
pMySR->SetGeogCS("MyGeogCS","MyWGS_1984","MyWGS 84 Spheriod",SRS_WGS84_SEMIMAJOR,SRS_WGS84_INVFLATTENING,SRS_PM_GREENWICH,0.0,SRS_UA_DEGREE,atof(SRS_UA_DEGREE_CONV));
char *pCS = new char[100];
pMySR->exportToWkt(&pCS);
输出:pCS=
GEOGCS["MyGeogCS",DATUM["MyWGS_1984",SPHEROID["MyWGS 84 Spheriod",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]]
2. SetWellKnownGeogCS():使用常用坐标系统。
对于一些常用的坐标系统,可以直接使用SetWellKnownGeogCS()。包括
示例:
OGRSpatialReference *pMySR = new OGRSpatialReference;
pMySR->SetWellKnownGeogCS("EPSG:4326");
char *pCS = new char[100];
pMySR->exportToWkt(&pCS);
输出:pCS=
GEOGCS["WGS84",DATUM["WGS_1984",SPHEROID["WGS84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]
WGS84的输出(与EPSG数值完全相同,但ID不同)
GEOGCS["WGS84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9108"]],AUTHORITY["EPSG","4326"]]
3. 导入WKT格式坐标系统
也可以使用exportToWkt(&txt)将当前的坐标系统导出为WKT格式。使用importFromWkt()可以使用wkt格式的坐标系统生成对象。
示例:
OGRSpatialReference *pMySR = new OGRSpatialReference;
char *pCSWKT= "GEOGCS[\"MyGeogCS\",DATUM[\"MyWGS_1984\",SPHEROID[\"MyWGS 84 Spheriod\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]";
pMySR->importFromWkt(&pCSWKT);
char *pCS = new char[100];
pMySR->exportToWkt(&pCS);
输出:pCS= 同1。
投影坐标系统依赖一个地理坐标系统,所有在定义投影坐标系时,应该定义相应的地理坐标系。
当前的OGR应该先定义地理坐标系,再定义投影坐标系。
可以定义投影的各个参数,也可以使用预定义的几个常用的投影方法,如SetTM()、SetMecator()、SetLCC()、SetUTM()。
也可以使用投影坐标系的地理坐标系来生成一个地理坐标系(主要用于投影坐标与相应地理坐标之间的转换)。
示例:
OGRSpatialReference *pMySR = new OGRSpatialReference;
pMySR->SetProjCS("MyProjCS");
pMySR->SetWellKnownGeogCS("NAD27");
pMySR->SetUTM(17,TRUE);
char *pCS = new char[100];
pMySR->exportToWkt(&pCS);
输出:pCS=
PROJCS["MyProjCS",GEOGCS["WGS84",DATUM["WGS_1984",SPHEROID["WGS84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9108"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-81],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["Meter",1]]
判断:IsGeocentic()、IsGeographic()、IsProjected()。
查询:GetSemiMajor()、GetSemiMinor()、GetInvFlatting()、GetAttrValue()(可以获取所有WKT中节点的值)等查询函数)、GetProjParm()(获取投影参数)、GetLinearUnits()(获取与线性单位的名称及与米的转换值)。
其它相关函数,参考API。
在OGR中没有API用于保存Shape文件的.prj文件。需要使用文件操作功能,将改变为esri格式的wkt格式的文本保存到.prj文件中。
示例
voidCLayer::setLayerGeogCS(const CString&strGeogCS,const CString &strLayerPath)
{
IConvertCString *pConvertCString = NULL;
getConvertCString(&pConvertCString);
char*pGeogCS = NULL;
pConvertCString->toChar(strGeogCS,pGeogCS);
OGRSpatialReference *pSR = new OGRSpatialReference;
char*pShpPrj;
pSR->SetWellKnownGeogCS(pGeogCS);
//save to esri
OGRErr errMorph = pSR->morphToESRI();
CString strPrjPath = strLayerPath + TEXT(".prj");
char*pPrjPath;
pConvertCString->toChar(strPrjPath,pPrjPath);
FILE *fPrj = fopen(pPrjPath,"w");
fprintf(fPrj,pShpPrj);
fclose(fPrj);
//release
deletepConvertCString;
pConvertCString = NULL;
return;
}
参考
http://osgeo-org.1560.x6.nabble.com/gdal-dev-OGR-L-SetSpatialRef-td3745413.html
用于坐标转换,需要PROJ4。
OGRCoordinateTransformation *OGRCreaterCoordinateTransformation(源坐标系,目标坐标系);//生成转换对象。成功,返回指针;失败,返回NULL。
OGRCoordinateTransformation::Transform():转换。成功返回TRUE,失败返回FALSE。
OGRCoordinateTransformation::GetSourceCS()、GetTargetCS():返回坐标系。
void DestroyCT(CT):dll内部销毁CT。
示例:
OGRSpatialReference *pMyProjCS = new OGRSpatialReference;
pMyProjCS->SetProjCS("UTM");
pMyProjCS->SetWellKnownGeogCS("EPSG:4326");
pMyProjCS->SetUTM(48,TRUE);
char *pProj;
pMyProjCS->exportToWkt(&pProj);
OGRSpatialReference *pMyGeogCS =pMyProjCS->CloneGeogCS();
OGRCoordinateTransformation *pCT = NULL;
pCT =OGRCreateCoordinateTransformation(pMyGeogCS,pMyProjCS);
if(pCT ==NULL)
{
OutputDebugStringA("Creater CT Failed.\n");
}
double x,y;
x = 116;//1480387.65
y = 37;//4151911.82
pCT->Transform(1,&x,&y);
OGRCoordinateTransformation::DestroyCT(pCT);
OGRSpatialReference *pMySR = new OGRSpatialReference;
CreateNew
//pMySR->SetGeogCS("MyGeogCS","MyWGS_1984","MyWGS 84 Spheriod",SRS_WGS84_SEMIMAJOR,SRS_WGS84_INVFLATTENING,SRS_PM_GREENWICH,0.0,SRS_UA_DEGREE,atof(SRS_UA_DEGREE_CONV));
WellKnown
//pMySR->SetWellKnownGeogCS("EPSG:4326");//("WGS84");
WKT
//char *pCSWKT = "GEOGCS[\"MyGeogCS\",DATUM[\"MyWGS_1984\",SPHEROID[\"MyWGS 84Spheriod\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]";
//pMySR->importFromWkt(&pCSWKT);
pMySR->SetProjCS("MyProjCS");
pMySR->SetWellKnownGeogCS("");
pMySR->SetUTM(17,TRUE);
char *pCS = new char[100];
pMySR->exportToWkt(&pCS);
BOOL bGeocCS = pMySR->IsGeocentric();
BOOL bGeogCS = pMySR->IsGeographic();
BOOL bProjCS = pMySR->IsProjected();
doubledMajor = pMySR->GetSemiMajor();
doubledMinor = pMySR->GetSemiMinor();
double dInvF= pMySR->GetInvFlattening();
const char *strSpheroid = pMySR->GetAttrValue("SPHEROID");
double dCM =pMySR->GetProjParm(SRS_PP_CENTRAL_MERIDIAN);
char*strUnits;
double dLM =pMySR->GetLinearUnits(&strUnits);
OGRSpatialReference *pMyProjCS = new OGRSpatialReference;
pMyProjCS->SetProjCS("UTM");
pMyProjCS->SetWellKnownGeogCS("EPSG:4326");
pMyProjCS->SetUTM(48,TRUE);
char *pProj;
pMyProjCS->exportToWkt(&pProj);
OGRSpatialReference *pMyGeogCS =pMyProjCS->CloneGeogCS();
OGRCoordinateTransformation *pCT = NULL;
pCT =OGRCreateCoordinateTransformation(pMyGeogCS,pMyProjCS);
if(pCT ==NULL)
{
OutputDebugStringA("Creater CT Failed.\n");
}
double x,y;
x = 116;//1480387.65
y = 37;//4151911.82
pCT->Transform(1,&x,&y);
OGRCoordinateTransformation::DestroyCT(pCT);
http://www.gdal.org/ogr/osr_tutorial.html