全是代码,整个逻辑都在里面,可贴纹理
/**
* 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();
}
}
文章浏览阅读3.9k次,点赞20次,收藏86次。显卡的工作是负责画面的渲染和输出,例如你在玩一个大型游戏,CPU的工作是根据游戏预设的各种算法计算出接下来会发生什么,并折合成海量的数据发送给显卡,显卡再对这些数据进行计算,渲染成1帧1帧的图像,传输到显示器,从而将画面呈现在我们眼前,而且显卡是在实时计算渲染,所以对显卡性能的要求就非常高,因此这就是我们平常所说的你想打游戏,就得有一张好的显卡。而看视频就不一样了,视频资源是已经被计算好的数据,先看只负责简单处理再输出就可以了,不需要再自己计算。就类比写作业,玩游戏就是自己计算然后写在本子上,看视频就是抄作_显卡分类
文章浏览阅读1.7k次,点赞4次,收藏25次。背景ICP算法是点云配准(registration)领域的主流算法,在学习过程中我尝试使用C++复现了ICP算法。我参考的是经典ICP论"P. Besl, N. McKay. ‘A Method for Registration of 3-D Shapes,’ IEEE Trans. on Pattern Analysis and Machine Intel., vol. 14, no. 2, pp. 239-256,1992"。建议论文和代码搭配阅读。环境windows10 + pcl1.11.1_method for registration of 3-d shapes
文章浏览阅读3.7k次。web.xml配置如下: springm_spring 过滤js代码
文章浏览阅读8.5k次,点赞2次,收藏17次。1、任务分类 游戏中任务可以分为主线任务、支线任务、日常任务、周任务、节日活动任务,其中周任务和节日任务可以根据设定的日期进行开启关闭,属于重复性任务。2、游戏条件 各类任务开启条件:1、玩家等级 2、玩家攻击力3、前置任务等等 完成条件:玩家进行任务进度是否达成 任务关闭:1、玩家领取奖励后关闭任务。2、时间过期3..._游戏任务种类
文章浏览阅读6.4k次,点赞8次,收藏35次。1. codeforces codeforces(这个网站每天会有比赛,一起打CF吧!)http://codeforces.com/problemset2. topcoder:http://www.topcoder.com/challenges/3. kattis 这个网站有历年的ICPC真题 https://open.kattis.com/4. 洛谷:..._清华大学 acm网站
文章浏览阅读599次。可行1:当E:\\a.txt 已经存在,且程序字符=Unicode的时候,下面代码可以正常#include <iostream>#include <windows.h>int main(){ HANDLE hFILE = (HANDLE)CreateFile(L"E:\\a.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); if (hFILE == INVALID__::createfilea中文打不开
文章浏览阅读1.1k次,点赞2次,收藏10次。paper:https://arxiv.org/pdf/2011.03972.pdfcode:https://github.com/sunsmarterjie/SDL-Skeleton摘要传统的物体骨架检测网络通常是手工制作的。 虽然有效,但它们需要密集的先验知识来为不同粒度的对象配置具有代表性的特征。 本文提出了自适应线性跨度网络(AdaLSN),在神经架构搜索(NAS)的驱动下,自动配置和集成目标骨架检测的尺度感知特征。AdaLSN是用线性跨度理论建立的,它为多尺度深度特征融合提供了最早的解释之一_线性跨度网络
文章浏览阅读662次。python的内存管理机制先从较浅的层面来说,Python的内存管理机制可以从三个方面来讲(1)垃圾回收(2)引用计数(3)内存池机制一、垃圾回收:python不像C++,Java等语言一样,他们可以不用事先声明变量类型而直接对变量进行赋值。对Python语言来讲,对象的类型和内存都是在运行时确定的。这也是为什么我们称Python语言为动态类型的原因(这里我们把动态类型可以简单的归结为对变量内存地址_python 创建金字塔 显示大内存图片
文章浏览阅读547次。试用QT中的多语言翻译基本原理:为了在使用多语言,必须做两件事情:1,把想要翻译的字符串放入tr()中,如 QString str=tr("Legal");2, 在开始的时候载入预先制作好的翻译文件(.qm)。以下利用Qt提供的工具,把翻译文件制作出来,并在程_qt translate file语言选什么
文章浏览阅读433次。Atitit 性能指标与性能提升的5个原则与性能提升模型 1. 性能的几个指标主要是响应时间(Response time) 2.吞吐量(Throughput)12. 性能提升的5个原则与性能提升模型 22.1. 分类优先级,与分区域,减少要操作或提取的内容与范围 22.2. div分而治之 聚沙成塔 分布式并发 22.3. 大力提升单体处理能力 22.4. _升级性能指标
文章浏览阅读5.3k次。12月17日,华为终端官方微博公布了新品信息,预告新款华为智慧屏将于12月21日下午14时的华为全屋智能及智慧屏新品发布会上正式亮相。华为智慧屏宣传海报文案透露出此次新款华为智慧屏将在语音及智能交互上带来惊喜体验。且在此之前,华为消费者业务IoT产品线总裁支浩曾透露发布于年底的全新华为智慧屏系列将定位大众娱乐。另外,随着鸿蒙系统2.0的升级,华为智慧屏系列也正式成为首批搭载鸿蒙2.0的终端产品。根..._华为电视安装第三方软件
文章浏览阅读179次。详解Java在redis中进行对象的缓存发布时间:2020-08-30 07:16:04来源:脚本之家阅读:110作者:pj小小码农Java在redis中进行对象的缓存一般有两种方法,这里介绍序列化的方法,个人感觉比较方便,不需要转来转去。一、首先,在存储的对象上实现序列化的接口package com.cy.example.entity.system;import java.util.List;i..._java redis设置person对象