前言:
GDAL(Geospatial Data Abstraction Library)是一个在X/MIT许可协议下的开源栅格空间数据转换库。它利用抽象数据模型来表达所支持的各种文件格式。它还有一系列命令行工具来进行数据转换和处理。
- 我这里主要是用作:autocad的
xxx.dxf
格式文件转成xxx.geojson
格式文件。 - 思路:
gdal
是c++
写的,安装调用它可以用命令行,也可以集成到java
项目上。所以首先要在web
服务器上安装gdal
,然后把gdal
提供的jar
依赖引到java
项目中,并且把gdal
的一些动态链接库(win
系统是.dll
文件,linux
是.so
文件)给到jdk
去调用。
我这里是本地开发,所以本文记录的是本地windows
系统上搭环境。
linux
系统,请参考:linux 安装 GDAL 3.3.2 - 简书 (jianshu.com)
一、下载
下载gdal windows版本64位最新的稳定版,前往:GISInternals Support Site


二、安装gdal
双击打开:
选择custom安装即可。
三、配置环境变量
Note: In order to have the bindings work the location of the core components must be included manually in the PATH environment variable.
- a.系统变量-path中新增:
C:\Program Files\GDAL\
- b.系统变量-新增-变量名:
GDAL_DATA
,变量值:C:\Program Files\GDAL\gdal-data
- c.系统变量-新增-变量名:
GDAL_DRIVER_PATH
,变量值:C:\Program Files\GDAL\gdalplugins
测试gdal安装是否成功,cmd输入:
# gdalinfo --version
image.png
四、java集成gdal
说明:
java集成gdal主要是引gdal.jar依赖以及配置jdk可以调用到.dll动态链接库。
引jar包可以有很多种方式,比如:
- 直接引入(不推荐);
- 打到本地maven仓库之后pom.xml引入(推荐);
- jar包复制到
src/main/resources/
下,直接在pom.xml中引入(最简单推荐,下文说的就是这种);
步骤:
- 本地使用springboot自建web应用,maven作为项目管理和构建工具;
- 把C:\Program Files\GDAL\下所有的.dll文件全部复制到jdk/bin/下;
-
把C:\Program Files\GDAL\java\下的gdal.jar和C:\Program Files\GDAL\下的gdalalljni.dll复制到src/main/resources/gdal/win32/下;
如图:
image.png
注意的就是linux的jar包和win32的jar包可能不一样,linux的要去下载gdal二进制资源然后编译等,而且第2第3部应用动态链接库也完全不一样,后期我再验证更新。我这里先说下win的开发环境配置。
- pom.xml中引入gdal.jar包:
<properties>
...
<gdal.binddir>src/main/resources/gdal/win32</gdal.binddir>
</properties>
<dependencies>
<dependency>
<groupId>org.gdal</groupId>
<artifactId>gdal</artifactId>
<version>3.5.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/${gdal.binddir}/gdal.jar</systemPath>
</dependency>
</dependencies>
-
测试dxf文件转geojson。
说明:把.dxf转成.geojson,转换后的geojson可读性很强导致文件过大,所以我使用分页分文件夹去转换,详情见测试代码源码。
image.png
效果:
image.png
image.png
image.png
源码:
说明:源码中涉及到下面几点的可以先忽略注释或者删掉
- 转换可能导致中文乱码,我这里在源码注掉了本篇不涉及,可以参见我这篇文章:GDAL 在把 dxf 转成 geojson 后,cad的图层名中文乱码问题 - 简书 (jianshu.com)
- 在FileUtil.java中可以看到main方法里有个dealDxf(path, inputFileName);方法,是手动处理个别cad图转换报错的问题,
原因:查看gdal的c++源码,在解析dxf中的id字符串属性长度超长报错,dxf实际就是个文本查看它发现里面有个别元素的id字符串过长,而且是重复有规律的(类似于在同文件夹下一直复制同一个文件windows会自动给新文件重命名),猜测是制图师在编辑cad时无脑复制粘贴某些元素导致。
解决:用计数的方式去处理这种超长id,如:把 id_1_1 转成 id_002,把 id_1_1_1_1 转成 id_004,把 id_1_1_1_1_1_1_1_1_1_1_1_1 转成 id_012。
- pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ckk</groupId>
<artifactId>gismap</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<gdal.binddir>src/main/resources/gdal/win32</gdal.binddir>
</properties>
<dependencies>
<dependency>
<groupId>org.gdal</groupId>
<artifactId>gdal</artifactId>
<version>3.5.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/${gdal.binddir}/gdal.jar</systemPath>
</dependency>
<!-- 编码检测依赖:cpdetector、antlr、chardet、jargs -->
<!-- <dependency>-->
<!-- <groupId>com.hongyi</groupId>-->
<!-- <artifactId>cpdetector</artifactId>-->
<!-- <version>1.0.10</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.hongyi</groupId>-->
<!-- <artifactId>antlr</artifactId>-->
<!-- <version>2.7.4</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.hongyi</groupId>-->
<!-- <artifactId>chardet</artifactId>-->
<!-- <version>1.0</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.hongyi</groupId>-->
<!-- <artifactId>jargs</artifactId>-->
<!-- <version>1.0</version>-->
<!-- </dependency>-->
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.0-alpha7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.2</version>
</dependency>
</dependencies>
</project>
- test.java:
package test;
import lombok.extern.slf4j.Slf4j;
import org.gdal.gdal.gdal;
import org.gdal.ogr.DataSource;
import org.gdal.ogr.*;
import org.gdal.osr.SpatialReference;
import util.file.FileUtil;
/**
* gdal测试类
* @author ckk
* @create 2022-08-06 16:07
**/
public class Test {
public static void main(String[] args) {
// 1.dxf 转 geojson
boolean b = dxf2GeoJson("D:\\cad2wms\\", "葫芦素-最新.dxf", "D:\\cad2wms\\hulusu_colliery_id\\");
System.out.println("bbbbbb==="+b);
}
/**
* dxf转geojson(矢量拆分)
* @param inputPath
* @param cadFileName
* @param outputPath
* @return
*/
public static boolean dxf2GeoJson(String inputPath, String cadFileName, String outputPath){
try {
ogr.RegisterAll();
// gdal.SetConfigOption 选项配置参见:https://trac.osgeo.org/gdal/wiki/ConfigOptions
// 为了支持中文路径,请添加下面这句代码
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
// 为了使属性表字段支持中文,请添加下面这句
gdal.SetConfigOption("SHAPE_ENCODING", "");
/**
* 判断编码dxf文件编码类型:
* 在cad另存为dxf时,由于不同版本问题导致编码不同。
* 已知:dxf >=2007 版本编码为 UTF-8,其他低版本编码为 GB2312
* 若为 UTF-8 需要设置:gdal.SetConfigOption("DXF_ENCODING", "ASCII");
*/
// String charset = EncodingDetector.getCharset(new File(inputPath + cadFileName));