|
@@ -0,0 +1,370 @@
|
|
|
+package com.fdkankan.contro.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.io.FileUtil;
|
|
|
+import cn.hutool.core.util.ArrayUtil;
|
|
|
+import cn.hutool.core.util.ObjUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.fdkankan.common.constant.CommonStatus;
|
|
|
+import com.fdkankan.contro.bean.TagBean;
|
|
|
+import com.fdkankan.contro.entity.ScenePlus;
|
|
|
+import com.fdkankan.contro.entity.ScenePlusExt;
|
|
|
+import com.fdkankan.contro.service.ILinkPanService;
|
|
|
+import com.fdkankan.contro.service.IScenePlusExtService;
|
|
|
+import com.fdkankan.contro.service.IScenePlusService;
|
|
|
+import com.fdkankan.fyun.face.FYunFileServiceInterface;
|
|
|
+import com.fdkankan.model.constants.ConstantFilePath;
|
|
|
+import com.fdkankan.model.constants.UploadFilePath;
|
|
|
+import com.fdkankan.redis.constant.RedisKey;
|
|
|
+import com.fdkankan.redis.util.RedisUtil;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.io.File;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class LinkPanServiceImpl implements ILinkPanService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IScenePlusService scenePlusService;
|
|
|
+ @Autowired
|
|
|
+ private IScenePlusExtService scenePlusExtService;
|
|
|
+ @Resource
|
|
|
+ private RedisUtil redisUtil;
|
|
|
+ @Resource
|
|
|
+ private FYunFileServiceInterface fYunFileService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Integer genLinkPanPost(String num) throws Exception {
|
|
|
+ log.info("开始计算场景关联,num:{}", num);
|
|
|
+ ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
|
|
|
+ ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
|
|
|
+ String dataSource = scenePlusExt.getDataSource();
|
|
|
+ String baseCapturePath = dataSource + File.separator + "capture" + File.separator;
|
|
|
+ String dataFdagePath = baseCapturePath + "data.fdage";
|
|
|
+ String dataFdageStr = FileUtil.readUtf8String(dataFdagePath);
|
|
|
+ JSONObject dataFdageObj = JSON.parseObject(dataFdageStr);
|
|
|
+ Integer links = 0;
|
|
|
+ if ( dataFdageObj.containsKey("points")){
|
|
|
+ JSONArray points = dataFdageObj.getJSONArray("points");
|
|
|
+ log.info("points:{}", JSON.toJSONString(points));
|
|
|
+ if(ObjUtil.isNotNull(points)){
|
|
|
+ for (Object point : points) {
|
|
|
+ JSONObject pointObj = (JSONObject) point;
|
|
|
+ Integer panoId = pointObj.getInteger("index");
|
|
|
+ List<String> panos = (List<String>)pointObj.get("panos");
|
|
|
+ log.info("panos:{}", JSON.toJSONString(panos));
|
|
|
+ if(panos==null || ArrayUtil.isEmpty(panos)){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ for (String pano : panos) {
|
|
|
+
|
|
|
+ String sid = FileUtil.getPrefix(pano);
|
|
|
+
|
|
|
+ String localImagesPath = dataSource + File.separator + "linkPan" + File.separator;
|
|
|
+ String target = localImagesPath + "panorama" + File.separator + sid;
|
|
|
+ String filePath = target + File.separator + "extras" + File.separator + "images" + File.separator + pano;
|
|
|
+ String resultPath = target + File.separator + "results";
|
|
|
+ JSONArray array = this.getUploadArray(resultPath + "/upload.json");
|
|
|
+ JSONObject fileJson;
|
|
|
+ String uploadFile, uploadFilePath;
|
|
|
+ String imgEditPath = String.format(UploadFilePath.IMG_EDIT_PATH, num);
|
|
|
+ String imgViewPath = String.format(UploadFilePath.IMG_VIEW_PATH, num);
|
|
|
+ for(int i = 0, len = array.size(); i < len; i++){
|
|
|
+ fileJson = array.getJSONObject(i);
|
|
|
+ uploadFile = fileJson.getString("file");
|
|
|
+ uploadFilePath = resultPath +File.separator + uploadFile;
|
|
|
+ //文件不存在抛出异常
|
|
|
+
|
|
|
+ if(!cn.hutool.core.io.FileUtil.exist(uploadFilePath)){
|
|
|
+ throw new Exception(uploadFilePath + "文件不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ Integer clazz = fileJson.getIntValue("clazz");
|
|
|
+ if(Objects.isNull(clazz)){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if(clazz == 4 || clazz == 5 || clazz == 7){
|
|
|
+ fYunFileService.uploadFile(uploadFilePath, imgEditPath + "panorama/" + sid + File.separator + uploadFile);
|
|
|
+ fYunFileService.uploadFile(uploadFilePath, imgViewPath + "panorama/" + sid + File.separator + uploadFile);
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ fYunFileService.uploadFile(filePath, imgEditPath + "panorama/" + sid + "/high/" + pano);
|
|
|
+ fYunFileService.uploadFile(filePath, imgViewPath + "panorama/" + sid + "/high/" + pano);
|
|
|
+
|
|
|
+ this.addOrUpdateLinPan(num, pano, panoId, sid);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("开始links.json文件");
|
|
|
+ links = this.publicLinkSceneData(num);
|
|
|
+ log.info("结束生成links.json文件");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ log.info("结束计算场景关联,num:{}", num);
|
|
|
+
|
|
|
+ return links;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<String> genLinkPanPre(String num) throws Exception {
|
|
|
+
|
|
|
+ List<String> panoTargetList = new ArrayList<>();
|
|
|
+
|
|
|
+ ScenePlus scenePlus = scenePlusService.getScenePlusByNum(num);
|
|
|
+ ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
|
|
|
+ String dataSource = scenePlusExt.getDataSource();
|
|
|
+ String baseCapturePath = dataSource + File.separator + "capture" + File.separator;
|
|
|
+ String dataFdagePath = baseCapturePath + "data.fdage";
|
|
|
+ String dataFdageStr = FileUtil.readUtf8String(dataFdagePath);
|
|
|
+ JSONObject dataFdageObj = JSON.parseObject(dataFdageStr);
|
|
|
+ if ( dataFdageObj.containsKey("points")){
|
|
|
+ JSONArray points = dataFdageObj.getJSONArray("points");
|
|
|
+ log.info("points:{}", JSON.toJSONString(points));
|
|
|
+ if(ObjUtil.isNotNull(points)){
|
|
|
+ for (Object point : points) {
|
|
|
+ JSONObject pointObj = (JSONObject) point;
|
|
|
+ List<String> panos = (List<String>)pointObj.get("panos");
|
|
|
+ log.info("panos:{}", JSON.toJSONString(panos));
|
|
|
+ if(panos==null || ArrayUtil.isEmpty(panos)){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ for (String pano : panos) {
|
|
|
+
|
|
|
+ String sid = FileUtil.getPrefix(pano);
|
|
|
+
|
|
|
+ String localImagesPath = dataSource + File.separator + "linkPan" + File.separator;
|
|
|
+ String target = localImagesPath + "panorama" + File.separator + sid;
|
|
|
+ FileUtil.del(target);
|
|
|
+
|
|
|
+ //文件写如本地磁盘
|
|
|
+ String filePath = target + File.separator + "extras" + File.separator + "images" + File.separator + pano;
|
|
|
+ File targetFile = new File(filePath);
|
|
|
+ if(!targetFile.getParentFile().exists()){
|
|
|
+ targetFile.getParentFile().mkdirs();
|
|
|
+ }
|
|
|
+ FileUtil.copy(baseCapturePath + pano, filePath, true);
|
|
|
+
|
|
|
+ //生成vision.txt
|
|
|
+ this.writeVisionTxt(sid, target);
|
|
|
+
|
|
|
+ //data.json增加extras为执行重建算法
|
|
|
+ this.writeDataJson(scenePlusExt.getSceneScheme(), scenePlusExt.getSceneResolution(), target);
|
|
|
+
|
|
|
+ //创建文件夹软连接并且复制data.json和project.json
|
|
|
+ String capturePath = target + File.separator + "capture";
|
|
|
+ String resultPath = target + File.separator + "results";
|
|
|
+ log.info("场景关联上传全景图:capturePath={}", capturePath);
|
|
|
+ log.info("场景关联上传全景图:resultPath={}", resultPath);
|
|
|
+ if(cn.hutool.core.io.FileUtil.exist(capturePath)){
|
|
|
+ cn.hutool.core.io.FileUtil.del(capturePath);
|
|
|
+ }
|
|
|
+ if(cn.hutool.core.io.FileUtil.exist(resultPath)){
|
|
|
+ cn.hutool.core.io.FileUtil.del(resultPath);
|
|
|
+ }
|
|
|
+ //下载data.fdage
|
|
|
+ FileUtil.copy(dataFdagePath, capturePath + File.separator + "/data.fdage", true);
|
|
|
+
|
|
|
+ panoTargetList.add(target);
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return panoTargetList;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Integer publicLinkSceneData(String num){
|
|
|
+
|
|
|
+ String userEditPath = String.format(UploadFilePath.USER_EDIT_PATH, num);
|
|
|
+ String userViewPath = String.format(UploadFilePath.USER_VIEW_PATH, num);
|
|
|
+
|
|
|
+ //生成links.json并上传到发布目录
|
|
|
+ String linkPanKey = String.format(RedisKey.SCENE_LINKPAN_DATA, num);
|
|
|
+ Map<String, String> linkPanMap = redisUtil.hmget(linkPanKey);
|
|
|
+ if(CollUtil.isEmpty(linkPanMap)){
|
|
|
+ return CommonStatus.NO.code().intValue();
|
|
|
+ }
|
|
|
+ List<JSONObject> tags = Lists.newArrayList();
|
|
|
+ List<TagBean> tagBeanList = new ArrayList<>();
|
|
|
+ if(CollUtil.isNotEmpty(linkPanMap)){
|
|
|
+ linkPanMap.entrySet().stream().forEach(entry -> {
|
|
|
+ JSONObject jsonObject = JSON.parseObject(entry.getValue());
|
|
|
+ tagBeanList.add(
|
|
|
+ TagBean.builder()
|
|
|
+ .createTime(jsonObject.getLong("createTime"))
|
|
|
+ .tag(jsonObject).build());
|
|
|
+ });
|
|
|
+ //按创建时间倒叙排序
|
|
|
+ tagBeanList.sort(Comparator.comparingLong(TagBean::getCreateTime).reversed());
|
|
|
+
|
|
|
+ //移除createTime字段
|
|
|
+ tags = tagBeanList.stream().map(tagBean -> {
|
|
|
+ JSONObject tag = tagBean.getTag();
|
|
|
+ tag.remove("createTime");
|
|
|
+ return tag;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+ String linkScenePath = userEditPath + "links.json";
|
|
|
+ String linkSceneViewPath = userViewPath + "links.json";
|
|
|
+ fYunFileService.uploadFile(tags.toString().getBytes(StandardCharsets.UTF_8), linkScenePath);
|
|
|
+ fYunFileService.uploadFile(tags.toString().getBytes(StandardCharsets.UTF_8), linkSceneViewPath);
|
|
|
+
|
|
|
+ return CommonStatus.YES.code().intValue();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addOrUpdateLinPan(String num, String pano, Integer panoId, String sid) throws Exception{
|
|
|
+
|
|
|
+ log.info("开始设置linksjson缓存");
|
|
|
+
|
|
|
+ List<JSONObject> linkPanList = new ArrayList<>();
|
|
|
+ JSONObject linkObj = new JSONObject();
|
|
|
+ linkPanList.add(linkObj);
|
|
|
+ JSONObject styleObj = new JSONObject();
|
|
|
+ linkObj.put("style", styleObj);
|
|
|
+ Map<String, String> enter = new HashMap<>();
|
|
|
+ styleObj.put("enter", enter);
|
|
|
+ enter.put("name", "default");
|
|
|
+ enter.put("url", "");
|
|
|
+ Map<String, String> exit = new HashMap<>();
|
|
|
+ styleObj.put("exit", exit);
|
|
|
+ exit.put("name", "out");
|
|
|
+ exit.put("url", "");
|
|
|
+ linkObj.put("resolution", "2k");
|
|
|
+ linkObj.put("thumb", pano);
|
|
|
+ linkObj.put("title", FileUtil.getPrefix(pano));
|
|
|
+ linkObj.put("type", "pano");
|
|
|
+ linkObj.put("panoId", panoId);
|
|
|
+ linkObj.put("sid", sid);
|
|
|
+
|
|
|
+ Map<String, String> addOrUpdateMap = new HashMap<>();
|
|
|
+ int i = 0;
|
|
|
+ for (JSONObject jsonObject : linkPanList) {
|
|
|
+ jsonObject.put("createTime", Calendar.getInstance().getTimeInMillis() + i++);
|
|
|
+ addOrUpdateMap.put(jsonObject.getString("sid"), jsonObject.toJSONString());
|
|
|
+ }
|
|
|
+
|
|
|
+ //处理新增和修改数据
|
|
|
+ log.info("开始redis缓存inksjson");
|
|
|
+ this.addOrUpdateLinkPanHandler(num, addOrUpdateMap);
|
|
|
+ log.info("结束redis缓存inksjson");
|
|
|
+
|
|
|
+ //场景关联数据备份到本地
|
|
|
+ log.info("开始本地备份inksjson缓存");
|
|
|
+ this.writeLinkScene(num);
|
|
|
+ log.info("结束本地备份inksjson缓存");
|
|
|
+
|
|
|
+ log.info("结束设置linksjson缓存");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addOrUpdateLinkPanHandler(String num, Map<String, String> addOrUpdateMap){
|
|
|
+ if(CollUtil.isEmpty(addOrUpdateMap))
|
|
|
+ return;
|
|
|
+
|
|
|
+ //批量写入缓存
|
|
|
+ String key = String.format("scene:LinkPan:num:%s", num);
|
|
|
+ log.info("linkjson key : {}", key);
|
|
|
+ log.info("linkjson value : {}", JSON.toJSONString(addOrUpdateMap));
|
|
|
+ redisUtil.hmset(key, addOrUpdateMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void writeLinkScene(String num) throws Exception{
|
|
|
+
|
|
|
+ String dataKey = String.format(RedisKey.SCENE_LINKPAN_DATA, num);
|
|
|
+ Map<String, String> tagMap = redisUtil.hmget(dataKey);
|
|
|
+ List<String> tagList = Lists.newArrayList();
|
|
|
+ tagMap.entrySet().stream().forEach(entry->{
|
|
|
+ if(StrUtil.isNotEmpty(entry.getValue())){
|
|
|
+ tagList.add(entry.getValue());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ JSONArray tagJsonArr = new JSONArray();
|
|
|
+ if(CollUtil.isNotEmpty(tagList)){
|
|
|
+ tagList.stream().forEach(linkPan->{
|
|
|
+ tagJsonArr.add(JSONObject.parseObject(linkPan));
|
|
|
+ });
|
|
|
+ }
|
|
|
+ jsonObject.put("tags", tagJsonArr);
|
|
|
+
|
|
|
+ String stylesKey = String.format(RedisKey.SCENE_LINKPAN_STYLES, num);
|
|
|
+ Map<String, String> styleMap = redisUtil.hmget(stylesKey);
|
|
|
+ List<JSONObject> styleList = Lists.newArrayList();
|
|
|
+ if(CollUtil.isNotEmpty(styleMap)){
|
|
|
+ styleMap.values().stream().forEach(style->{
|
|
|
+ styleList.add(JSONObject.parseObject(style));
|
|
|
+ });
|
|
|
+ }
|
|
|
+ jsonObject.put("styles", styleList);
|
|
|
+
|
|
|
+ String linkScenePath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + "links.json";
|
|
|
+ FileUtil.writeUtf8String(jsonObject.toJSONString(), linkScenePath);
|
|
|
+ }
|
|
|
+
|
|
|
+ private JSONArray getUploadArray(String uploadJsonPath){
|
|
|
+ if(!FileUtil.exist(uploadJsonPath)){
|
|
|
+ throw new RuntimeException("build link pan fail, upload.json is not exist");
|
|
|
+ }
|
|
|
+ String uploadData = FileUtil.readUtf8String(uploadJsonPath);
|
|
|
+ JSONArray array = null;
|
|
|
+ if (StrUtil.isNotEmpty(uploadData)) {
|
|
|
+ JSONObject uploadJson = JSONObject.parseObject(uploadData);
|
|
|
+ array = uploadJson.getJSONArray("upload");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CollUtil.isEmpty(array)) {
|
|
|
+ throw new RuntimeException("build link pan fail, array is empty");
|
|
|
+ } else {
|
|
|
+ return array;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void writeVisionTxt(String sid, String target){
|
|
|
+ JSONObject visionJson = new JSONObject();
|
|
|
+ JSONArray visionArray = new JSONArray();
|
|
|
+ visionJson.put("uuid", sid);
|
|
|
+ visionJson.put("group", 1);
|
|
|
+ visionJson.put("subgroup", 0);
|
|
|
+ visionArray.add(visionJson);
|
|
|
+ JSONObject vision = new JSONObject();
|
|
|
+ vision.put("sweepLocations", visionArray);
|
|
|
+ cn.hutool.core.io.FileUtil.writeString(vision.toString(), target + "/extras" + File.separator + "vision.txt", StandardCharsets.UTF_8);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void writeDataJson(Integer sceneScheme, String sceneResolution, String target){
|
|
|
+ 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");//替换全景图算法
|
|
|
+
|
|
|
+ String skyboxType = "SKYBOX_V7";//默认2k minion
|
|
|
+ if("4k".equals(sceneResolution)){
|
|
|
+ skyboxType = "SKYBOX_V6";
|
|
|
+ }
|
|
|
+ if(sceneScheme == 3){
|
|
|
+ skyboxType = "SKYBOX_V13";
|
|
|
+ if("4k".equals(sceneResolution)){
|
|
|
+ skyboxType = "SKYBOX_V14";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dataJson.put("skybox_type", skyboxType);
|
|
|
+ cn.hutool.core.io.FileUtil.writeString(dataJson.toString(), target + File.separator+"data.json", StandardCharsets.UTF_8);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+}
|