Proj.4庫的編譯及使用
Proj.4是開源GIS最著名的地圖投影庫,GRASS GIS, MapServer, PostGIS, Thuban, OGDI, Mapnik, TopoCad, GDAL/OGR等軟體的投影都直接或間接的使用Proj.4。
Proj.4的功能主要有經緯度坐标與地理坐标的轉換,坐标系的轉換,包括基準變換等,下面以指令行方式和程式設計方式來說明經緯度坐标與地理坐标轉換功能的使用。
Proj.4的下載下傳和編譯
使用git進行下載下傳。
git clone https://github.com/OSGeo/proj.4.git
Linux下的編譯和安裝
下載下傳之後,使用cmake生成Makefile進行編譯。
mkdir -p build &&cd build #進入proj.4工程目錄後,建立一個建構目錄,并進入
# 使用cmake生成Makefile,指定安裝路徑和生成庫類型為靜态庫
cmake -DCMAKE_INSTALL_PREFIX=./install -DBUILD_LIBPROJ_SHARED=OFF ..
# 編譯
make
# 安裝,安裝的目錄是之前指定的目錄,就是目前目錄下的install目錄
make install
安裝完成之後進入install目錄,可以看到對應的頭檔案和庫檔案。
> tree
.
├── bin
│ ├── cs2cs
│ ├── geod
│ ├── nad2bin
│ └── proj
├── include
│ ├── geodesic.h
│ ├── proj_api.h
│ └── projects.h
├── lib
│ └── libproj.a
└── share
├── cmake
│ └── PROJ4
│ ├── proj4-config.cmake
│ ├── proj4-config-version.cmake
│ ├── proj4-targets.cmake
│ └── proj4-targets-release.cmake
├── man
│ ├── man1
│ │ ├── cs2cs.1
│ │ ├── geod.1
│ │ └── proj.1
│ └── man3
│ ├── geodesic.3
│ └── pj_init.3
└── proj
├── CH
├── epsg
├── esri
├── esri.extra
├── GL27
├── IGNF
├── nad27
├── nad83
├── nad.lst
├── ntf_r93.gsb
├── null
├── nzgd2kgrid0005.gsb
├── other.extra
├── proj_def.dat
└── world
10 directories, 34 files
Windows下使用VS2013進行編譯
先使用cmake生成VS工程
cd build # 先進入build目錄
# 下面設定了安裝目錄和編譯參數等
cmake -DCMAKE_INSTALL_PREFIX=D:/proj.4 -DBUILD_LIBPROJ_SHARED=OFF -G"Visual Studio 12 Win64" ..
打開VS2013 x64本機指令行工具,然後進入build目錄,執行下面指令
msbuild ALL_BUILD.vcxproj /p:Configuration="Release"
msbuild INSTALL.vcxproj /p:Configuration="Release"

編譯安裝完成後,可以進入D:\Proj.4目錄檢視輸出的頭檔案和庫檔案(以及share目錄下的一些資料檔案)。
使用Proj.4庫
使用以下代碼來做測試
#include <stdio.h>
#include <stdlib.h>
#include "proj_api.h"
int main()
{
// 定義一個北京54的橫軸墨卡托投影坐标系
// +proj=lcc 投影類型:橫軸墨卡托投影
// +ellps=krass 橢球體
// +lat_1=25n +lat_2=47n 次元範圍(标準緯線)
// +lon_0=117e 中央經度為東經117度
// +x_0=20500000 X軸(東)方向偏移量
// +y_0=0 Y軸(北)方向偏移量
// +units=m 機關
// +k=1.0 比率
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";
//如果你想轉換到WGS84基準
//"+towgs84=22,-118,30.5,0,0,0,0"
projPJ pj; // 坐标系對象指針
// 初始化坐标系對象
if (!(pj = pj_init_plus(beijing1954))){
exit(-1); // 初始化失敗,退出程式
}
// 待轉換的坐标(投影坐标)
// 注意坐标系定義中的+x_0=20500000,坐标值應該也是帶有帶号的
projUV parr[4] = {
{20634500.0,4660000.0},
{20635000.0,4661000.0},
{20635500.0,4659000.0},
{20634000.0,4662000.0}
};
printf("DEG_TO_RAD = %f (1度=%f弧度)\n",DEG_TO_RAD,DEG_TO_RAD);
// 逐點轉換
for(int i=0; i<4; i++)
{
printf("\n--------------轉換第%d點---------------\n",i+1);
projUV p;
p = pj_inv(parr[i],pj); // 投影逆變換(投影坐标轉經緯度坐标)
printf("北京54投影 坐标:%10lf,%10lf\n",parr[i].u,parr[i].v);
printf("北京54經緯度坐标:%10lf,%10lf\n",p.u/DEG_TO_RAD,p.v/DEG_TO_RAD); // 輸出的時候,将弧度轉換為度
p = pj_fwd(p,pj); // 投影正變換(經緯度坐标轉投影坐标)
printf("北京54投影 坐标:%10lf,%10lf\n",p.u,p.v);
}
// 釋放投影對象記憶體
pj_free(pj);
return 0;
}
編譯的時候,需要連結pthread和m兩個庫,因為前面編譯的時候,生成的是靜态庫。如果生成的是動态庫,則是不需要的。
test.c在install目錄下寫的,是以指定的路徑是如下的。
gcc test.c -Iinclude -Llib -lproj -lpthread -lm -o test
運作結果如下:
> ./test
DEG_TO_RAD = 0.017453 (1度=0.017453弧度)
--------------轉換第1點---------------
北京54投影 坐标:20634500.000000,4660000.000000
北京54經緯度坐标:118.611065, 40.462077
北京54投影 坐标:20634500.000000,4660000.000000
--------------轉換第2點---------------
北京54投影 坐标:20635000.000000,4661000.000000
北京54經緯度坐标:118.617253, 40.471148
北京54投影 坐标:20635000.000000,4661000.000000
--------------轉換第3點---------------
北京54投影 坐标:20635500.000000,4659000.000000
北京54經緯度坐标:118.622841, 40.452777
北京54投影 坐标:20635500.000000,4659000.000000
--------------轉換第4點---------------
北京54投影 坐标:20634000.000000,4662000.000000
北京54經緯度坐标:118.605475, 40.480447
北京54投影 坐标:20634000.000000,4662000.000000