123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- package com.fdkankan.contro.mq.service.impl;
- import cn.hutool.core.collection.CollUtil;
- import cn.hutool.core.io.FileUtil;
- import cn.hutool.core.util.StrUtil;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
- import com.fdkankan.common.constant.*;
- import com.fdkankan.common.util.FileUtils;
- import com.fdkankan.contro.constant.UserEditDataType;
- import com.fdkankan.contro.entity.*;
- import com.fdkankan.contro.mq.service.IBuildSceneService;
- import com.fdkankan.contro.service.ICommonService;
- import com.fdkankan.contro.service.*;
- import com.fdkankan.contro.service.impl.FdkkV4Service;
- 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.CreateObjUtil;
- import com.fdkankan.rabbitmq.bean.BuildSceneCallMessage;
- import com.fdkankan.rabbitmq.bean.BuildSceneResultMqMessage;
- import com.fdkankan.rabbitmq.util.RabbitMqProducer;
- import com.fdkankan.redis.constant.RedisKey;
- import com.fdkankan.redis.util.RedisUtil;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.cloud.context.config.annotation.RefreshScope;
- import org.springframework.stereotype.Service;
- import org.springframework.util.ObjectUtils;
- import javax.annotation.Resource;
- import java.io.File;
- import java.math.BigDecimal;
- import java.util.*;
- /**
- * <p>
- * TODO
- * </p>
- *
- * @author dengsixing
- * @since 2022/3/1
- **/
- @Slf4j
- @Service
- @RefreshScope
- public class BuildObjServiceImpl implements IBuildSceneService {
- @Value("${queue.modeling.modeling-call}")
- private String queueModelingCall;
- @Value("${queue.modeling.obj.modeling-post}")
- private String queueObjModelingPost;
- @Value("${queue.modeling.obj.modeling-pre}")
- private String queueObjModelingPre;
- @Value("${model.modelKind:3dtiles}")
- private String modelKind;
- @Value("#{'${model.3dtiles.sceneSource:}'.split(',')}")
- private List<Integer> sdTilesSceneSourceList;
- @Value("${env:gn}")
- private String env;
- @Autowired
- private RabbitMqProducer mqProducer;
- @Resource
- private FYunFileServiceInterface fYunFileService;
- @Autowired
- private ISceneProService sceneProService;
- @Autowired
- private IFdkkLaserService fdkkLaserService;
- @Autowired
- private FdkkV4Service fdkkV4Service;
- @Autowired
- private IBuildSceneDTService buildSceneDTService;
- @Autowired
- private ISceneProEditService sceneProEditService;
- @Autowired
- private IScenePlusService scenePlusService;
- @Autowired
- private ISceneBuildProcessLogService sceneBuildProcessLogService;
- @Autowired
- private ICommonService commonService;
- @Autowired
- private IScenePlusExtService scenePlusExtService;
- @Autowired
- private RedisUtil redisUtil;
- @Autowired
- private ICameraDetailService cameraDetailService;
- @Autowired
- private ICompanyService companyService;
- @Autowired
- private IBuildService buildService;
- @Override
- public void buildScenePre(BuildSceneCallMessage message) throws Exception{
- boolean success = false;
- String num = message.getSceneNum();
- String path = message.getPath();
- String laserObjFilePath = path + "_laser_obj";
- try {
- //根据相机类型,组装资源路径
- log.info("开始准备生成OBJ场景资源,路径:{}", laserObjFilePath);
- FileUtils.delAllFile(laserObjFilePath);
- //获取解压后的资源的data.fdage中的数据
- fYunFileService.downloadFile(ConstantFilePath.OSS_PREFIX + path.replace(ConstantFilePath.BUILD_MODEL_LASER_PATH, "") + "/data.fdage", laserObjFilePath + "/capture/data.fdage");
- JSONObject jsonObject = FileUtils.readJson(laserObjFilePath + File.separator + "capture" + File.separator + "data.fdage");
- if(ObjectUtils.isEmpty(jsonObject)){
- log.error("data.fdage文件不存在");
- return ;
- }
- //下载资源到本地
- this.downLoadSource(message, laserObjFilePath);
- if (!jsonObject.containsKey("exportMeshObj") || jsonObject.getIntValue("exportMeshObj") != 1) {
- // 写入data.fdage 防止重算
- jsonObject.put("exportMeshObj", 1);
- FileUtil.writeUtf8String(jsonObject.toJSONString(), laserObjFilePath + File.separator + "capture" + File.separator + "data.fdage");
- fYunFileService.uploadFile(laserObjFilePath + File.separator + "capture" + File.separator + "data.fdage",
- ConstantFilePath.OSS_PREFIX + path.replace(ConstantFilePath.BUILD_MODEL_LASER_PATH, "") + "/data.fdage");
- }
- // 重新构造datafdage文件,添加生成obt文件选项
- jsonObject.put("OnlyExportMeshObj",true);
- FileUtils.writeFile(laserObjFilePath + File.separator + "capture" + File.separator + "data.fdage", jsonObject.toJSONString());
- message.getBuildContext().put("previousPath",path);
- message.setCameraType("14");
- message.setResolution(jsonObject.getString("resolution"));
- message.setPath(laserObjFilePath);
- message.setResultReceiverMqName(queueObjModelingPost);
- message.setBizType("obj");
- JSONObject fdageData = commonService.getFdageData(laserObjFilePath + File.separator + "capture" + File.separator + "data.fdage");
- Map<String, Object> dataExtras = new HashMap<>(1);
- dataExtras.put("big_depthmap", true);
- buildService.writeDataJson(message, fdageData, null, dataExtras);
- success = true;
- log.info("场景计算资源准备结束,场景码:{}", message.getSceneNum());
- }catch (Exception e){
- log.error("生成OBJ场景资源准备异常,num=" + num, e);
- buildSceneDTService.handBaseFail("生成OBJ场景资源准备异常", message.getPath(), message.getSceneNum(), "计算控制服务器");
- throw e;
- }finally {
- fdkkLaserService.pushBuildStatusToLaserSystem(num, laserObjFilePath + "/laserData/mesh", success ? CommonOperStatus.SUCCESS.code() : CommonOperStatus.FAILD.code());
- }
- }
- @Override
- public void downLoadSource(BuildSceneCallMessage message,String path) throws Exception{
- //下载原始资源文件
- String ossPath = commonService.getOssOrignPath(message.getPath());
- fYunFileService.downloadFileByCommand(path + File.separator + "capture", ossPath);
- //下载caches/image,算法会执行快一些
- String ossResultPath = String.format(UploadFilePath.scene_result_data_path, message.getSceneNum());
- fYunFileService.downloadFileByCommand(path + "/caches/images/", ossResultPath + "caches/images/");
- //下载点位校准文件,刘强版本大改,要求只有包含字段vision_edit_version且vision_edit_version的值是1.0时,才下载vision_edit.txt文件进行计算,其他情况不保留
- //2025-04-01,刘强再次要求,vision_edit_version >= 1.0 可以下载vision_edit.txt进行计算
- if(fYunFileService.fileExist(ossResultPath + "extras/" + "vision_edit.txt")){
- String fileContent = fYunFileService.getFileContent(ossResultPath + "extras/" + "vision_edit.txt");
- JSONObject jsonObject = JSON.parseObject(fileContent);
- if(jsonObject.containsKey("vision_edit_version")){
- BigDecimal visionEditVersion = jsonObject.getBigDecimal("vision_edit_version");
- if(visionEditVersion.compareTo(new BigDecimal("1.0")) != -1){
- fYunFileService.downloadFile(ossResultPath + "extras/vision_edit.txt", path + "/extras/vision_edit.txt");
- }
- }
- }
- }
- public static void main(String[] args) {
- JSONObject o = new JSONObject();
- o.put("vision_edit_version", "1.1");
- System.out.println(o.getBigDecimal("vision_edit_version"));
- }
- @Override
- public void buildScenePost(BuildSceneResultMqMessage message) throws Exception {
- String path = message.getPath();
- String projectNum = message.getBuildContext().get("sceneNum").toString();
- String laserObjFilePath = path;
- boolean success = false;
- try {
- //上传计算日志
- String buildLogPath = String.format(UploadFilePath.BUILD_LOG_PATH, projectNum);
- fYunFileService.uploadFile(path + File.separator + "console.log", buildLogPath + "console.log");
- if (!message.getBuildSuccess()) {
- log.error("生成OBJ场景计算失败!");
- scenePlusService.update(new LambdaUpdateWrapper<ScenePlus>()
- .set(ScenePlus::getSceneStatus, SceneStatus.FAILD.code())
- .eq(ScenePlus::getNum, projectNum));
- // 发送钉钉消息,计算失败
- buildSceneDTService.handModelFail("生成OBJ场景计算失败!", message.getPath(), message.getBuildContext().get("sceneNum").toString(), message.getHostName());
- return;
- }
- ScenePro scenePro = sceneProService.getByNum(projectNum);
- String version = "v4";
- String ossImagePath = String.format(UploadFilePath.IMG_VIEW_PATH, projectNum);
- //如果是微服务上线之前的存量场景且未生成过obj(未升级过),需要上传到v3的目录,在函数最后调用升级接口进行文件拷贝
- if(Objects.nonNull(scenePro) && scenePro.getIsUpgrade() != CommonStatus.YES.code().intValue()){
- ossImagePath = String.format(ConstantFilePath.IMAGE_PATH_FORMAT, projectNum);
- version = "v3";
- }
- //上传obj
- String resultsPath = path + File.separator + "results" + File.separator;
- if(this.modelKind.equals(ModelKind.DAM.code())){
- CreateObjUtil.convertTxtToDam(path + File.separator + "results" + File.separator + "tex" + File.separator + "modeldata.txt", path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam");
- CreateObjUtil.convertDamToLzma(path + File.separator + "results/");
- CreateObjUtil.convertTxtToDam(path + File.separator + "results" + File.separator + "tex" + File.separator + "modeldata.txt", path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam");
- File file = new File(path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam.lzma");
- while (!file.exists()) {
- Thread.sleep(60000);
- }
- fYunFileService.uploadFile(path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam.lzma", ossImagePath + ConstantFileName.modelUUID + "_50k.dam.lzma");
- fYunFileService.uploadFile(path + File.separator + "results" + File.separator + ConstantFileName.modelUUID + "_50k.dam", ossImagePath + ConstantFileName.modelUUID + "_50k.dam");
- }
- if(this.modelKind.equals(ModelKind.THREE_D_TILE.code())
- && CollUtil.isNotEmpty(sdTilesSceneSourceList)
- && sdTilesSceneSourceList.contains(SceneSource.JG.code())){
- String threedtilesPath = resultsPath + ModelKind.THREE_D_TILE.code();
- String oss3dtilesPath = ossImagePath + ModelKind.THREE_D_TILE.code();
- List<String> list = FileUtils.list(new File(threedtilesPath));
- if(CollUtil.isEmpty(list)){
- log.error("3dtiles目录异常,3dtiles地址:{}", new File(path + File.separator + "results" + File.separator + ModelKind.THREE_D_TILE.code()));
- throw new Exception("3dtiles目录异常");
- }
- //先删除
- fYunFileService.deleteFolder(oss3dtilesPath);
- //上传3dtiles文件
- fYunFileService.uploadFileByCommand(threedtilesPath, oss3dtilesPath);
- }
- String texPath = laserObjFilePath + File.separator + "results" + File.separator + "tex";
- File texFile = new File(texPath);
- if(texFile.exists()){
- for (File textureFile : texFile.listFiles()) {
- if(textureFile.getName().endsWith(".jpg")){
- fYunFileService.uploadFile(textureFile.getAbsolutePath(),
- ossImagePath + ConstantFileName.modelUUID + "_50k_texture_jpg_high1/"+textureFile.getName());
- }
- }
- }
- fYunFileService.uploadFile(laserObjFilePath + File.separator + "results" + File.separator + "tex/texture1.jpg",
- ossImagePath + ConstantFileName.modelUUID + "_50k_texture_jpg_high1/texture1.jpg");
- // 拷贝结果
- log.info("开始拷贝obj文件");
- FileUtils.copyFolderAllFiles(laserObjFilePath + "/results/mesh", laserObjFilePath + "/laserData/mesh/", true);
- //先删除
- fYunFileService.deleteFolder(String.format(UploadFilePath.DATA_VIEW_PATH, projectNum) + "mesh");
- //上传mesh文件
- fYunFileService.uploadFileByCommand(laserObjFilePath + "/results/mesh", String.format(UploadFilePath.DATA_VIEW_PATH, projectNum) + "mesh");
- CreateObjUtil.convertTxtToVisionmodeldata(resultsPath + "vision.txt", resultsPath + "vision.modeldata");
- fYunFileService.uploadFile(resultsPath + "vision.txt", ossImagePath.concat("vision.txt"));
- fYunFileService.uploadFile(resultsPath + "vision.modeldata", ossImagePath.concat("vision.modeldata"));
- if(!ObjectUtils.isEmpty(scenePro)){
- LambdaUpdateWrapper<ScenePro> updateWrapper = new LambdaUpdateWrapper<ScenePro>()
- .set(ScenePro::getStatus, -2).eq(ScenePro::getNum, projectNum);
- sceneProService.update(updateWrapper);
- sceneProEditService.update(new LambdaUpdateWrapper<SceneProEdit>().set(SceneProEdit::getMapVisi,0)
- .eq(SceneProEdit::getProId,scenePro.getId()));
- }
- ScenePlus scenePlus = scenePlusService.getScenePlusByNum(projectNum);
- if(Objects.nonNull(scenePlus)){
- // //清除用户编辑业务数据
- // Set<String> bizs = new HashSet<>();
- // bizs.add(UserEditDataType.BOX_MODEL.message());
- // bizs.add(UserEditDataType.FLOORPLAN.message());
- // commonService.initUserEditData(projectNum, bizs, null);
- LambdaUpdateWrapper<ScenePlus> plusUpdateWrapper = new LambdaUpdateWrapper<ScenePlus>()
- .set(ScenePlus::getSceneStatus, -2).eq(ScenePlus::getNum, projectNum);
- scenePlusService.update(plusUpdateWrapper);
- ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
- scenePlusExt.setAlgorithmTime(Calendar.getInstance().getTime());
- //计算容量
- Long space = commonService.getSpace(projectNum);
- scenePlusExt.setSpace(space);
- scenePlusExt.setMeshComputeTime(message.getComputeTime());
- Object[] editInfoArr = commonService.updateEditInfo(scenePlus);
- SceneEditInfo sceneEditInfo = (SceneEditInfo)editInfoArr[0];
- SceneEditInfoExt sceneEditInfoExt = (SceneEditInfoExt)editInfoArr[1];
- SceneEditControls sceneEditControls = (SceneEditControls)editInfoArr[2];
- if(this.modelKind.equals(ModelKind.THREE_D_TILE.code())
- && CollUtil.isNotEmpty(sdTilesSceneSourceList)
- && sdTilesSceneSourceList.contains(scenePlus.getSceneSource())){
- scenePlusExt.setModelKind(ModelKind.THREE_D_TILE.code());
- scenePlusExtService.updateById(scenePlusExt);
- }
- log.info("生成scene.json上传oss并设置缓存,num:{}", projectNum);
- CameraDetail cameraDetail = cameraDetailService.getByCameraId(scenePlus.getCameraId());
- Company company = !org.apache.commons.lang3.ObjectUtils.isEmpty(cameraDetail.getCompanyId()) ? companyService.getById(cameraDetail.getCompanyId()) : null;
- //写scene.json
- log.info("---------------------videos:{}", scenePlusExt.getVideos());
- commonService.writeSceneJson(projectNum,sceneEditInfo, sceneEditInfoExt, sceneEditControls, scenePlus,scenePlusExt,company);
- }
- //重置异步操作记录
- commonService.removeSceneAsynOperLog(projectNum);
- // 如果未升级V4,则升级V4
- if("v3".equals(version)){
- fdkkV4Service.upgradeToV4(projectNum);
- }
- success = true;
- //国际环境需要发邮件通知
- if("eur".equals(env)){
- commonService.sendEmail(projectNum, "obj");
- }
- }catch (Exception e){
- log.error("生成OBJ场景计算结果处理异常,num=" + projectNum, e);
- buildSceneDTService.handBaseFail("生成OBJ场景计算结果处理异常", message.getPath(), projectNum, "计算控制服务器");
- throw e;
- }finally {
- fdkkLaserService.pushBuildStatusToLaserSystem(projectNum, laserObjFilePath + "/laserData/mesh", success ? CommonOperStatus.SUCCESS.code() : CommonOperStatus.FAILD.code());
- }
- }
- }
|