1. 正文

GDAL可以支持将KML作为矢量文件文件读取,但是需要在编译的时候添加第三方库的支持,否则默认的编译结果是还是会不识别这种格式。

查阅官方文档发现有两种驱动可以支持KML:一种驱动名称是KML,需要Expat库的支持,这是一个解析XML格式的库;另一种驱动名称是LIBKML,需要LibKML库的支持,这是google自己的KML读写库。第二种方式支持的功能更多,并且LibKML本身也需要Expat库的支持。如果两种驱动都存在,那么在读取的时候第二种会覆盖第一种,也就是采用LIBKML的方式读取KML。我这里就是顺手把两种驱动都添加进去了。

阅读这篇文章之前需要预先知道GDAL是如何编译的,可参看《Win64下编译集成GEOS和Proj4的GDAL》

1.1. 编译LibKML

LibKML的源码托管在GitHub(可点击点击进入)。下载解压后可在其根目录找到libkml.sln这个文件,通过这个文件可以在visual studio中打开,然后直接编译就可以了。总结下在编译过程中我遇到的问题:

1.1.1. 第三方库支持

LibKML的源码文件夹中已经自带了其需要的第三方库,如下图所示:

LibKML这个静态库挺奇怪,只需要包含第三方对应的头文件即可编译了,所以如果编译的时候提示找不到头文件,可以自己把包含目录重新设置一下,如下图所示。这种问题一般都是包含目录的相对路径出错或者缺失造成的。

1.1.2. 编译错误

在编译libkmlbase这个库的file_win32.cc这个文件的时候,提示这段代码出错:

// Internal to the win32 file class. We need a conversion from string to
// LPCWSTR.
static std::wstring Str2Wstr(const string& str) {
std::wstring wstr(str.length(), L'');
std::copy(str.begin(), str.end(), wstr.begin());
return wstr;
} // Internal to the win32 file class. We need a conversion from std::wstring to
// string.
string Wstr2Str(const std::wstring& wstr) {
size_t s = wstr.size();
string str(static_cast<int>(s+1), 0);
WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), static_cast<int>(s), &str[0],
static_cast<int>(s), NULL, NULL);
return str;
}

出错的地方在std::wstring wstr(str.length(), L'')这一行,错误提示是“error C2137: 空字符常量”。其实就是C/C++没有定义“空字符常量”,L''这种写法不太标准,将其改成L' '就可以了。同时这段代码还存在另一个问题:这段代码的意思是字符串wstring和字符串string互相转换,但是很明显这种写法是不支持中文字符的。我这里就将这段代码替换为:

//改动:
//str 与 wstr 的互转
static std::wstring Str2Wstr(const string& str)
{
size_t i;
std::string curLocale = setlocale(LC_ALL, NULL);
setlocale(LC_ALL, "chs");
const char* _source = str.c_str();
size_t _dsize = str.size() + 1;
wchar_t* _dest = new wchar_t[_dsize];
wmemset(_dest, 0x0, _dsize);
mbstowcs_s(&i, _dest, _dsize, _source, _dsize);
std::wstring result = _dest;
delete[] _dest;
setlocale(LC_ALL, curLocale.c_str());
return result;
}
string Wstr2Str(const std::wstring& wstr)
{
size_t i;
std::string curLocale = setlocale(LC_ALL, NULL);
setlocale(LC_ALL, "chs");
const wchar_t* _source = wstr.c_str();
size_t _dsize = 2 * wstr.size() + 1;
char* _dest = new char[_dsize];
memset(_dest, 0x0, _dsize);
wcstombs_s(&i, _dest, _dsize, _source, _dsize);
std::string result = _dest;
delete[] _dest;
setlocale(LC_ALL, curLocale.c_str());
return result;
}

1.2. 配置GDAL

修改GDAL的编译配置文件nmake.opt,找到LibKML部分,修改为:

# Uncomment out the following lines to enable LibKML support.
#LIBKML_DIR = C:/Dev/libkml
#LIBKML_INCLUDE = -I$(LIBKML_DIR)/src -I$(LIBKML_DIR)/third_party/boost_1_34_1
#LIBKML_LIBRARY = $(LIBKML_DIR)/msvc/Release
#LIBKML_LIBS = $(LIBKML_LIBRARY)/libkmlbase.lib \
# $(LIBKML_LIBRARY)/libkmlconvenience.lib \
# $(LIBKML_LIBRARY)/libkmldom.lib \
# $(LIBKML_LIBRARY)/libkmlengine.lib \
# $(LIBKML_LIBRARY)/libkmlregionator.lib \
# $(LIBKML_LIBRARY)/libkmlxsd.lib \
# $(LIBKML_LIBRARY)/minizip_static.lib \
# $(LIBKML_DIR)/third_party\expat.win32/libexpat.lib \
# $(LIBKML_DIR)/third_party\uriparser-0.7.5.win32/release/uriparser.lib \
# $(LIBKML_DIR)/third_party\zlib-1.2.3.win32/lib/minizip.lib \
# $(LIBKML_DIR)/third_party\zlib-1.2.3.win32/lib/zlib.lib
LIBKML_DIR = C:/Work/GDALBuild/libkml-master
LIBKML_INCLUDE = -I$(LIBKML_DIR)/src -I$(LIBKML_DIR)/third_party/boost_1_34_1
LIBKML_LIBRARY = $(LIBKML_DIR)/x64/Release
LIBKML_LIBS = $(LIBKML_LIBRARY)/libkmlbase.lib \
$(LIBKML_LIBRARY)/libkmlconvenience.lib \
$(LIBKML_LIBRARY)/libkmldom.lib \
$(LIBKML_LIBRARY)/libkmlengine.lib \
$(LIBKML_LIBRARY)/libkmlregionator.lib \
$(LIBKML_LIBRARY)/libkmlxsd.lib \
$(LIBKML_DIR)/third_party/zlib-1.2.3/contrib/minizip/x64/Release/minizip_static.lib \
$(EXPAT_DIR)/build/Release/libexpat.lib \
$(LIBKML_DIR)/third_party/uriparser-0.7.5/win32/uriparser.lib \
$(LIBKML_DIR)/third_party\zlib-1.2.3.win32/lib/minizip.lib \
$(LIBKML_DIR)/third_party\zlib-1.2.3.win32/lib/zlib.lib

这里的目录设置可能每个人有点不太一样,注意不要硬抄根据实际情况修改下。具体来说LIBKML_DIR定义的一个根目录,通过这个目录依次找到:LIBKML_INCLUDE包含的头文件目录;LIBKML_LIBRARY依赖的库文件目录;LIBKML_LIBS具体的每一个lib。

minizip_static.lib这个文件可能没有直接提供,但是是有源代码的,可以自己编译一下:

libexpat.lib文件也有点不同,宏(EXPAT_DIR)来自于Expat部分:

# Uncomment for Expat support (required for KML, GPX and GeoRSS read support).
#EXPAT_DIR = "C:\Program Files\Expat 2.0.1"
#EXPAT_INCLUDE = -I$(EXPAT_DIR)/source/lib
#EXPAT_LIB = $(EXPAT_DIR)/bin/libexpat.lib
EXPAT_DIR = "C:\Work\GDALBuild\libexpat-master"
EXPAT_INCLUDE = -I$(EXPAT_DIR)/expat/lib
EXPAT_LIB = $(EXPAT_DIR)/build/Release/libexpat.lib

这个Expat部分理论上是可以用third_party中已经编译好的头文件和lib的,但是我这里并没有详细求证,因为我是先配置好Expat再配置LibKML的,Expat是自己编译的。

1.3. 链接问题

在编译链接GDAL的过程中,出现了形如“无法解析的外部符号“这种类型的错误,如下所示:

这是由于LibKML默认工程中包含的文件不全,GDAL在编译链接的时候找不到实现造成的。只需要搜索无法解析的函数所在的文件,将其加入到LibKML的工程中,重新编译LibKML和GDAL就可以了。我这里缺失的文件有:

  1. libkmldom工程:xal.h、xal.cc、gx_timeprimitive.h、gx_timeprimitive.cc、gx_tour.h、gx_tour.cc
  2. libkmlbase工程: zip_file.h、zip_file.cc、uri_parser.cc、xml_namespaces.h、xml_namespaces.cc
  3. libkmlengine工程:id_mapper.h、id_mapper.cc、find_xml_namespaces.h、find_xml_namespaces.cc

2. 参考

[1] gdal集成kml库的做法

[2] 解决gdal集成libkml的链接错误

[2] std::wstring

GDAL集成对KML文件的支持的更多相关文章

  1. gdal集成kml库的做法

    作者:朱金灿 来源:http://blog.csdn.net/clever101 最近要读取kml文件,具体就是把kml文件当作一个矢量文件来读取.我发现gdal是支持集成kml库的.不过集成这个km ...

  2. 使用C#版本的gdal库打开hdf文件

    作者:朱金灿 来源:http://blog.csdn.net/clever101 最近应同事的请求帮忙研究下使用C#版的gdal库读取hdf文件,今天算是有一点成果,特地做一些记录. 首先是编译C#版 ...

  3. c#两种方式调用google地球,调用COM API以及调用GEPLUGIN 与js交互,加载kml文件,dae文件。将二维高德地图覆盖到到三维谷歌地球表面。

    网络上资源很多不全面,自己在开发的时候走了不少弯路,在这里整理了最全面的google全套开发,COM交互,web端交互.封装好了各种模块功能. 直接就可以调用. 第一种方式:调用COMAPI实现调用g ...

  4. nginx+tomcat+二级域名静态文件分离支持mp4视频播放配置实例

    nginx+tomcat+二级域名静态文件分离支持mp4视频播放配置实例 二级域名配置 在/etc/nginx/conf.d/目录下配置二级域名同名的conf文件,路径改成对应的即可 statics. ...

  5. Spring集成Hibernate映射文件的4种方式

    概要: 在Spring的applicationContext.xml中集成Hibernate映射文件,通常是在<sessionFactory>这个Bean实例中进行的,若配置的映射文件较少 ...

  6. hadoop对于压缩文件的支持及算法优缺点

    hadoop对于压缩文件的支持及算法优缺点   hadoop对于压缩格式的是透明识别,我们的MapReduce任务的执行是透明的,hadoop能够自动为我们 将压缩的文件解压,而不用我们去关心. 如果 ...

  7. Java操作属性文件,支持新增或更新多个属性

    Java操作属性文件.支持新增或更新多个属性 一.更新或新增单个属性的方法 /** * 写入properties信息 * @param filePath 绝对路径(包含文件名称和后缀名) * @par ...

  8. C# 程序自动批量生成 google maps 的KML文件

    原文:C# 程序自动批量生成 google maps 的KML文件 google maps 的 KML 文件可以用于静态的地图标注,在某些应用中,我们手上往往有成百上千个地址,我们需要把这些地址和描述 ...

  9. winform展示Unity3D文件(支持动态改变文件路径)

    winform下展示Unity3D文件可以支持对Unity3D实现的模块进行包装,以及在其他的项目中需要展示Unity3D的界面时候,恰到适宜地进行打开展示,这里我展示如何使用winform打开Uni ...

随机推荐

  1. response向客户端写入数据

    1.写入文字: protected void doGet(HttpServletRequest request, HttpServletResponse response) throws Servle ...

  2. java8 新特性精心整理

    前言 越来越多的项目已经使用 Java 8 了,毫无疑问,Java 8 是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和 JVM 等方面的十多个新特 ...

  3. Scala 系列(十三)—— 隐式转换和隐式参数

    一.隐式转换 1.1 使用隐式转换 隐式转换指的是以implicit关键字声明带有单个参数的转换函数,它将值从一种类型转换为另一种类型,以便使用之前类型所没有的功能.示例如下: // 普通人 clas ...

  4. [Leetcode][动态规划] 第935题 骑士拨号器

    一.题目描述 国际象棋中的骑士可以按下图所示进行移动:                           我们将 “骑士” 放在电话拨号盘的任意数字键(如上图所示)上,接下来,骑士将会跳 N-1 步 ...

  5. 环境搭建-Hadoop集群搭建

    环境搭建-Hadoop集群搭建 写在前面,前面我们快速搭建好了centos的集群环境,接下来,我们就来开始hadoop的集群的搭建工作 实验环境 Hadoop版本:CDH 5.7.0 这里,我想说一下 ...

  6. 完美激活Pycharm2019.2.3专业版

    完美激活Pycharm2019.2.3专业版 Pycharm官网自9月11更新到pycharm2019.2.2版本后,在短短的2周时间与9月25又带来新版本2019.2.3,不可说更新不快,侧面可以看 ...

  7. Spring 梳理-el表达式和jstl

    JSP中有这么几种元素 1: Scriptlet <% ... %> 2: 声明元素 <%! ... %> 3: Java表达式 <%= ... %> 4: 指令元 ...

  8. visual c++.net 技术内幕 第6版 附带的程序如何在vs2013中编译成功

    看vc++技术内幕时 如果你使用的是比此书的附带项目更新版的vs时千万不要使用这种方法,这些对编译都有影响. 请使用当前新版的vs并输入书中改动的代码就Ok,因为vs会生成合理的mfc代码,养成好的习 ...

  9. Scala Try Catch Finally

    Scala Try Catch Finally: 在Java中返回值优先级顺序:finally最高, try,catch 选其一,try中抛异常,返回catch,不抛异常,返回try,. public ...

  10. 使用echarts画一个类似组织结构图的图表

    昨天,写了一篇关于圆环进度条的博客(请移步:Vue/React圆环进度条),已经烦不胜烦,今天又遇到了需要展示类似公司的组织结构图的功能需求,要冒了!!! 这种需求,自己用div+css也是可以实现的 ...