之前写了不少关于GDAL编译的文章,但是没有一次是完整记录的,主要是因为可参考的文章很多,但是想来想去,还是整理一份完整的文章吧。
本文将详细介绍使用VS2015完整编译x64版本GDAL+PROJ+GEOS并测试各模块,附上完整的测试代码,供需要的人参考。
准备工作:
源代码,去官网下载,也可以直接下载我已经整理好的代码,官方源码打包,没有任何修改,压缩包的名字都没有改过。
gdal244_vs2015.rar - 蓝奏云文件大小:19.5 M|https://autumoon.lanzouq.com/iYMekypyk9c将文件直接解压到C盘根目录,如下图所示:
然后分别解压到当前目录,得到如下结果:
然后下载下面已经修改好的opt文件,直接覆盖到上方的解压目录,如果想了解详细修改了什么,逐个对照opt文件就可以了。
gdal244_vs2015_opts.rar - 蓝奏云文件大小:14.5 K|https://autumoon.lanzouq.com/iZLrwyq06ij
开始编译
先编译geos:
在开始菜单中找到Visual Studio 2015的工具,vs2015本机工具命令提示,打开。切换到geos所在的目录,输入命令:
nmake /f makefile.vc
然后是测试,测试代码如下:
//author:autumoon
//联系QQ:4589968
//日期:2022-01-13
// GeosTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "GeosTest.h"
#include "geos/include/geos.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 唯一的应用程序对象
CWinApp theApp;
using namespace std;
void test();
string str(bool flag);
int main(int argc,char *argv[])
{
test();
system("pause");
return 1;
}
void test()
{
cout<<"GEOS库版本为:"<<GEOS_VERSION<<endl;
typedef Coordinate PT;
GeometryFactory::Ptr factory = GeometryFactory::create();
CoordinateArraySequenceFactory csf; //构建第一个矩形p1
CoordinateSequence* cs1 = csf.create(5,2);//五个2维点,第三维度z始终为0
cs1->setAt(PT(0,0),0);
cs1->setAt(PT(3,0),1);
cs1->setAt(PT(3,3),2);
cs1->setAt(PT(0,3),3);
cs1->setAt(PT(0,0),4); //与第一个点相等,构成闭合
LinearRing* ring1 = factory->createLinearRing(cs1); //点构成线
Geometry* p1 = factory->createPolygon(ring1,NULL); //线构成面
CoordinateSequence* cs2 = csf.create(5,2); //构建一个四边形p2
cs2->setAt(PT(2,2),0);
cs2->setAt(PT(4,5),1);
cs2->setAt(PT(5,5),2);
cs2->setAt(PT(5,4),3);
cs2->setAt(PT(2,2),4);
LinearRing * ring2 = factory->createLinearRing(cs2);
Geometry* p2 = (factory->createPolygon(ring2,NULL));
CoordinateSequence *cs3 = new CoordinateArraySequence(); //构建一个三角形p3
int xoffset=4,yoffset=4,side=2;
cs3->add(PT(xoffset, yoffset));
cs3->add(PT(xoffset, yoffset+side));
cs3->add(PT(xoffset+side, yoffset+side));
cs3->add(PT(xoffset, yoffset));
LinearRing * ring3 = factory->createLinearRing(cs3);
Geometry* p3 = (factory->createPolygon(ring3,NULL));
bool flag12=p1->intersects(p2);
bool flag13=p1->intersects(p3);
bool flag23=p2->intersects(p3);
cout<<"图1与图2:"<<str(flag12)<<endl;
cout<<"图1与图3:"<<str(flag13)<<endl;
cout<<"图2与图3:"<<str(flag23)<<endl;
factory->destroy();
}
string str(bool flag)
{
string result=(flag==true)?"相交":"不相交";
return result;
}
正常输出:
接着编译proj:
输入编译指令。(每一行输入完毕,回车执行后再输入下一行。注意空格。)
nmake /f makefile.vc
nmake /f makefile.vc install-all
nmake /f makefile.vc
测试proj:
// PROJ4Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "PROJ4Test.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 唯一的应用程序对象
CWinApp theApp;
using namespace std;
#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;
}
正常输出:
编译GDAL:
nmake /f makefile.vc
nmake /f makefile.vc install
nmake /f makefile.vc devinstall
测试GDAL:
#include <iostream>
#include "gdal.h"
#include "gdal_priv.h"
#include "ogr_spatialref.h"
using namespace std;
int main(int argc, char* argv[])
{
//if (argc < 2) return -1;
GDALAllRegister();
OGRRegisterAll();
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); //设置支持中文路径
string gdal_data_path = "D:\\MyItems\\Image\\cmdGDALxp\\cmdGDAL\\gdal\\data";
CPLSetConfigOption("GDAL_DATA", gdal_data_path.c_str());
OGRSpatialReference spatialReference;
OGRErr oerr = spatialReference.importFromEPSG(4326);//WGS84
std::cout << "err = " << oerr;
auto errMsg = CPLGetLastErrorMsg();
std::cout << errMsg;
getchar();
return 0;
}
注意其中的gdal_data_path路径设置可能不同,正常情况下err = 0;