全是代码,整个逻辑都在里面,可贴纹理
/**
* 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();
}
}
文章浏览阅读6.2k次,点赞6次,收藏26次。我是一个深度学习代码小白,请你用中文写上注释,能让我能轻松理解下面这段代码。注意包含所有函数、调用和参数的注释。以同样的python代码块样式返回你写的代码给我。代码看累了,就看《动手学深度学习》文档:基于PyTorch框架,从底层函数实现基础功能,再到框架的高级功能。努力上路的小白一枚,麻烦路过的大佬指导一二,同时希望能和大家交流学习~争取更新学习这个文档的专栏,记录学习过程。量身定做了一套话术hhh,亲身测试还不错。这个感觉更浅一点儿,之后复习看吧。20天吃掉那只Pytorch。_深度学习程序怎么读
文章浏览阅读2.7w次,点赞126次,收藏1.2k次。耗废1024根秀发,Java学习路线图来了,整合了自己所学的所有技术整理出来的2022最新版Java学习路线图,适合于初、中级别的Java程序员。_java学习路线
文章浏览阅读4.4k次。1.7-savingPNG介绍代码详情函数详解savePNGFile()源码savePNGFile()源码提示savePNGFile()推荐用法处理结果代码链接介绍PCL提供了将点云的值保存到PNG图像文件的可能性。这只能用有有序的云来完成,因为结果图像的行和列将与云中的行和列完全对应。例如,如果您从类似Kinect或Xtion的传感器中获取了点云,则可以使用它来检索与该云匹配的640x480 RGB图像。代码详情#include <pcl / io / pcd_io.h>#incl_pcl::io:savepng
文章浏览阅读936次。吸引妹子的关键点不在于喝什么咖啡,主要在于竖立哪种男性人设。能把人设在几分钟内快速固定下来,也就不愁吸引对口的妹子了。我有几个备选方案,仅供参考。1. 运动型男生左手单手俯卧撑,右手在键盘上敲代码。你雄壮的腰腹肌肉群活灵活现,简直就是移动的春药。2.幽默男生花 20 块找一个托(最好是老同学 or 同事)坐你对面。每当你侃侃而谈,他便满面涨红、放声大笑、不能自已。他笑的越弱_咖啡厅写代码
文章浏览阅读1.2w次,点赞5次,收藏5次。今天 (应该是昨天了,昨晚太晚了没发出去)下午参加了腾讯WXG的面委会面试。前面在牛客上搜索了面委会相关的面经普遍反映面委会较难,因为都是微信的核心大佬,问的问题也会比较深。昨晚还蛮紧张的,晚上都没睡好。面试使用的是腾讯会议,时间到了面试官准时进入会议。照例是简单的自我介绍,然后是几个常见的基础问题:例如数据库索引,什么时候索引会失效、设计模式等。这部分比较普通,问的也不是很多,不再赘述。现在回想下,大部分还是简历上写的技能点。接下来面试官让打开项目的代码,对着代码讲解思路。我笔记本上没有这部分代码,所_腾讯面委会面试是什么
文章浏览阅读382次,点赞3次,收藏4次。AI绘画自动生成器是一种利用人工智能技术,特别是深度学习算法,来自动创建视觉艺术作品的软件工具。这些工具通常基于神经网络模型,如生成对抗网络(GANs),通过学习大量的图像数据来生成新的图像。AI绘画自动生成器作为艺术与科技结合的产物,正在开启艺术创作的新篇章。它们不仅为艺术家和设计师提供了新的工具,也为普通用户提供了探索艺术的机会。随着技术的不断进步,我们可以预见,AI绘画自动生成器将在未来的创意产业中发挥越来越重要的作用。
文章浏览阅读1.7k次。理解为ListView 的三种形式吧ListView 默认构造但是这种方式创建的列表存在一个问题:对于那些长列表或者需要较昂贵渲染开销的子组件,即使还没有出现在屏幕中但仍然会被ListView所创建,这将是一项较大的开销,使用不当可能引起性能问题甚至卡顿直接返回的是每一行的Widget,相当于ios的row。行高按Widget(cell)高设置ListView.build 就和io..._flutter listview.separated和listview.builder
文章浏览阅读1.4k次,点赞4次,收藏14次。废话不多说直接上干货1.js运行机制JavaScript单线程,任务需要排队执行同步任务进入主线程排队,异步任务进入事件队列排队等待被推入主线程执行定时器的延迟时间为0并不是立刻执行,只是代表相比于其他定时器更早的被执行以宏任务和微任务进一步理解js执行机制整段代码作为宏任务开始执行,执行过程中宏任务和微任务进入相应的队列中整段代码执行结束,看微任务队列中是否有任务等待执行,如果有则执行所有的微任务,直到微任务队列中的任务执行完毕,如果没有则继续执行新的宏任务执行新的宏任务,凡是在..._前端面试
文章浏览阅读1k次。(3)若没有查到,则将请求发给根域DNS服务器,并依序从根域查找顶级域,由顶级查找二级域,二级域查找三级,直至找到要解析的地址或名字,即向客户机所在网络的DNS服务器发出应答信息,DNS服务器收到应答后现在缓存中存储,然后,将解析结果发给客户机。(3)若没有查到,则将请求发给根域DNS服务器,并依序从根域查找顶级域,由顶级查找二级域,二级域查找三级,直至找到要解析的地址或名字,即向客户机所在网络的DNS服务器发出应答信息,DNS服务器收到应答后现在缓存中存储,然后,将解析结果发给客户机。_linux
文章浏览阅读7.9k次,点赞26次,收藏66次。HTML DOM——文档元素的操作1、通过id获取文档元素任务描述相关知识什么是DOM文档元素节点树通过id获取文档元素代码文件2、通过类名获取文档元素任务描述相关知识通过类名获取文档元素代码文件3、通过标签名获取文档元素任务描述相关知识通过标签名获取文档元素获取标签内部的子元素代码文件4、html5中获取元素的方法一任务描述相关知识css选择器querySelector的用法代码文件5、html5中获取元素的方法二任务描述相关知识querySelectorAll的用法代码文件6、节点树上的操作任务描述相关_javascript学习手册十三:html dom——文档元素的操作(一)
文章浏览阅读132次。《LeetCode学习》172. 阶乘后的零(java篇)_java 给定一个整数n,返回n!结果尾数中零的数量
文章浏览阅读426次。请注意,本文将要给大家分享的并不是开启公众号的安全操作风险提醒,而是当公众号粉丝给公众号发消息的时候,公众号的管理员和运营者如何能在手机上立即收到消息通知,以及在手机上回复粉丝消息。第一步:授权1、在微信中点击右上角+,然后选择“添加朋友”,然后选择“公众号”,然后输入“微小助”并关注该公众号。2、进入微小助公众号,然后点击底部菜单【新增授权】,如下图所示:3、然后会打开一个温馨提示页面。请一定要..._php微信公众号服务提示