搭建GDAL JAVA环境;DXF转KML;坐标转换;PROJ: proj_create_from_database 错误解决
搭建JAVA GDAL环境
GDAL是一个栅格和矢量地理空间数据格式的转换库,由开源地理空间基金会按照MIT开源协议发布。作为一个库,它向应用程序为所有支持的数据格式提供统一的栅格抽象数据模型和矢量抽象数据模型。它还提供了用于数据转换和处理的各种有用的命令行实用工具。
GDAL官网: GDAL — GDAL documentation
中文官网:GDAL — GDAL 文档 (osgeo.cn)
下载安装
GISInternals is an online system for creating daily built binary packages for the GDAL and MapServer projects.
GISIinternals是一个在线系统,用于为GDAL和MapServer项目创建每日构建的二进制包。
打开上述地址后,根据自己系统选择对应的版本
本地部署
-
解压后将GDAL的
/bin
文件夹下所有的.dll
(不包括bin目录下的文件夹)和/bin/gdal/java
下的dll
文件拷贝到jdk安装路径的bin目录下- 注意不要把GDAL解压到带有中文或空格的目录下
- JDK安装目录,指的是当前java程序依赖的jdk的安装目录,如使用的jre运行java程序则需要将相关dll文件方到jre的bin目录下【无法确定运行环境时,建议,直接给jdk和jre都放】
-
将GDAL的bin目录添加到
Path
的环境变量下【建议将以下图片的这些目录都添加到环境变量中,避免后续重复添加】
-
添加环境变量
D:\gdal\bin\gdal\plugins
目录添加到环境变量,变量名为GDAL_DRIVER_PATH
- 将
proj.db
所在路径D:\gdal\bin\proj9\share
添加到环境变量,变量名为PROJ_LIB
使用GDAL命令行
这个库分为两大部分是GDAL和OGR,分别管理着栅格和矢量数据。底层是c语言,上层可以是多种语言(包括python,java等)调用,下方是(栅格和矢量)数据处理的中文索引,以及中文帮助;
附官网数据来源:栅格:栅格raster— GDAL 文档 、矢量Programs — GDAL documentation
栅格
- Common options
- gdalinfo :列出有关栅格数据集的信息。
- gdal_translate :在不同格式之间转换栅格数据。
- gdaladdo :生成或重建概述图像。
- gdalwarp :图像重新投影和扭曲实用程序。
- gdaltindex: Builds an OGR-supported dataset as a raster tileindex.
- gdalbuildvrt :从数据集列表生成VRT。
- gdal_contour :从栅格高程模型生成矢量等高线。
- gdaldem :用于分析和可视化DEM的工具。
- rgb2pct.py :将24位RGB图像转换为8位调色板。
- pct2rgb.py :将8位调色板图像转换为24位RGB。
- gdalattachpct.py: Attach a color table to a raster file from an input file.
- gdal_merge.py :拼接一组图像。
- gdal2tiles.py :使用TMS tiles、KMLs和简单的web查看器生成目录。
- gdal2xyz.py: Translates a raster file into xyz format.
- gdal_rasterize :将矢量几何图形烧成栅格。
- gdaltransform :转换坐标。
- nearblack :将近乎黑白的边框转换为黑色。
- gdal_retile.py :重定时一组平铺和/或构建平铺棱锥层。
- gdal_grid :从分散的数据创建规则网格。
- gdal_proximity.py :生成栅格近似图。
- gdal_polygonize.py :从栅格生成多边形要素图层。
- gdal_sieve.py :删除小栅格多边形。
- gdal_fillnodata.py :通过从边缘插值来填充栅格区域。
- gdallocationinfo :栅格查询工具
- gdalsrsinfo :以多种格式(WKT、PROJ.4等)列出有关给定SRS的信息
- gdalmove.py :就地转换栅格文件的地理参考。
- gdal_edit.py :就地编辑现有GDAL数据集的各种信息。
- gdal_calc.py :具有numpy语法的命令行栅格计算器。
- gdal_pansharpen.py :执行pansharpen操作。
- gdal-config (Unix) :确定有关GDAL安装的各种信息。
- gdalmanage :标识、删除、重命名和复制栅格数据文件。
- gdalcompare.py :比较两个图像。
- gdal_viewshed :计算栅格的可见性遮罩。
- gdal_create :创建栅格文件(无源数据集)。
矢量
- Common options
- gdalinfo :列出有关栅格数据集的信息。
- gdal_translate :在不同格式之间转换栅格数据。
- gdaladdo :生成或重建概述图像。
- gdalwarp :图像重新投影和扭曲实用程序。
- gdaltindex: Builds an OGR-supported dataset as a raster tileindex.
- gdalbuildvrt :从数据集列表生成VRT。
- gdal_contour :从栅格高程模型生成矢量等高线。
- gdaldem :用于分析和可视化DEM的工具。
- rgb2pct.py :将24位RGB图像转换为8位调色板。
- pct2rgb.py :将8位调色板图像转换为24位RGB。
- gdalattachpct.py: Attach a color table to a raster file from an input file.
- gdal_merge.py :拼接一组图像。
- gdal2tiles.py :使用TMS tiles、KMLs和简单的web查看器生成目录。
- gdal2xyz.py: Translates a raster file into xyz format.
- gdal_rasterize :将矢量几何图形烧成栅格。
- gdaltransform :转换坐标。
- nearblack :将近乎黑白的边框转换为黑色。
- gdal_retile.py :重定时一组平铺和/或构建平铺棱锥层。
- gdal_grid :从分散的数据创建规则网格。
- gdal_proximity.py :生成栅格近似图。
- gdal_polygonize.py :从栅格生成多边形要素图层。
- gdal_sieve.py :删除小栅格多边形。
- gdal_fillnodata.py :通过从边缘插值来填充栅格区域。
- gdallocationinfo :栅格查询工具
- gdalsrsinfo :以多种格式(WKT、PROJ.4等)列出有关给定SRS的信息
- gdalmove.py :就地转换栅格文件的地理参考。
- gdal_edit.py :就地编辑现有GDAL数据集的各种信息。
- gdal_calc.py :具有numpy语法的命令行栅格计算器。
- gdal_pansharpen.py :执行pansharpen操作。
- gdal-config (Unix) :确定有关GDAL安装的各种信息。
- gdalmanage :标识、删除、重命名和复制栅格数据文件。
- gdalcompare.py :比较两个图像。
- gdal_viewshed :计算栅格的可见性遮罩。
- gdal_create :创建栅格文件(无源数据集)。
使用JAVA读取DXF文件并转为KML
- gdal安装目录下
D:\gdal\bin\gdal\java
bin目录下gdal下java目录中的gdal.jar
复杂到java项目中
- 将gdal.jar添加到项目依赖中,右击gdal.jar选择
Add as Library
;
- java中复杂以下代码测试
import org.gdal.gdal.gdal;
import org.gdal.ogr.ogr;
//测试案例
class GdalDemo {
//获取所有驱动的名称并打印
public void printDriver() {
gdal.AllRegister();
int count = ogr.GetDriverCount();
for (int i = 0; i < count; i++) {
String driverName = ogr.GetDriver(i).getName();
System.out.print(driverName + "\t");
}
gdal.GDALDestroyDriverManager();
}
public static void main(String[] args) {
GdalDemo demo = new GdalDemo();
demo.printDriver();
}
}
- 测试成功
- 完整代码
/**
* 使用gdal 解析dxf,并将数据读取转为KML 或 GEOJSON
* 包含坐标转换
*/
public class DXFToGeoJSONConverter {
public static void main(String[] args) {
Boolean converter = converter("E://test//1.kml", "E://test//白马2000-3-108.dxf");
if (converter) {
System.out.println("成功");
} else {
System.out.println("失败");
}
}
/**
*
* @param outPath 输出文件全路径
* @param inPath 读取文件全路径
* @return
*/
public static Boolean converter(String outPath, String inPath) {
// 注册所有的驱动
//gdal.AllRegister();
ogr.RegisterAll();
gdal.SetConfigOption("DWG_ENCODING", "UTF-8");//DWG文件编码
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");//支持中文路径
gdal.SetConfigOption("SHAPE_ENCODING", "CP936");//属性表字段支持中文
DataSource dataSource = ogr.Open(inPath, 0);
if (dataSource == null) {
System.out.println("打开文件失败!" + gdal.GetLastErrorMsg());
return false;
}
System.out.println("打开文件成功!");
//构造坐标系转换对象
SpatialReference src = new SpatialReference();
// src.ImportFromProj4("+proj=tmerc +lat_0=0 +lon_0=108 +k=1 +x_0=36500000 +y_0=0 +ellps=GRS80 +units=m +no_defs");
src.ImportFromEPSG(4545); // CGCS2000 中央经线 108 3分带 36带
System.out.println("原坐标系:" + src.ExportToProj4());
SpatialReference dest = new SpatialReference();
dest.ImportFromEPSG(4326); // WGS84
System.out.println("目标坐标系:" + dest.ExportToProj4());
// SpatialReference dest = dest1.CloneGeogCS();
CoordinateTransformation transformation = new CoordinateTransformation(src, dest);//源,目标
//1.创建驱动程序
Driver dv = ogr.GetDriverByName("KML"); //直接转KML
// Driver dv = ogr.GetDriverByName("GeoJSON"); //直接转GEOJSON
int layerCount = dataSource.GetLayerCount();
System.out.println("总图层数:" + layerCount);
DataSource ds = dv.CreateDataSource(outPath);
for (int i = 0; i < layerCount; i++) {
// 2.循环读取每个图层
Layer inLayer = dataSource.GetLayerByIndex(i);
if (inLayer == null) {
continue;
}
String layerName = inLayer.GetName();
//3.每个DataSource创建一个输出的layer
Layer outLayer = ds.CreateLayer(layerName, dest, ogrConstants.wkbUnknown, null);
long featureCount = inLayer.GetFeatureCount();
System.out.println("总图形数:" + featureCount);
for (long j = 0; j < featureCount; j++) {
Feature feature = inLayer.GetFeature(j);
feature.GetStyleString();
//4.获取输入的几何对象,调用其转换方法,转换后存入新的layer中
Geometry geometry = feature.GetGeometryRef();
geometry.Transform(transformation);
//注意,转换为后时 经度 纬度 的顺序,如果需要纬度在前,需要交换xy
// geometry.SwapXY();
geometry.CloseRings();
outLayer.CreateFeature(feature);
}
}
System.out.println("转换成功!!!");
return true;
}
}
GDAL坐标转换
/**
* 用gdal进行坐标转换
*/
public class CoordinateTransformationExample {
public static void main(String[] args) {
// 注册GDAL驱动
gdal.AllRegister();
// 输入的坐标
double inputX = 36587998.113885;
double inputY = 3796047.384520;
// 创建源坐标系统 (CGCS2000 3度带,中央经线108)
SpatialReference srcSRS = new SpatialReference();
srcSRS.ImportFromProj4("+proj=tmerc +lat_0=0 +lon_0=108 +k=1 +x_0=36500000 +y_0=0 +ellps=GRS80 +units=m +no_defs");
// 创建目标坐标系统 (WGS84)
SpatialReference tgtSRS = new SpatialReference();
tgtSRS.ImportFromEPSG(4326);
// 创建坐标转换对象
CoordinateTransformation transformation = new CoordinateTransformation(srcSRS, tgtSRS);
// 执行坐标转换
double[] transformedCoords = transformation.TransformPoint(inputX, inputY);
// 输出转换后的经纬度 (转换后经纬度位置交换了,注意不要取错参数)
System.out.println("Transformed Coordinates (WGS84):");
System.out.println("Longitude: " + transformedCoords[1]);
System.out.println("Latitude: " + transformedCoords[0]);
}
}
可能遇到的错误
ERROR 1: PROJ: proj_create_from_database: D:\ideawork\pkgs\proj-6.2.1-h9f7ef89_0\Library\share\proj\proj.db lacks DATABASE.LAYOUT.VERSION.MAJOR / DATABASE.LAYOUT.VERSION.MINOR metadata. It comes from another PROJ installation.
原因分析:
使用osgeo.osr能够直接从安装的GDAL包读取指定投影类型的信息,在proj.db中存储了常用的投影系统的参数,因此指定EPSG号就能从proj.db中取到投影信息。
经过排查,我的情况是在开发环境中同时安装了GDAL和其他地理空间库(如PostGresql),此时同一环境路径下可能会产生多个proj.db文件,访问它的时候程序会无法判断访问哪个。因此只需要去查找gdal安装的那个proj.db在哪里,在程序中指定环境变量即可解决。
解决方法:
其他参考文章: