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