geoJSON 生成dae (java)-程序员宅基地

技术标签: java  开发语言  

全是代码,整个逻辑都在里面,可贴纹理

/**
 * geoJSON 生成dae 接口
 * ...
 *
 * @author qzblm
 */

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jetbrains.annotations.NotNull;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.triangulate.DelaunayTriangulationBuilder;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.http.HttpServletResponse;
import java.awt.geom.Point2D;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ColladaExporter{
    
    /**
     * 导出obj格式。
     *
     * @param geoJSON 示例参数 {"features"}
     * @return 示例返回值生成的obj的zip
     */
    public static String LoadObj(String geoJSON ) throws IOException {
    
//            String filePath = "E:\\tiff\\one.json";


        char randomLetter = generateRandomLetter();
        CreateDirPath("D:\\objs\\");
        String createPath = "D:\\objs\\"+randomLetter+randomLetter+randomLetter;
        CreateDirPath(createPath);
        String objFilename = createPath+"\\models.dae";
        CreateDir(objFilename);//创造文件obj
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode geoJson = objectMapper.readTree(geoJSON);
        JsonNode  features =  geoJson.get("features");
        List<String> objAll   = new ArrayList<>();
        List<String> objVT   = new ArrayList<>();
        List<String> objVn   = new ArrayList<>();
        List<String> mtl   = new ArrayList<>();

        String Collada ="<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n" +
                "<COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">\n";
        String asset =" <asset>\n" +
                "    <contributor>\n" +
                "      <author>GDobj2Collada</author>\n" +
                "      <authoring_tool>GDobj2Collada Exporter</authoring_tool>\n" +
                "    </contributor>\n" +
                "    <created>2023-10-07T08:59:24</created>\n" +
                "    <modified>2023-10-07T08:59:24</modified>\n" +
                "    <unit name=\"meter\" meter=\"1\" />\n" +
                "    <up_axis>Y_UP</up_axis>\n" +
                "  </asset>\n";
        String library_images ="<library_images>\n";
        String library_effects = "  <library_effects>\n" +
                "    <effect id=\"DefaultMaterial-fx\" name=\"DefaultMaterial\">\n" +
                "      <profile_COMMON>\n" +
                "        <technique sid=\"standard\">\n" +
                "          <phong>\n" +
                "            <emission>\n" +
                "              <color sid=\"emission\">0   0   0   1</color>\n" +
                "            </emission>\n" +
                "            <ambient>\n" +
                "              <color sid=\"ambient\">0   0   0   1</color>\n" +
                "            </ambient>\n" +
                "            <diffuse>\n" +
                "              <color sid=\"diffuse\">0.60000002   0.60000002   0.60000002   1</color>\n" +
                "            </diffuse>\n" +
                "            <specular>\n" +
                "              <color sid=\"specular\">0   0   0   1</color>\n" +
                "            </specular>\n" +
                "            <shininess>\n" +
                "              <float sid=\"shininess\">0</float>\n" +
                "            </shininess>\n" +
                "            <transparent>\n" +
                "              <color sid=\"transparent\">1   1   1   1</color>\n" +
                "            </transparent>\n" +
                "            <transparency>\n" +
                "              <float sid=\"transparency\">1</float>\n" +
                "            </transparency>\n" +
                "            <index_of_refraction>\n" +
                "              <float sid=\"index_of_refraction\">1</float>\n" +
                "            </index_of_refraction>\n" +
                "          </phong>\n" +
                "        </technique>\n" +
                "      </profile_COMMON>\n" +
                "    </effect>\n";
        String library_materials = " <library_materials>\n" +
                "    <material id=\"DefaultMaterial\" name=\"DefaultMaterial\">\n" +
                "      <instance_effect url=\"#DefaultMaterial-fx\"/>\n" +
                "    </material>\n";
        String library_geometries = "  <library_geometries>\n";
        String  library_visual_scenes =" <library_visual_scenes>\n" +
                "    <visual_scene id=\"models.obj\" name=\"models.obj\">\n";


        int objVTs = 0;
        int f = 1;
        int index = 1;
        for(int i =0;i<features.size();i++){
    

            List<String> objV   = new ArrayList<>();
            List<String> objF   = new ArrayList<>();
            JsonNode properties  = features.get(i).get("properties");
            String Z = "0.0";
            System.out.println("生成中"+features.get(i).get("id"));
            String ZH = properties.get("height").toString();
            ZH = ZH.substring(1, ZH.length() - 1);
            String floor = properties.get("floor").toString();
            floor = floor.substring(1, floor.length() - 1);
            double floors = Double.parseDouble(floor);
//                JsonNode h2 = objectMapper.readTree(h3.toString().replaceAll("\"", ""));
//                JsonNode data2 =features.get(0).get("properties").get("outloop")
            JsonNode data2 = objectMapper.readTree(properties.get("outloop").toString().replaceAll("\"", ""));
            JsonNode url  = properties.get("url");
            for(int a =0;a< url.size();a++){
    
                if(url.get(a).toString().length()>2){
    
                    loadTextrue(url.get(a).toString(),createPath+"\\texture"+(i+a)+".png");
                    mtl.add("newmtl material"+(i+a)+"\n");
                    mtl.add("Ns 250.000000\n");
                    mtl.add("Ka 1.000000 1.000000 1.000000\n");
                    mtl.add("Ks 0.500000 0.500000 0.500000\n");
                    mtl.add("Ke 0.000000 0.000000 0.000000\n");
                    mtl.add("Ni 1.450000\n");
                    mtl.add("d 1.000000\n");
                    mtl.add("illum 2\n");
                    mtl.add("map_Kd  "+"texture"+(i+a)+".png\n");
                    library_images += "<image id=\"material"+(i+a)+"-diffuse-image\">\n" +
                            "      <init_from>texture"+i+".png</init_from>\n" +
                            "    </image>\n";
                }
            }
            library_effects +="    <effect id=\"material"+i+"-fx\" name=\"material"+i+"\">\n" +
                    "      <profile_COMMON>\n" +
                    "        <newparam sid=\"material"+i+"-diffuse-surface\">\n" +
                    "          <surface type=\"2D\">\n" +
                    "            <init_from>material"+i+"-diffuse-image</init_from>\n" +
                    "          </surface>\n" +
                    "        </newparam>\n" +
                    "        <newparam sid=\"material"+i+"-diffuse-sampler\">\n" +
                    "          <sampler2D>\n" +
                    "            <source>material"+i+"-diffuse-surface</source>\n" +
                    "          </sampler2D>\n" +
                    "        </newparam>\n" +
                    "        <technique sid=\"standard\">\n" +
                    "          <phong>\n" +
                    "            <emission>\n" +
                    "              <color sid=\"emission\">0   0   0   1</color>\n" +
                    "            </emission>\n" +
                    "            <ambient>\n" +
                    "              <color sid=\"ambient\">1   1   1   1</color>\n" +
                    "            </ambient>\n" +
                    "            <diffuse>\n" +
                    "              <texture texture=\"material"+i+"-diffuse-sampler\" texcoord=\"CHANNEL0\" />\n" +
                    "            </diffuse>\n" +
                    "            <specular>\n" +
                    "              <color sid=\"specular\">0.5   0.5   0.5   1</color>\n" +
                    "            </specular>\n" +
                    "            <shininess>\n" +
                    "              <float sid=\"shininess\">250</float>\n" +
                    "            </shininess>\n" +
                    "            <transparent>\n" +
                    "              <color sid=\"transparent\">1   1   1   1</color>\n" +
                    "            </transparent>\n" +
                    "            <transparency>\n" +
                    "              <float sid=\"transparency\">1</float>\n" +
                    "            </transparency>\n" +
                    "            <index_of_refraction>\n" +
                    "              <float sid=\"index_of_refraction\">1.45</float>\n" +
                    "            </index_of_refraction>\n" +
                    "          </phong>\n" +
                    "        </technique>\n" +
                    "      </profile_COMMON>\n" +
                    "    </effect>\n";
            library_materials += "   <material id=\"material"+i+"\" name=\"material"+i+"\">\n" +
                    "      <instance_effect url=\"#material"+i+"-fx\"/>\n" +
                    "    </material>\n";

            List<Double[]> point = new ArrayList<>();
            for(int z =0;z<data2.size();z++){
    
                JsonNode data5 =  data2.get(z);
                if(data5 != null){
    
                    Double[] data3 ={
    data5.get(0).asDouble(),data5.get(1).asDouble()};
                    String Z1 = "50.0";
                    data3[1] = (data3[1]);
                    data3[0] = (data3[0]);
                    point.add(data3);
                }
            }
            // 计算面周长
            Double perimeter = (double) 0;
            List<Double> perimeters   = new ArrayList<>();
            for(int z = 0;z+1<point.size();z++){
    
                Double[] Around1 =  point.get(z);
                Double[] Around2 =  point.get(z+1);
                Point2D.Double p1 = new Point2D.Double( Around1[0], Around1[1]);
                Point2D.Double p2 = new Point2D.Double(Around2[0], Around2[1]);
                double distance = p1.distance(p2);
                perimeter += distance;
                perimeters.add(distance);
            }
            Double perimeter2 = (double) 0;
//            point.add(point.get(0));
            // 生成周边
            for(int z = 0;z+1<point.size();z++){
    
                Double[] Around1 =  point.get(z);
                Double[] Around2 =  point.get(z+1);
                perimeter2 += perimeters.get(z);
                objVn.add("vn -0.0000 -0.0000 -1.0000\n");
                objVT.add(((perimeter2-perimeters.get(z))/perimeter)+" 0.0");
                objVT.add(perimeter2/perimeter+" 0.0 ");
                objVT.add(perimeter2/perimeter+" 1.0 ");
                objVT.add(((perimeter2-perimeters.get(z))/perimeter)+" 1.0 ");
                String F1 = objV.size() + " " + (objV.size() + 1)+ " " + (objV.size() + 2)+ " " ;
                F1 += objV.size() + " " + (objV.size() + 2)+ " " + (objV.size() + 3);
                String V1 =  Around1[0] + " " + Z + " " + Around1[1] + " ";
                String V2 =  Around2[0] + " " + Z + " " + Around2[1] + " ";
                String V3 =  Around2[0] + " " + ZH + " " + Around2[1] + " ";
                String V4 =  Around1[0] + " " + ZH + " " + Around1[1] + " ";
                f +=1;
                objV.add(V1);objV.add(V2);objV.add(V3);objV.add(V4);
                objF.add(F1);
            }
            point.add(point.get(0));
            List<Coordinate> coordinateList = new ArrayList<>();
            for (int c =0;c<point.size();c++){
    
                coordinateList.add(new Coordinate(point.get(c)[0],point.get(c)[1],0));
            }
            Coordinate[] coords = coordinateList.toArray(new Coordinate[0]);
            GeometryFactory geomFactory = new GeometryFactory();
            LinearRing shell = geomFactory.createLinearRing(coords);
            Polygon polygon = geomFactory.createPolygon(shell, null);
            DelaunayTriangulationBuilder builders = new DelaunayTriangulationBuilder();
            builders.setSites(polygon);
            GeometryCollection triangles = (GeometryCollection) builders.getTriangles(geomFactory);
//            int bc = objV.size();
            for (int c = 0; c < triangles.getNumGeometries(); c++) {
    
                Polygon triangle = (Polygon) triangles.getGeometryN(c);
                boolean isInnerPolygonContained =  polygon.intersects(triangle)&& !polygon.touches(triangle);
                if(isInnerPolygonContained){
    

                    //生成顶部
                    objVT.add("0.0 0.0 ");
                    objVT.add("1.0 0.0 ");
                    objVT.add("1.0 1.0 ");
                    String F1 = objV.size() + " " + (objV.size()+1) + " " + (objV.size()+2) + " ";

                    objVn.add("vn -0.0000 -0.0000 -1.0000\n");
                    String V1 = triangle.getCoordinates()[0].x + " 0 " + triangle.getCoordinates()[0].y + " ";
                    String V2 = triangle.getCoordinates()[1].x + " 0 "  + triangle.getCoordinates()[1].y + " ";
                    String V3 = triangle.getCoordinates()[2].x + " 0 "  + triangle.getCoordinates()[2].y + " ";
                    objV.add(V1);objV.add(V2);objV.add(V3);
                    objF.add(F1);
                    f +=1;
                    //生成底部
                    objVT.add("0.0 0.0 ");
                    objVT.add("1.0 0.0 ");
                    objVT.add("1.0 1.0 ");
                    String F2 = objV.size() + " " + (objV.size()+1) + " " + (objV.size()+2) + " ";
                    V1 = triangle.getCoordinates()[0].x + " " + ZH + " " + triangle.getCoordinates()[0].y + " ";
                    V2 = triangle.getCoordinates()[1].x + " " + ZH + " " + triangle.getCoordinates()[1].y + " ";
                    V3 = triangle.getCoordinates()[2].x + " " + ZH + " " + triangle.getCoordinates()[2].y + " ";
                    objV.add(V1);objV.add(V2);objV.add(V3);
                    objF.add(F2);
                    f +=1;

                }
            }
            objAll.add("o Cylinder_"+index+"\n");

            index+=1;
            String positions_array = "";
            String tex_array ="";
            String p = "";
            String vcount = "";
            String normals_array ="";
            for(int b =0;b<objV.size();b++){
    
                positions_array +=objV.get(b) ;
                normals_array +="-0 -0 -1 ";
            }


            for(int b =0;b<objVT.size();b++){
    
                tex_array += objVT.get(b)+" ";
            }

            for(int b =0;b<objF.size();b++){
    
                p += objF.get(b)+" ";
                if(objF.get(b).split(" ").length==6){
    
                    vcount += "3 3 ";
                }else{
    
                    vcount += "3 ";
                }

            }
            objVTs+=objV.size();
            library_geometries +="  <geometry id=\"meshId"+i+"\" name=\"meshId"+i+"_name\" >\n" +
                    "      <mesh>\n" +
                    "   <source id=\"meshId"+i+"-positions\" name=\"meshId"+i+"-positions\">\n" +
                    "  <float_array id=\"meshId"+i+"-positions-array\" count=\""+objV.size()*3+"\">" +
                    positions_array +
                    " </float_array>\n" +
                    "    <technique_common>\n" +
                    "            <accessor count=\""+objV.size()+"\" offset=\"0\" source=\"#meshId"+i+"-positions-array\" stride=\"3\">\n" +
                    "              <param name=\"X\" type=\"float\" />\n" +
                    "              <param name=\"Y\" type=\"float\" />\n" +
                    "              <param name=\"Z\" type=\"float\" />\n" +
                    "            </accessor>\n" +
                    "          </technique_common>\n" +
                    "        </source>\n";
            library_geometries += "  <source id=\"meshId"+i+"-normals\" name=\"meshId"+i+"-normals\">\n" +
                    "       <float_array id=\"meshId"+i+"-normals-array\" count=\""+objV.size()*3+"\">\n" +
                    normals_array +
                    "       </float_array>\n" +
                    "       <technique_common>\n" +
                    "            <accessor count=\"2250\" offset=\"0\" source=\"#meshId"+i+"-normals-array\" stride=\"3\">\n" +
                    "              <param name=\"X\" type=\"float\" />\n" +
                    "              <param name=\"Y\" type=\"float\" />\n" +
                    "              <param name=\"Z\" type=\"float\" />\n" +
                    "            </accessor>\n" +
                    "          </technique_common>\n" +
                    "        </source>\n";
            library_geometries += "<source id=\"meshId"+i+"-tex0\" name=\"meshId"+i+"-tex0\">\n" +
                    "          <float_array id=\"meshId"+i+"-tex0-array\" count=\""+objV.size()*2+"\">" +
                    tex_array+
                    "</float_array>\n" +
                    "    <technique_common>\n" +
                    "            <accessor count=\""+objV.size()+"\" offset=\"0\" source=\"#meshId"+i+"-tex0-array\" stride=\"2\">\n" +
                    "              <param name=\"S\" type=\"float\" />\n" +
                    "              <param name=\"T\" type=\"float\" />\n" +
                    "            </accessor>\n" +
                    "          </technique_common>\n" +
                    "        </source>\n";
            library_geometries += "   <vertices id=\"meshId"+i+"-vertices\">\n" +
                    "          <input semantic=\"POSITION\" source=\"#meshId"+i+"-positions\" />\n" +
                    "        </vertices>\n";
            library_geometries +=  "<polylist count=\"900\" material=\"defaultMaterial\">\n" +
                    "          <input offset=\"0\" semantic=\"VERTEX\" source=\"#meshId"+i+"-vertices\" />\n" +
                    "          <input offset=\"0\" semantic=\"NORMAL\" source=\"#meshId"+i+"-normals\" />\n" +
                    "          <input offset=\"0\" semantic=\"TEXCOORD\" source=\"#meshId"+i+"-tex0\" set=\"0\" />\n" +
                    "           <vcount>" +
                    vcount+
                    "</vcount>\n" +
                    "            <p>" +
                    p+
                    "</p>\n" +
                    "    </polylist>\n" +
                    "    </mesh>\n" +
                    "    </geometry>\n";
            library_visual_scenes+=
                    "       <node id=\"Cylinder_"+(i+1)+"\"  name=\"Cylinder_"+(i+1)+"\" type=\"NODE\">\n" +
                    "        <matrix sid=\"matrix\">1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</matrix>\n" +
                    "        <instance_geometry url=\"#meshId"+i+"\">\n" +
                    "          <bind_material>\n" +
                    "            <technique_common>\n" +
                    "              <instance_material symbol=\"defaultMaterial\" target=\"#material"+i+"\">\n" +
                    "                <bind_vertex_input semantic=\"CHANNEL0\" input_semantic=\"TEXCOORD\" input_set=\"0\"/>\n" +
                    "              </instance_material>\n" +
                    "            </technique_common>\n" +
                    "          </bind_material>\n" +
                    "        </instance_geometry>\n" +
                    "      </node>\n";
        }

        library_images += "  </library_images>\n";
        library_effects += "   </library_effects>\n";
        library_materials += "  </library_materials>\n";
        library_geometries += "  </library_geometries>\n";
        library_visual_scenes +="  </visual_scene>\n" +
                "  </library_visual_scenes>\n";
        Collada += asset +
                library_images +
                library_effects+
                library_effects+
                library_materials+library_geometries+
                " <library_controllers>\n" +
                "  </library_controllers>\n"+
                library_visual_scenes+"  " +
                "  <scene>\n" +
                "    <instance_visual_scene url=\"#models.obj\" />\n" +
                "  </scene>\n" +
                "</COLLADA>";
        CreateObj(objFilename,Collada);
        createZip(createPath+"\\archive.zip",createPath);

        return createPath;
    }
    /**
     * 得到最大最小值。
     *
     * @param features 示例参数 {"features"}
     * @return MaxMin
     */
    private  static Double[] getMaxMin(JsonNode features){
    
        Double[] MaxMin = new Double[2];
        MaxMin[0] = -100000000000000.0;
        MaxMin[1] = -100000000000000.0;
        for(int i =0;i<features.size();i++) {
    
            JsonNode data1 = features.get(i).get("geometry");
            JsonNode data2 = data1.get("coordinates");
            for (int z = 0; z < data2.size(); z++) {
    
                JsonNode data5 = data2.get(z);
                System.out.println(data5.size());
                if (data5.size() == 2) {
    
//                    Double[] data3 = CoordinateConverter(data5.get(0), data5.get(1));
                    Double[] data3 ={
    data5.get(0).asDouble(),data5.get(1).asDouble()};
                    if (MaxMin[0] < data3[0]) {
    
                        MaxMin[0] = data3[0];
                    }
                    if (MaxMin[1] < data3[1]) {
    
                        MaxMin[1] = data3[1];
                    }
                }
            }
        }
        return   MaxMin;
    }
    /**
     * 创造obj文件。
     *
     * @param objFilename 示例参数 {"features"}
     * @param mtlFilename 示例参数 {"features"}
     * @param mtl 示例参数 {"features"}
     * @param objAll 示例参数 {"features"}
     * @return MaxMin
     */
    private static void CreateObj(
            String objFilename,
            String mtlFilename
    ) throws IOException{
    
        FileWriter mtlWriter = new FileWriter(objFilename);
        mtlWriter.write(mtlFilename);
        mtlWriter.close();
        System.out.println("Dae模型文件已生成。");

    }
    /**
     * 创造压缩文件。
     *
     * @param zipFile 示例参数 {"features"}
     * @param sourceFolder 示例参数 {"features"}
     * @return MaxMin
     */
    private static void createZip(String zipFile,String sourceFolder) throws IOException {
    
        File file = new File(sourceFolder);
        file.createNewFile();
        // 创建输出压缩文件流
        try (FileOutputStream fos = new FileOutputStream(zipFile);
             ZipOutputStream zos = new ZipOutputStream(fos)) {
    
            // 压缩文件夹及其内容
            compressFolder(new File(sourceFolder), zos, "",zipFile);

            System.out.println("文件夹及其内容已成功压缩为:" + zipFile);
        } catch (IOException e) {
    
            e.printStackTrace();
        }

    }
    /**
     * 创造压缩文件。
     *
     * @param folder 示例参数 {"features"}
     * @param zos 示例参数 {"features"}
     * @param parentPath 示例参数 {"features"}
     * @param excludeFile 示例参数 {"features"}
     * @return MaxMin
     */
    private static void compressFolder(File folder, ZipOutputStream zos, String parentPath, String excludeFile) throws IOException {
    
        for (File file : folder.listFiles()) {
    
            if (file.isDirectory()) {
    
                // 递归压缩子目录
                compressFolder(file, zos, parentPath + file.getName() + "/", excludeFile);
            } else {
    
                // 排除zip文件
                if (!file.getAbsolutePath().equals(excludeFile) && !isZipFile(file)) {
    
                    // 压缩文件
                    String entryPath = parentPath + file.getName();
                    zos.putNextEntry(new ZipEntry(entryPath));

                    try (FileInputStream fis = new FileInputStream(file)) {
    
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = fis.read(buffer)) > 0) {
    
                            zos.write(buffer, 0, length);
                        }
                    }

                    zos.closeEntry();
                }
            }
        }
    }
    /**
     * 排除压缩文件。
     *
     * @param file 示例参数 {"features"}
     * @return MaxMin
     */
    private static boolean isZipFile(File file) {
    
        String fileName = file.getName();
        return fileName.endsWith(".zip") || fileName.endsWith(".ZIP");
    }
    //添加压缩包
    private static void addToZip(File file, ZipOutputStream zos, String parentFolder) throws IOException {
    
        FileInputStream fis = new FileInputStream(file);

        // 获取文件相对于父文件夹的路径
        String entryPath = parentFolder + file.getName();

        // 创建ZipEntry对象并设置名称
        ZipEntry entry = new ZipEntry(entryPath);

        // 将ZipEntry对象添加到ZipOutputStream中
        zos.putNextEntry(entry);

        // 从输入流中读取数据并写入压缩文件中
        byte[] buffer = new byte[1024];
        int length;
        while ((length = fis.read(buffer)) >= 0) {
    
            zos.write(buffer, 0, length);
        }

        // 关闭当前条目并将流定位到下一个条目的开头
        zos.closeEntry();
        fis.close();
    }
    public static char generateRandomLetter() {
    
        Random random = new Random();
        int randomNumber = random.nextInt(26);  // 生成一个0到25之间的随机数

        char randomLetter = (char) (randomNumber + 'A');  // 将随机数转换为对应的大写字母

        return randomLetter;
    }
    private  static Double[] CoordinateConverter(JsonNode longitude,JsonNode latitude){
    
        double lonRad = Math.toRadians(longitude.asDouble());
        double latRad = Math.toRadians(latitude.asDouble());
        // 椭球体参数
        double a = 6378137;   // 长半轴
        double e = 0.081819190842621;  // 第一偏心率的平方根
        // 计算转换后的坐标
        double x = a * lonRad;
        double y = a * Math.log(Math.tan(Math.PI / 4 + latRad / 2) * Math.pow((1 - e * Math.sin(latRad)) / (1 + e * Math.sin(latRad)), e / 2));
        Double[] data =new Double[2];
        data[0] = x;
        data[1] = y;
        return data;
    }
    private static  void CreateDirPath(String folderPath)throws IOException{
    
        File folder = new File(folderPath);
        if (folder.mkdir()) {
    
//            System.out.println("Folder created successfully.");
        } else {
    
//            System.out.println("Failed to create folder.");
        }
    }
    //创建文件
    private static void CreateDir(String objFilename) throws IOException {
    
        File file = new File(objFilename);
        if (file.createNewFile()) {
    
        } else {
    
        }

    }
    //导出纹理
    private static void loadTextrue(String base64String,String outputPath) throws IOException {
    
        String modifiedStr = base64String.substring(1, base64String.length() - 1);
        String[] a= modifiedStr.split(",");
        byte[] imageBytes = Base64.getDecoder().decode(a[1]);
        // 创建输出流
        OutputStream outputStream = new FileOutputStream(outputPath);
        // 将字节数组写入输出流
        outputStream.write(imageBytes);
        // 关闭输出流
        outputStream.close();

    }
    @PostMapping("/getGeojson")
    @CrossOrigin(origins = "*")
    public ResponseEntity<byte[]> downloadFile(@RequestBody String geojson, HttpServletResponse response) throws IOException {
    
        ObjModelGenerator objModelGenerator = new ObjModelGenerator();
        String filePath =  LoadObj(geojson);
        String zip =  filePath+"\\archive.zip";
        byte[] fileBytes = getFileBytes(zip);
        // 设置响应头部信息
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", "archive.zip");
        deleteFolder(new File(filePath));
        return new ResponseEntity<>(fileBytes, headers, HttpStatus.OK);
    }
    //得到压缩包文件流
    private byte[] getFileBytes(String filePath) throws IOException {
    
        File file = new File(filePath);
        byte[] fileBytes = new byte[(int) file.length()];
        try (FileInputStream fis = new FileInputStream(file)) {
    
            fis.read(fileBytes);
        }
        return fileBytes;
    }
    //删除生成的文件
    private static void deleteFolder(File folder) {
    
        if (folder.isDirectory()) {
    
            File[] files = folder.listFiles();
            if (files != null) {
    
                for (File file : files) {
    
                    deleteFolder(file);
                }
            }
        }
        // 删除文件或空目录
        folder.delete();
    }
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_55104937/article/details/135955717

智能推荐

适合入门的8个趣味机器学习项目-程序员宅基地

文章浏览阅读86次。首发地址:https://yq.aliyun.com/articles/221708谈到机器学习,相信很多除学者都是通过斯坦福大学吴恩达老师的公开课《Machine Learning》开始具体的接触机器学习这个领域,但是学完之后又不知道自己的掌握情况,缺少一些实际的项目操作。对于机器学习的相关竞赛挑战,有些项目的门槛有些高,参加后难以具体的实现,因此造..._scrath五子棋下载

oracle 12c avg,Oracle 12c新特性系列专题-安徽Oracle授权认证中心-程序员宅基地

文章浏览阅读83次。原标题:Oracle 12c新特性系列专题-安徽Oracle授权认证中心 随着Oracle database 12c的普及,数据库管理员 (DBA) 的角色也随之发生了转变。 Oracle 12c数据库对 DBA 而言是下一代数据管理。它让 DBA 可以摆脱单调的日常管理任务,能够专注于如何从数据中获取更多价值。未来我们会推出基于Oracle12c的技术文章,帮助DBA尽快掌握新一代数据库的新特性..._ilm add policy row store compress advanced row after

第七周项目三(负数把正数赶出队列)-程序员宅基地

文章浏览阅读150次。问题及代码:*Copyright(c)2016,烟台大学计算机与控制工程学院 *All right reserved. *文件名称:负数把正数赶出队列.cpp *作者:张冰 *完成日期;2016年10月09日 *版本号;v1.0 * *问题描述: 设从键盘输入一整数序列a1,a2,…an,试编程实现: 当ai>0时,ai进队,当ai<0时,将队首元素出队,当ai

Linux命名空间学习教程(二) IPC-程序员宅基地

文章浏览阅读150次。本文讲的是Linux命名空间学习教程(二) IPC,【编者的话】Docker核心解决的问题是利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源。而 LXC所实现的隔离性主要是来自内核的命名空间, 其中pid、net、ipc、mnt、uts 等命名空间将容器的进程、网络、消息、文件系统和hostname 隔离开。本文是Li..._主机的 ipc 命名空间

adb强制安装apk_adb绕过安装程序强制安装app-程序员宅基地

文章浏览阅读2w次,点赞5次,收藏7次。在设备上强制安装apk。在app已有的情况下使用-r参数在app版本低于现有版本使用-d参数命令adb install -r -d xxx.apk_adb绕过安装程序强制安装app

随便推点

STM32F407 越界问题定位_stm32flash地址越界怎么解决-程序员宅基地

文章浏览阅读290次。如果是越界进入硬件错误中断,MSP 或者 PSP 保存错误地址,跳转前会保存上一次执行的地址,lr 寄存器会保存子函数的地址,所以如果在 HardFault_CallBack 中直接调用 C 语言函数接口会间接修改了 lr,为了解决这个问题,直接绕过 lr 的 C 语言代码,用汇编语言提取 lr 寄存器再决定后面的操作。由于 STM32 加入了 FreeRTOS 操作系统,可能导致无法准确定位,仅供参考(日常编程需要考虑程序的健壮性,特别是对数组的访问,非常容易出现越界的情况)。_stm32flash地址越界怎么解决

利用SQL注入上传木马拿webshell-程序员宅基地

文章浏览阅读1.8k次。学到了一种操作,说实话,我从来没想过还能这样正常情况下,为了管理方便,许多管理员都会开放MySQL数据库的secure_file_priv,这时就可以导入或者导出数据当我如图输入时,就会在D盘创建一个名为123456.php,内容为<?php phpinfo();?>的文件我们可以利用这一点运用到SQL注入中,从拿下数据库到拿下目标的服务器比如我们在使用联合查询注入,正常是这样的语句http://xxx?id=-1 union select 1,'你想知道的字段的内容或查询语句',

Html CSS的三种链接方式_html链接css代码-程序员宅基地

文章浏览阅读2.9w次,点赞12次,收藏63次。感谢原文:https://blog.csdn.net/abc5382334/article/details/24260817感谢原文:https://blog.csdn.net/jiaqingge/article/details/52564348Html CSS的三种链接方式css文本的链接方式有三种:分别是内联定义、链入内部css、和链入外部css1.代码为:<html>..._html链接css代码

玩游戏哪款蓝牙耳机好?2021十大高音质游戏蓝牙耳机排名_适合游戏与运动的高音质蓝牙耳机-程序员宅基地

文章浏览阅读625次。近几年,蓝牙耳机市场发展迅速,越来越多的消费者希望抛弃线缆,更自由地听音乐,对于运动人士来说,蓝牙耳机的便携性显得尤为重要。但目前市面上的大多数蓝牙耳机实际上都是“有线”的,运动过程中产生的听诊器效应会严重影响听歌的感受。而在“真无线”耳机领域,除了苹果的AirPods外,可供选择的产品并不多,而AirPods又不是为运动场景打造的,防水能力非常差。那么对于喜欢运动又想要“自由”的朋友来说,有没有一款产品能够满足他们的需求呢?下面这十款小编专门为大家搜罗的蓝牙耳机或许就能找到适合的!网红击音F1_适合游戏与运动的高音质蓝牙耳机

iOS 17 测试版中 SwiftUI 视图首次显示时状态的改变导致动画“副作用”的解决方法-程序员宅基地

文章浏览阅读1k次,点赞6次,收藏7次。在本篇博文中,我们在 iOS 17 beta 4(SwiftUI 5.0)测试版中发现了 SwiftUI 视图首次显示时状态的改变会导致动画“副作用”的问题,并提出多种解决方案。

Flutter 自定义 轮播图的实现_flutter pageview轮播图 site:csdn.net-程序员宅基地

文章浏览阅读1.9k次。  在 上篇文章–Flutter 实现支持上拉加载和下拉刷新的 ListView 中,我们最终实现的效果是在 listView 上面留下了一段空白,本意是用来加载轮播图的,于是今天就开发了一下,希望能给各位灵感。一 、效果如下说一下大体思路   其实图片展示是用的 PageView ,然后,下面的指示器 是用的 TabPageSelector ,当然整体是用 Stack 包裹起来的。1、..._flutter pageview轮播图 site:csdn.net