Java調用開源GDAL解析dxf成shp,再調用開源GeoTools解析shp文件


  • 需求

    最近項目要做國產化,有一個導入CAD的功能需要修改。要換成開源的或者國產的技術去解析CAD。DWG格式的,懂的都懂,開源的不可能解析,國產收費的那些CAD公司,個人認為也是買的AutoCAD的接口解析的。所以我們只能改成解析CAD的另一種文件格式:DXF文件。

  • 方案

    解析dxf用開源的GDAL,調用GDAL驅動把dxf轉成shp文件,然后再用開源的GeoTools去解析shp文件。

    GDAL的依賴下載地址:https://www.gisinternals.com/release.php

    調用GDAL動態鏈接庫:

      windows系統:

        (1)第一種簡單粗暴的方式就是把gdal包bin目錄下所有的dll文件和bin\gdal\java下的dll文件丟到你的JDK的bin目錄下,對應的jar包也許在\bin\gdal\java目錄下。

        (2)第二種是自己新建一個文件夾把需要的dll文件全放在一起,然后自己配環境變量(總之讓系統能找到你的庫就行了)。

      Linux和docker鏡像:

         在Linux上,gdal官網上沒有編譯好的包,要自己去下gdal的源碼包,然后自己編譯,后面會生成.so文件和jar包,和windows一樣可以配置環境變量或者把so文件丟到jdk的bin目錄下。

         docker鏡像,可以去dockerhub(https://hub.docker.com/r/osgeo/gdal/tags?page=1&ordering=last_updated)下載鏡像,然后鏡像里邊會有相應的jar包和so文件(一般比較大的鏡像才會有),可以直接拿里邊的jar包和so文件來用。或者直接在鏡像里部署應用也可以。docker鏡像的jar包和so文件不知道在linux上能不能用,按道理應該可以吧,這個沒試過。但是docker鏡像上的好像有系統的區別?(還有好多疑問啊,后面遇到了再驗證吧)。

      注意:jar包和so文件是一一對應的,就是鏡像里的jar包和你自己編譯生成的so文件不能配合使用,但是windows上調用dll動態鏈接庫,用到的jar包卻不講究,不管是docker還是linux上的jar包都可以用(至少我在項目中測試是這樣的,我也不知道為啥)

    GeoTools包下載地址(也可以用maven):https://sourceforge.net/projects/geotools/files/

  • 代碼

  

DXF轉SHP代碼片段:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.*;

import org.geotools.data.shapefile.ShapefileDataStore;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.geotools.data.FeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;

import org.gdal.gdal.gdal;
import org.gdal.ogr.DataSource;
import org.gdal.ogr.Driver;
import org.gdal.ogr.Layer;
import org.gdal.ogr.ogr;

public String getDxfData() throws Exception{
            
            //dxf文件路徑
            String filePath ="C:\\WorkSpace\\rect_field_demo.dxf";
            // 注冊所有的驅動
            ogr.RegisterAll();
            gdal.SetConfigOption("DXF_ENCODING","UTF-8");
            gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8","YES");//支持中文路徑
            gdal.SetConfigOption("SHAPE_ENCODING","CP936");//屬性表字段支持中文
            DataSource ds = ogr.Open(filePath,1);
            if (ds == null)
            {
                System.out.println("打開文件失敗!" );
                return null;
            }
            System.out.println("打開文件成功!" );
            Layer oLayer = ds.GetLayerByIndex(0);
            if(oLayer == null){
                System.out.println("獲取失敗");
                return null;
            }
            oLayer.ResetReading();
            Driver dv = ogr.GetDriverByName("ESRI Shapefile"); //調用驅動轉shp
            String extfile = "C:\\WorkSpace\\rect_field_demo.shp";
            DataSource dataSource = dv.CopyDataSource(ds, extfile);//創建shp文件並寫入內容
            dataSource.delete();    //釋放與數據源對象關聯的本機資源並關閉文件(這句非常重要,如果沒有關閉文件,那么下面的解析shp就解析不了)
            String geometry = getShpData("C:\\WorkSpace\\rect_field_demo.shp",coordInfo);

            return geometry;

        }
解析shp文件public static String getShpData(String filePath) throws Exception {
        File file = new File(filePath);
        long fileSize = file.length();
        List<Map<String,Object>> list = new ArrayList<Map<String, Object>>();
        ShapefileDataStore shpDataStore = new ShapefileDataStore(file.toURL());
        shpDataStore.setStringCharset(Charset.forName("GBK"));
        String typeName = shpDataStore.getTypeNames()[0];
        FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = null;
        featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>)shpDataStore.getFeatureSource(typeName);//這里我看了很多人的博客都沒有指定類(FeatureSource<SimpleFeatureType, SimpleFeature>),難道不會報錯嗎,反正我的會
        FeatureCollection<SimpleFeatureType, SimpleFeature> result = featureSource.getFeatures();

        FeatureIterator<SimpleFeature> itertor = result.features();
        while (itertor.hasNext())
        {
            Map<String,Object> data  = new HashMap<String, Object>();
            SimpleFeature feature = itertor.next();
            Collection<Property> p = feature.getProperties();
            Iterator<Property> it = p.iterator();
            while(it.hasNext()) {
                Property pro = it.next();
                String field = pro.getName().toString();
                String value = pro.getValue().toString();
                field = field.equals("the_geom")?"wkt":field;
                data.put(field, value);
            }
            list.add(data);
        }
        JSONArray jsonarray = JSONArray.fromObject(list);
        return jsonarray.toString();
    }

 

 

ps:Java大學的時候學過,之后就沒寫過了,這里基本上全是抄的,哈哈哈哈,抄得不好見諒!忘記抄的誰的了,就不注明了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM