文件转换-cad转geojson

Posted 占星安啦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文件转换-cad转geojson相关的知识,希望对你有一定的参考价值。

前言

基于前一篇文章GeoServer系列-通过mongodb发布geojson数据,业务上可将常见的地理文件统一为geojson保存到mongodb,方便统一维护和发布geoserver,这一篇将举例cad格式转geojson,并设置坐标

1,必要的依赖

  • 文件转换和解析用到了gdal,需要先下载并配置环境变量(我用的3.3),安装后可使用以下命令查看版本

    C:\\Users\\CDLX>gdalinfo.exe --version
    GDAL 3.3.0, released 2021/04/26

  • pom引入

    <dependencies>
        <dependency>
            <groupId>org.gdal</groupId>
            <artifactId>gdal</artifactId>
            <version>3.2.0</version>
        </dependency>
    </dependencies>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.8.7</version>
    </dependency>
    

2,转换入口

    /**
     * dwg转geojson
     *
     * @param fileName gdb文件名  xxx.dwg
     * @param fileMd5  文件md5值   1232131
     * @return
     */
    @Override
    public String dwgToJson(String fileName,String userId, String fileMd5) 
        String wsDirPath = fileDirectory + "/" + fileMd5 + userId;
        //文件名
        String dwgname = fileName.substring(0, fileName.lastIndexOf("."));
        String dwgpath = wsDirPath + "/" + fileName;
        //1,dwg转dxf D:\\TS\\temp\\cadtest\\cadtest.dxf
        String outFile = dwgpath.replace(".dwg", ".dxf");
        String res = dwg2dxf(dwgpath, outFile);
        if (res != null) 
            return res;
        
        //2,dxf转换成json  D:\\TS\\temp\\cadtest\\cadtest.geojson
        String jsonPath = outFile.replace(".dxf", "转换前.geojson");
        res = dxfToJson(outFile, jsonPath);
        if (res != null) 
            return res;
        
        //3,坐标转换  D:\\TS\\temp\\cadtest\\cadtest转换.geojson
        long begin = System.currentTimeMillis();
        String newJsonPath = jsonPath.replace("转换前.geojson", "") + ".geojson";
        res = geoJsonCov(jsonPath, newJsonPath, dwgname);
        if (res != null) 
            return res;
        
        long end = System.currentTimeMillis();
        log.info("dwg坐标转换耗时:", (end - begin));
        return null;
    

3,dwg转dxf

    public String dwg2dxf(String dwgPath, String outFile) 
        File dwgFile = new File(dwgPath);
        if (dwgFile.exists()) 
            if (!dwgFile.getName().endsWith(".dwg")) 
                return "文件格式错误";
            
            LoadOptions loadOptions = new LoadOptions();
            loadOptions.setSpecifiedEncoding(CodePages.SimpChinese);
            CadImage cadImage = (CadImage) Image.load(dwgFile.getAbsolutePath(), loadOptions);
            cadImage.save(outFile);
            cadImage.close();
            return null;
         else 
            return "dwg文件不存在," + dwgPath;
        
    

4,dxf转geojson

    /**
     * dxf转json
     *
     * @param dxfPath     D:\\TS\\sharding\\filemd5\\cadtest.dxf
     * @param geoJsonPath D:\\TS\\sharding\\filemd5\\cadtest.geojson
     */
    public String dxfToJson(String dxfPath, String geoJsonPath) 
        ogr.RegisterAll();
        //支持中文路径
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
        gdal.SetConfigOption("DXF_ENCODING", "UTF-8");

        //读取文件转化为DataSource
        DataSource ds = ogr.Open(dxfPath, 0);
        if (ds == null) 
            return "打开文件失败," + dxfPath;
        
        //获取geojso
        Driver geojsonDriver = ogr.GetDriverByName("GeoJSON");
        DataSource geojsonDataSource = geojsonDriver.CopyDataSource(ds, geoJsonPath);
        geojsonDataSource.delete();
        ds.delete();
        return null;
    

5,坐标转换(重点来了)

因为cad文件没有坐标系,需要预设一个坐标系,将上一步中geojson中的坐标进行转换

    /**
     * 坐标转换
     *
     * @param geoJsonPath D:\\\\ITS\\\\Sharding\\filemd5\\xx.geojson
     * @param outputJson  D:\\\\ITS\\\\Sharding\\filemd5\\xx转换.geojson
     * @param dwgName     图层名称
     */
    public String geoJsonCov(String geoJsonPath, String outputJson, String dwgName) 
        ogr.RegisterAll();
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");//支持中文路径
        gdal.SetConfigOption("DXF_ENCODING", "UTF-8");
        DataSource ds2 = ogr.Open(geoJsonPath, 0);
        System.out.println("----------坐标转换开始-----------");
        //读取第一个图层,这个图层不是cad中的layer
        Layer oLayer = ds2.GetLayerByIndex(0);
        if (oLayer == null) 
            log.error("从dwg的geojson中获取layer 获取失败:", geoJsonPath);
            ds2.delete();
            return "从dwg的geojson中获取layer 获取失败";
        

        //新创建一个图层geojson
        Driver geojsonDriver = ogr.GetDriverByName("GeoJSON");
        SpatialReference epsg2000 = new SpatialReference("");
        epsg2000.ImportFromEPSG(4490);
        DataSource dataSource = geojsonDriver.CreateDataSource(outputJson, null);
        Layer geojsonLayer = dataSource.CreateLayer(dwgName, epsg2000, ogrConstants.wkbUnknown, null);

        Feature feature;
        String geometryStr;
        String newGeometryStr;
        while ((feature = oLayer.GetNextFeature()) != null) 
            //获取空间属性
            Geometry geometry = feature.GetGeometryRef();
            // 解决自相交问题
            //geometry = geometry.Buffer(0.0);
            //System.out.println(geometry.ExportToJson());
            geometryStr = geometry.GetCurveGeometry().ExportToJson();
            if (geometryStr == null) 
                continue;
            
            newGeometryStr = String.valueOf(paseCoordinates(geometryStr));
            Geometry newGeometry = Geometry.CreateFromJson(newGeometryStr);
            //传给新建的矢量图层
            Feature dstFeature = feature.Clone();
            dstFeature.SetGeometry(newGeometry);
            geojsonLayer.CreateFeature(dstFeature);
        
        geojsonDriver.delete();
        ds2.delete();
        dataSource.delete();
        return null;
    

6,一个朴实无华的逐行坐标转换

逐行读取geojson的Feature,遍历每个坐标

    /**
     * 转换每个Feature的坐标
     * @param coordinatesStr Feature原始json字符串
     * @return
     */
    public StringBuffer paseCoordinates(String coordinatesStr) 
        //String a = " \\"type\\": \\"Feature\\", \\"id\\": 0, \\"properties\\":  \\"Layer\\": \\"SXSS\\", \\"SubClasses\\": \\"AcDbEntity:AcDbBlockReference\\", \\"Linetype\\": \\"Continuous\\", \\"EntityHandle\\": \\"4F2\\" , \\"geometry\\":  \\"type\\": \\"MultiLineString\\", \\"coordinates\\": [ [ [ 406567.373450083076023, 3058272.568403942044824 ], [ 406565.039480640378315, 3058269.633257158566266 ] ], [ [ 406565.039480640378315, 3058269.633257158566266 ], [ 406565.597624949878082, 3058269.85315527068451 ] ], [ [ 406565.039480640378315, 3058269.633257158566266 ], [ 406565.128001464472618, 3058270.226590381469578 ] ] ]  ";
        int offset = coordinatesStr.indexOf("coordinates\\":") + 13;
        String b = coordinatesStr.substring(offset);
        //System.out.println(b);
        String[] c = b.split("\\\\],");
        StringBuffer stringBuffer = new StringBuffer();
        int n = c.length;
        for (String d : c) 
            //System.out.println(d);
            int begin = d.lastIndexOf("[");
            int end = d.indexOf("]");
            String oldZb = d.substring(begin < 0 ? 0 : begin + 1, end < 0 ? d.length() - 1 : end - 1);
            //System.out.println(oldZb);
            String newZb = CadUtil.covStr(oldZb);
            //System.out.println(newZb);
            if (begin > 0) 
                stringBuffer.append(d, 0, begin + 1).append(newZb);
            
            if (n != 1) 
                stringBuffer.append("]");
            
            if (end > 0) 
                stringBuffer.append(d.substring(end - 1));
            
            if (n > 1) 
                stringBuffer.append(",");
            
            n--;
        
        stringBuffer.insert(0, coordinatesStr.substring(0, offset));
        return stringBuffer;
    

纠正经纬度颠倒问题

    public static String covStr(String zb) 
        String[] poi = zb.trim().split(",");
        double x = Double.parseDouble(poi[0]);
        double y = Double.parseDouble(poi[1]);
        //坐标经纬度交换
        if (x > y) 
            return dxfToSwapxy(x, y);
         else 
            return dxfToSwapxy(y, x);
        
    

硬菜(x_x)

    /**
     * 坐标转换
     *
     * @param X
     * @param Y
     * @return
     */
    public static String dxfToSwapxy(double X, double Y) 
        double lat, lon;
        //中央子午线,结合这个网址进行查找,目前用的EPSG:4532中的123D。https://wenku.baidu.com/view/e219e246e3bd960590c69ec3d5bbfd0a7856d530.html
        double L0 = 105;
        Y -= 500000;
        double[] result = new double[2];
        double iPI = 0.0174532925199433;//pi/180
        double a = 6378137.0; //长半轴 m
        double b = 6356752.31414; //短半轴 m
        //扁率 a-b/a
        double e = 0.0818191910428; //第一偏心率 Math.sqrt(5)
        double ee = Math.sqrt(a * a - b * b) / b; //第二偏心率
        double bf = 0; //底点纬度
        double a0 = 1 + (3 * e * e / 4) + (45 * e * e * e * e / 64) + (175 * e * e * e * e * e * e / 256) + (11025 * e * e * e * e * e * e * e * e / 16384) + (43659 * e * e * e * e * e * e * e * e * e * e / 65536);
        double b0 = X / (a * (1 - e * e) * a0);
        double c1 = 3 * e * e / 8 + 3 * e * e * e * e / 16 + 213 * e * e * e * e * e * e / 2048 + 255 * e * e * e * e * e * e * e * e / 4096;
        double c2 = 21 * e * e * e * e / 256 + 21 * e * e * e * e * e * e / 256 + 533 * e * e * e * e * e * e * e * e / 8192;
        double c3 = 151 * e * e * e * e * e * e * e * e / 6144 + 151 * e * e * e * e * e * e * e * e / 4096;
        double c4 = 1097 * e * e * e * e * e * e * e * e / 131072;
        bf = b0 + c1 * Math.sin(2 * b0) + c2 * Math.sin(4 * b0) + c3 * Math.sin(6 * b0) + c4 * Math.sin(8 * b0); // bf =b0+c1*sin2b0 + c2*sin4b0 + c3*sin6b0 +c4*sin8b0 +...
        double tf = Math.tan(bf);
        double n2 = ee * ee * Math.cos(bf) * Math.cos(bf); //第二偏心率平方成bf余弦平方
        double c = a * a / b;
        double v = Math.sqrt(1 + ee * ee * Math.cos(bf) * Math.cos(bf));
        double mf = c / (v * v * v); //子午圈半径
        double nf = c / v;//卯酉圈半径

        //纬度计算
        lat = bf - (tf / (2 * mf) * Y) * (Y / nf) * (1 - 1 / 12 * (5 + 3 * tf * tf + n2 - 9 * n2 * tf * tf) * (Y * Y / (nf * nf)) + 1 / 360 * (61 + 90 * tf * tf + 45 * tf * tf * tf * tf) * (Y * Y * Y * Y / (nf * nf * nf * nf)));
        //经度偏差
        lon = 1 / (nf * Math.cos(bf)) * Y - (1 / (6 * nf * nf * nf * Math.cos(bf))) * (1 + 2 * tf * tf + n2) * Y * Y * Y + (1 / (120 * nf * nf * nf * nf * nf * Math.cos(bf))) * (5 + 28 * tf * tf + 24 * tf * tf * tf * tf) * Y * Y * Y * Y * Y;
        result[0] = retain6(lat / iPI);
        result[1] = retain6(L0 + lon / iPI);
        return result[1] + "," + result[0];
    
    
     public static double retain6(double num) 
        String result = String.format("%.10f", num);//小数点后面保留10位小数
        return Double.valueOf(result);
    

CAD转图片怎么转?教你快速转换方法

工作中会遇到很多的问题,就比如说在CAD中就需要将CAD文件的格式进行来回的转换,常见的就是CAD转换为图片格式的。下面来教大家快速转换的方法。具体操作如下:
技术图片

转换方法:
1.打开需要使用的CAD工具来转换图纸文件的格式,之后就会进入到CAD的首页界面中,选择左侧文件转换功能区的“CAD转图片”选项。
.技术图片

2.添加需要转换的文件,想要方便的小伙伴们可以直接将转换的文件拖拽到CAD界面中进行转换。或者也可以选择界面中的“添加文件”选项进行点击,在跳转出的界面中添加好要转换的文件。
技术图片

3.将其文件添加完成后,在输入目录中选择“浏览”按钮,设置好图片转换后需要保存的位置。这样方便实用的时候进行查找。
技术图片

4.在CAD软件右下角中的输出格式中,有七种转换图片的格式。根据工作需要来设置图片转换的格式,这里就以JPG格式为例。为了不让转换文件中的字体模糊,在转换前将“页面大小”调整到最大值进行转换。
技术图片

5.然后就可以选择“批量转换”按钮进行点击,稍微等待几分钟后,在状态栏中就会显示文件转换完成。
技术图片

转换后预览文件方法:
1.点击文件后的“预览”选项,在界面弹出的页面中就可以查看到转换后的JPG图片的效果展示。
技术图片

2.点击“图层”选项,查看文件的的图层,之后在退出预览界面就可以了。
技术图片

好了,以上就是给大家整理的CAD转图片的的转换方法,希望在大家繁忙的工作中对大家有所帮助,感兴趣的伙伴们可以去试一试哈。

以上是关于文件转换-cad转geojson的主要内容,如果未能解决你的问题,请参考以下文章

CAD转PNG,快速转换操作演示

求助:CAD文件转GIS后,看起来是点;点“地球”也没用,用放大镜不方便,有啥办法让其转后直接全屏显示?

CAD转PDF格式文件使用哪一款转换器比较快捷?

在线转换怎样将CAD文件转JPG格式?

CAD批量转PDF文件什么软甲比较好

迅捷CAD转换器怎么将CAD批量转成PDF?