GIS PROJ4

Proj.4是开源GIS最著名的地图投影库,许多GIS开源软件的投影都直接使用Proj.4的库文件。该项目遵循MIT license,用C语言编写,由USGS的Gerald I. Evenden在1980年代创立并一直维护到退休,后转手到Frank Warmerdam手中。Warmerdam现任OSGeo主席,于2008年5月把Proj.4纳入成为MetaCRS的一部分。Proj.4的主页(http://trac.osgeo.org/proj/ )现亦进入OSGeo,并提供Win32下的预编译文件直接使用,Linux下也有,我本文只介绍Windows下的使用方法,Linux俺不会。4月份还在原来的主页上,并且需要自己编译安装才可使用。

功能主要有经纬度坐标与地理坐标的转换,坐标系的转换,包括基准变换等,下面以命令行方式和编程方式来说明经纬度坐标与地理坐标转换功能的使用。

命令行方式:下载bin压缩包,按照Readme说明用DOS命令将文件夹添加到系统环境变量,之后可用示例数据测试经纬度与平面坐标的转换。(DOS命令不会的自行解决。)用dos命令添加系统环境变量,当此次命令结束,系统环境变量即恢复原状,下次使用仍需要添加。若在“我的电脑”属性里添加系统环境变量,则一次设置可多次使用。

再用一个自定义的复杂示例说明部分命令的用法,示例数据与我介绍.NET开源投影库Proj.NET时使用的数据相同:同学提供投影参数和四个投影坐标,让帮忙转换成经纬度坐标。投影参数:椭球体Krasovsky_1940;Datum:北京1954;投影:兰勃特双标准纬线,25N,47N。坐标数据:20634500,4660000; 20635500,466000; 20634500, 4659000;20635500,4659000 。

 

上图给出了全部过程,最重要的是确定参数以及参数的取值:+proj=lcc +ellps=krass +lat_1=25n +lat_2=47n +lon_0=117e +x_0=20500000 +y_0=0 +units=m +k=1.0,分别代表了投影、椭球体、两条标准纬线、中央经线、东偏移量、北偏移量、单位、比率(scale)等。如果转换到wgs84坐标系,可加上+towgs84=22,-118,30.5,0,0,0,0 (三参数)。-I 代表着从地理坐标到经纬坐标,ctrl + Z 回到命令初始,下面又给出了一个简单的从经纬度到地理坐标系示例,proj 后面没有 -I。

参数名称固定,但参数的取值范围倒没有明确的列表,不过可以通过命令方式查询,譬如-le 列出了椭球体的域(list ellpsoid),-lp则列出了各种投影方式(list project),比瓢画葫芦可完成自己的任务,想了解更多的命令自行参考主页给出的Document。

点坐标太多怎么办?命令行方式也可读入坐标点文件进行批量转换。

编程方式:其他应用Proj.4的开源软件如GDAL、MapServer等使用的应该都是编译好的proj.dll文件。Bin压缩包里的proj.dll我没试验过,但两个月前下载源文件,自己makefile生成安装编译,再编程测试。我VC++不够熟练,当时鼓捣了半天才弄好,步骤如下。

下载源文件包,打开Readme文件按照“Windows Build”下的说明进行编译。Readme文件还有关于新版本变化和编程使用等简略说明。

修改src下的makefile.vc文件。首先把PPROJ_LIB_DIR的参数值设为指向NAD所在的位置,例如我的E:/PROJ4/NAD。其次修改VERSION的参数值为空。最好再自行阅读下makefile文件中的 其他内容,比如最后生成proj_i.lib是动态链接库,而proj.lib是静态的。

用DOS命令nmake /f makefile.vc all 进行编译生成。在这之前,确保nmake可以使用,即需要设置VC++系统环境变量。设置环境变量的方法前面已经默认告诉了两种,VC还可以用VCVARS32.BAT 或vcvarsall.bat 设置。下图在我的机子设置上就差个回车。

 

编译生成之后的src目录下的proj.dll、proj.lib、proj_i.lib,再加上proj_api.h等文件必可为编程所用。同时也可使用proj.exe来用命令完成任务,如前述。

示例程序,数据与上述相同。小白一下,记得引入头文件proj_api.h,把proj.dll、proj_i.lib等文件放到合适的位置,如应用程序的debug下。貌似也可放在Windows/System32下...

#include "proj_api.h"
#include <iostream>
#pragma comment(lib,"..\\debug\\proj_i.lib")
using namespace std;

int main(int argc, char **argv) {
    const char* beijing1954="+proj=lcc +ellps=krass +lat_1=25n +lat_2=47n +lon_0=117e +x_0=20500000 +y_0=0 +units=m +k=1.0";
    //if you want to convert to wgs84 datum
    //"+towgs84=22,-118,30.5,0,0,0,0"
    projUV p;
    projPJ pj;
    
    double xArray[4]={20634500,20635500,20634500,20635500};
    double yArray[4]={4660000,4660000,4659000,4659000};    

    if (!(pj = pj_init_plus(beijing1954))) exit(1);

    for(int i=0; i<4; i++)
    {
        p.u = xArray[i];
        p.v = yArray[i];
        p=pj_inv(p,pj);
        cout.setf(ios_base::fixed);
        p.u/=DEG_TO_RAD;
        p.v/=DEG_TO_RAD;
        cout<<"Beijing 1954:    "<<xArray[i]<<"    "<<yArray[i] <<endl;
        cout<<"pj_inv result:    "<<p.u<<"    "<<p.v<<endl;
    }
    //118d36'39.836"E 40d27'43.476"N; 118d37'22.949"E 40d27'42.926"N; 118d36'39.119"E 40d27'10.545"N; 118d37'22.227"E 40d27'9.995"N
    //118.611065,40.462077,118.623041,40.461924,118.610866,40.452929,118.622841,40.452777
    pj_free(pj);
    exit(0);

    return 0;
}

更多函数原型的用法,如pj_init、pj_init_plus、pj_fwd、pj_inv、pj_transform、pj_free等,参考api简单说明或文档。

你可能感兴趣的:(编程,windows,linux,dos,任务,makefile)