|
@@ -0,0 +1,345 @@
|
|
|
+package com.fdkankan.scene.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.io.FileUtil;
|
|
|
+import cn.hutool.core.util.CharsetUtil;
|
|
|
+import cn.hutool.core.util.ZipUtil;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.fdkankan.common.constant.ErrorCode;
|
|
|
+import com.fdkankan.common.exception.BusinessException;
|
|
|
+import com.fdkankan.common.util.FileUtils;
|
|
|
+import com.fdkankan.fyun.face.FYunFileServiceInterface;
|
|
|
+import com.fdkankan.model.constants.ConstantFileName;
|
|
|
+import com.fdkankan.model.constants.ConstantFilePath;
|
|
|
+import com.fdkankan.model.constants.UploadFilePath;
|
|
|
+import com.fdkankan.model.utils.ComputerUtil;
|
|
|
+import com.fdkankan.model.utils.CreateObjUtil;
|
|
|
+import com.fdkankan.scene.entity.*;
|
|
|
+import com.fdkankan.scene.service.*;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class ReverseSceneServiceImpl implements IReverseSceneService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IScenePlusService scenePlusService;
|
|
|
+ @Autowired
|
|
|
+ private IScenePlusExtService scenePlusExtService;
|
|
|
+ @Resource
|
|
|
+ private FYunFileServiceInterface fileServiceInterface;
|
|
|
+ @Autowired
|
|
|
+ private ISceneEditInfoService sceneEditInfoService;
|
|
|
+ @Autowired
|
|
|
+ private ISceneEditInfoExtService sceneEditInfoExtService;
|
|
|
+ @Autowired
|
|
|
+ private ISceneEditControlsService sceneEditControlsService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void reverseScene(JSONObject jsonObject) throws Exception {
|
|
|
+
|
|
|
+ String num = jsonObject.getString("num");
|
|
|
+ ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
|
|
|
+ ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
|
|
|
+ SceneEditInfo sceneEditInfo = sceneEditInfoService.getByScenePlusId(scenePlus.getId());
|
|
|
+ if(Objects.isNull(sceneEditInfo)){
|
|
|
+ sceneEditInfo = new SceneEditInfo();
|
|
|
+ sceneEditInfo.setScenePlusId(scenePlus.getId());
|
|
|
+ }
|
|
|
+ sceneEditInfoService.saveOrUpdate(sceneEditInfo);
|
|
|
+ SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByEditInfoId(sceneEditInfo.getId());
|
|
|
+ if(Objects.isNull(sceneEditInfoExt)){
|
|
|
+ sceneEditInfoExt = new SceneEditInfoExt();
|
|
|
+ sceneEditInfoExt.setEditInfoId(sceneEditInfo.getId());
|
|
|
+ sceneEditInfoExt.setScenePlusId(scenePlus.getId());
|
|
|
+ }
|
|
|
+ sceneEditInfoExtService.saveOrUpdate(sceneEditInfoExt);
|
|
|
+
|
|
|
+ SceneEditControls sceneEditControls = sceneEditControlsService.getBySceneEditId(sceneEditInfo.getId());
|
|
|
+ if(Objects.isNull(sceneEditControls)){
|
|
|
+ sceneEditControls = new SceneEditControls();
|
|
|
+ sceneEditControls.setEditInfoId(sceneEditInfo.getId());
|
|
|
+ }
|
|
|
+ sceneEditControlsService.saveOrUpdate(sceneEditControls);
|
|
|
+
|
|
|
+
|
|
|
+ String zipPath = scenePlusExt.getDataSource();
|
|
|
+ String zipParentDir = FileUtil.getParent(zipPath, 1);
|
|
|
+
|
|
|
+ //生成vision.txt
|
|
|
+ this.genVisionTxt(num, zipParentDir);
|
|
|
+
|
|
|
+ //解压
|
|
|
+ ZipUtil.unzip(zipPath, CharsetUtil.CHARSET_GBK);
|
|
|
+
|
|
|
+ //计算模型
|
|
|
+ this.genModel(num, zipParentDir);
|
|
|
+
|
|
|
+ //计算全景图
|
|
|
+ this.genPano(num, zipParentDir);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void genVisionTxt(String num, String zipParentDir) throws Exception {
|
|
|
+ String workJsonPath = zipParentDir + "/work.json";
|
|
|
+ JSONObject jsonObject = JSON.parseObject(workJsonPath);
|
|
|
+ JSONArray observers = jsonObject.getJSONArray("observers");
|
|
|
+ JSONObject visionTxtObj = new JSONObject();
|
|
|
+ List<JSONObject> sweepLocations = new ArrayList<>();
|
|
|
+ visionTxtObj.put("sweepLocations", sweepLocations);
|
|
|
+ for(int i = 0; i < observers.size(); i++){
|
|
|
+ JSONObject observerObj = (JSONObject) observers.get(i);
|
|
|
+ JSONObject sweepLocation = new JSONObject();
|
|
|
+ sweepLocations.add(sweepLocation);
|
|
|
+ sweepLocation.put("id", i);
|
|
|
+ sweepLocation.put("uuid", observerObj.getString("index"));
|
|
|
+
|
|
|
+ JSONObject pose = new JSONObject();
|
|
|
+ sweepLocation.put("pose", pose);
|
|
|
+ pose.put("rotation", observerObj.getJSONObject("quaternion"));
|
|
|
+ JSONObject translation = new JSONObject();
|
|
|
+ pose.put("translation", translation);
|
|
|
+ JSONArray positions = observerObj.getJSONArray("position");
|
|
|
+ for(int j = 0; j < positions.size(); j++){
|
|
|
+ Float v = (Float) positions.get(i);
|
|
|
+ if(i == 0){
|
|
|
+ translation.put("x", v);
|
|
|
+ }
|
|
|
+ if(i == 1){
|
|
|
+ translation.put("y", v);
|
|
|
+ }
|
|
|
+ if(i == 2){
|
|
|
+ translation.put("z", v);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ JSONObject puck = new JSONObject();
|
|
|
+ sweepLocation.put("puck", puck);
|
|
|
+ JSONArray standing_positions = observerObj.getJSONArray("standing_position");
|
|
|
+ for(int j = 0; j < standing_positions.size(); j++){
|
|
|
+ Float v = (Float) standing_positions.get(i);
|
|
|
+ if(i == 0){
|
|
|
+ puck.put("x", v);
|
|
|
+ }
|
|
|
+ if(i == 1){
|
|
|
+ puck.put("y", v);
|
|
|
+ }
|
|
|
+ if(i == 2){
|
|
|
+ puck.put("z", v);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ sweepLocation.put("group", 0);
|
|
|
+ sweepLocation.put("subgroup", observerObj.getInteger("floor_index"));
|
|
|
+ sweepLocation.put("device", 0);
|
|
|
+ sweepLocation.put("subdevice", 0);
|
|
|
+ sweepLocation.put("room", 0);
|
|
|
+
|
|
|
+ JSONObject ggaLocation = new JSONObject();
|
|
|
+ sweepLocation.put("ggaLocation", ggaLocation);
|
|
|
+ ggaLocation.put("StatusIndicator",0);
|
|
|
+ ggaLocation.put("satellitesCount",0);
|
|
|
+ ggaLocation.put("lon","");
|
|
|
+ ggaLocation.put("lat","");
|
|
|
+ ggaLocation.put("alt","");
|
|
|
+
|
|
|
+ sweepLocation.put("visibles", observerObj.get("visible_nodes"));
|
|
|
+ sweepLocation.put("visibles2", observerObj.get("visible_nodes"));
|
|
|
+ sweepLocation.put("visibles3", observerObj.get("visible_nodes"));
|
|
|
+ }
|
|
|
+
|
|
|
+ FileUtil.writeUtf8String(JSON.toJSONString(sweepLocations), zipParentDir + "vision.txt");
|
|
|
+
|
|
|
+ //转换modedata
|
|
|
+ CreateObjUtil.convertTxtToVisionmodeldata(zipParentDir + "vision.txt", zipParentDir + "vision.modeldata");
|
|
|
+
|
|
|
+ fileServiceInterface.uploadFile(zipParentDir + "vision.txt", String.format(UploadFilePath.IMG_VIEW_PATH, num) + "vision.txt");
|
|
|
+ fileServiceInterface.uploadFile(zipParentDir + "vision.modeldata", String.format(UploadFilePath.IMG_VIEW_PATH, num) + "vision.modeldata");
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void genPano(String num, String zipParentDir) throws Exception {
|
|
|
+ //全景图计算根目录
|
|
|
+ String target = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "reverseScene_images";
|
|
|
+ //解压缩文件存放目录
|
|
|
+ String targetImagesPath = target + "/extras/images/";
|
|
|
+
|
|
|
+ List<File> files = FileUtil.loopFiles(zipParentDir + "/src_pano/");
|
|
|
+ for (File file : files) {
|
|
|
+ String index = FileUtil.getName(file).split("_")[0];
|
|
|
+ FileUtil.copyContent(file, new File(targetImagesPath + index + ".jpg"), true);
|
|
|
+ }
|
|
|
+
|
|
|
+ FileUtil.copy(zipParentDir + "/vision.txt", target + "/extras/" + "vision.txt", true);
|
|
|
+ //data.json增加extras为执行重建算法
|
|
|
+ JSONObject floorplanJson = new JSONObject();
|
|
|
+ floorplanJson.put("has_source_images", true);
|
|
|
+ floorplanJson.put("has_vision_txt", true);
|
|
|
+
|
|
|
+ JSONObject dataJson = new JSONObject();
|
|
|
+ dataJson.put("extras", floorplanJson);
|
|
|
+ dataJson.put("split_type", "SPLIT_V8");
|
|
|
+ //V5表示不需要生成high,low文件
|
|
|
+ String skyboxType = "SKYBOX_V14";
|
|
|
+ dataJson.put("skybox_type", skyboxType);
|
|
|
+ FileUtil.writeUtf8String(JSON.toJSONString(dataJson), target + File.separator+"data.json");
|
|
|
+
|
|
|
+ this.uploadPanoramaHandler(num, target, targetImagesPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void uploadPanoramaHandler(String num,String target, String targetImagesPath) throws Exception {
|
|
|
+ String imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, num);
|
|
|
+ List<String> uploadFileList = FileUtil.loopFiles(targetImagesPath).stream().map(v->v.getAbsolutePath()).collect(Collectors.toList());
|
|
|
+ CreateObjUtil.build3dModel(target , "1");
|
|
|
+
|
|
|
+ String uploadJsonPath= target + File.separator + "results" +File.separator+"upload.json";
|
|
|
+ Thread.sleep(2000);
|
|
|
+ boolean exist = ComputerUtil.checkComputeCompleted(uploadJsonPath, 5, 1000);
|
|
|
+ if(!exist){
|
|
|
+ throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
|
|
|
+ }
|
|
|
+ String uploadData = FileUtils.readFile(uploadJsonPath);
|
|
|
+ JSONObject uploadJson = null;
|
|
|
+ JSONArray array = null;
|
|
|
+ if(uploadData!=null) {
|
|
|
+ uploadJson = JSONObject.parseObject(uploadData);
|
|
|
+ array = uploadJson.getJSONArray("upload");
|
|
|
+ }
|
|
|
+ if(array == null){
|
|
|
+ throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
|
|
|
+ }
|
|
|
+ Map<String, String> map = new HashMap<>();
|
|
|
+ JSONObject fileJson = null;
|
|
|
+ String fileName = "";
|
|
|
+ for(int i = 0, len = array.size(); i < len; i++) {
|
|
|
+ fileJson = array.getJSONObject(i);
|
|
|
+ fileName = fileJson.getString("file");
|
|
|
+ //文件不存在抛出异常
|
|
|
+ if (!new File(target + File.separator + "results" + File.separator + fileName)
|
|
|
+ .exists()) {
|
|
|
+ throw new Exception(
|
|
|
+ target + File.separator + "results" + File.separator + fileName + "文件不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ //high文件夹
|
|
|
+ if (fileJson.getIntValue("clazz") == 3) {
|
|
|
+ map.put(target + File.separator + "results" + File.separator + fileName,
|
|
|
+ imgViewPath + "pan/high/" + fileName.replace("high/", ""));
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //low文件夹
|
|
|
+ if (fileJson.getIntValue("clazz") == 4) {
|
|
|
+ map.put(target + File.separator + "results" + File.separator + fileName,
|
|
|
+ imgViewPath + "pan/low/" + fileName.replace("low/", ""));
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ //tiles文件夹,亚马逊没有裁剪图片api,不需要上传4k图
|
|
|
+ if (fileJson.getIntValue("clazz") == 5) {
|
|
|
+ map.put(target + File.separator + "results" + File.separator + fileName,
|
|
|
+ imgViewPath + fileName);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ //tiles文件夹,亚马逊瓦片图
|
|
|
+ if (fileJson.getIntValue("clazz") == 7) {
|
|
|
+ map.put(target + File.separator + "results" + File.separator + fileName,
|
|
|
+ imgViewPath + fileName);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //用户上传的全景图上传到ossresult目录
|
|
|
+ String ossCachesImagesPath = String.format(UploadFilePath.scene_result_data_path, num) + "caches/images/";
|
|
|
+ uploadFileList.stream().forEach(srcPath->{
|
|
|
+ map.put(srcPath, srcPath.replace(targetImagesPath, ossCachesImagesPath));
|
|
|
+ });
|
|
|
+
|
|
|
+ if(map.size()>0) {
|
|
|
+ fileServiceInterface.uploadMulFiles(map);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void genModel(String num, String zipParentDir) throws Exception {
|
|
|
+ String path = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "reverseScene_obj2txt";
|
|
|
+ String filePath = path + "/extras/";
|
|
|
+ //计算模型
|
|
|
+ FileUtil.copyContent(new File(zipParentDir + "/src_model/material/"), new File(filePath), true);
|
|
|
+ FileUtil.copyContent(new File(zipParentDir + "/src_model/mtl/"), new File(filePath), true);
|
|
|
+ FileUtil.copyContent(new File(zipParentDir + "/src_model/obj/"), new File(filePath), true);
|
|
|
+ this.writeDataJson(path);
|
|
|
+ CreateObjUtil.build3dModel(path , "1");
|
|
|
+ this.uploadFileofterBuildDamModel(path, filePath, num);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void writeDataJson(String path){
|
|
|
+ JSONObject dataJson = new JSONObject();
|
|
|
+ dataJson.put("obj2txt", true);
|
|
|
+ dataJson.put("split_type", "SPLIT_V6");
|
|
|
+ dataJson.put("data_describe", "double spherical");
|
|
|
+ dataJson.put("skybox_type", "SKYBOX_V5");
|
|
|
+ FileUtils.writeFile(path + "/data.json", dataJson.toString());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void uploadFileofterBuildDamModel(String path, String filePath, String sceneNum) throws Exception {
|
|
|
+ //因为共享目录有延迟,这里循环检测算法是否计算完毕3次,每次隔五秒
|
|
|
+ String uploadJsonPath = path + File.separator + "results" +File.separator+"upload.json";
|
|
|
+ boolean exist = ComputerUtil.checkComputeCompleted(uploadJsonPath, 5, 1000);
|
|
|
+ if(!exist){
|
|
|
+ throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
|
|
|
+ }
|
|
|
+ String uploadData = FileUtils.readFile(uploadJsonPath);
|
|
|
+ JSONObject uploadJson = null;
|
|
|
+ JSONArray array = null;
|
|
|
+ if(uploadData!=null) {
|
|
|
+ uploadJson = JSONObject.parseObject(uploadData);
|
|
|
+ array = uploadJson.getJSONArray("upload");
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String,String> map = new HashMap<String,String>();
|
|
|
+ JSONObject fileJson = null;
|
|
|
+ String fileName = "";
|
|
|
+ String imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, sceneNum);
|
|
|
+ for(int i = 0, len = array.size(); i < len; i++) {
|
|
|
+ fileJson = array.getJSONObject(i);
|
|
|
+ fileName = fileJson.getString("file");
|
|
|
+ //文件不存在抛出异常
|
|
|
+ if (!new File(path + File.separator + "results" + File.separator + fileName).exists()) {
|
|
|
+ throw new Exception(path + File.separator + "results" + File.separator + fileName + "文件不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ //tex文件夹
|
|
|
+ if (fileJson.getIntValue("clazz") == 15) {
|
|
|
+ map.put(path + File.separator + "results" + File.separator + fileName,
|
|
|
+ imgViewPath + ConstantFileName.modelUUID + "_50k_texture_jpg_high1/" + fileName.replace("tex/", ""));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ String damPath = path + File.separator + "results" +File.separator+ ConstantFileName.modelUUID+"_50k.dam";
|
|
|
+ CreateObjUtil.convertTxtToDam( path + File.separator + "results" +File.separator+"modeldata.txt", damPath);
|
|
|
+ boolean existDam = ComputerUtil.checkComputeCompleted(damPath, 5, 2);
|
|
|
+ if(!existDam){
|
|
|
+ throw new BusinessException(ErrorCode.FAILURE_CODE_7013);
|
|
|
+ }
|
|
|
+// CreateObjUtil.convertDamToLzma(path + File.separator + "results");
|
|
|
+// CreateObjUtil.convertTxtToDam( path + File.separator + "results" +File.separator+"modeldata.txt", path + File.separator + "results" + File.separator+ConstantFileName.modelUUID+"_50k.dam");
|
|
|
+// map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam.lzma", imgViewPath +ConstantFileName.modelUUID+"_50k.dam.lzma");
|
|
|
+ map.put(path + File.separator + "results" +File.separator+ConstantFileName.modelUUID+"_50k.dam", imgViewPath+ConstantFileName.modelUUID+"_50k.dam");
|
|
|
+
|
|
|
+ String ossMeshPath = String.format(UploadFilePath.DATA_VIEW_PATH, sceneNum) + "mesh";
|
|
|
+ //上传obj相关文件
|
|
|
+ List<String> fileNames = FileUtil.listFileNames(filePath);
|
|
|
+ fileNames.stream().forEach(name->map.put(filePath + name, ossMeshPath + File.separator + name));
|
|
|
+
|
|
|
+ fileServiceInterface.uploadMulFiles(map);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|