|
@@ -0,0 +1,253 @@
|
|
|
+package com.fdkankan.indoor.core.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.io.FileUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.fdkankan.indoor.base.constant.TypeConstant;
|
|
|
+import com.fdkankan.indoor.base.convert.ModifyCloud;
|
|
|
+import com.fdkankan.indoor.base.util.Result;
|
|
|
+import com.fdkankan.indoor.base.util.SnowFlakeUUidUtils;
|
|
|
+import com.fdkankan.indoor.core.entity.ControlPointEntity;
|
|
|
+import com.fdkankan.indoor.core.entity.SiteModelEntity;
|
|
|
+import com.fdkankan.indoor.core.entity.SpecialPointEntity;
|
|
|
+import com.fdkankan.indoor.core.entity.dto.SiteDto;
|
|
|
+import com.fdkankan.indoor.core.entity.dto.SitePolygon;
|
|
|
+import com.fdkankan.indoor.core.service.CloudService;
|
|
|
+import com.fdkankan.indoor.core.service.SiteService;
|
|
|
+import com.fdkankan.indoor.core.service.SpecialPointService;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import net.sf.json.JSONArray;
|
|
|
+import net.sf.json.JSONObject;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.UUID;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Created by owen on 2021/8/24 0024 18:26
|
|
|
+ */
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class CloudServiceImpl extends IBaseServiceImpl implements CloudService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ SpecialPointService specialPointService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ SiteService siteService;
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Result upload(String sceneCode, MultipartFile file) {
|
|
|
+
|
|
|
+ // step1: 长传点云到nas目录
|
|
|
+ if (file == null) {
|
|
|
+ throw new RuntimeException("文件为空");
|
|
|
+ }
|
|
|
+ String originalFilename = file.getOriginalFilename();
|
|
|
+ String suffix = StrUtil.subAfter(originalFilename, ".", true);
|
|
|
+
|
|
|
+// String newName = DateUtil.format(LocalDateTime.now(), "yyyyMMdd_HHmmssSSS");
|
|
|
+ UUID uuid = UUID.randomUUID();
|
|
|
+ String newName = "poi-" + uuid + "." + suffix;
|
|
|
+
|
|
|
+ String urlPath = "/" + sceneCode + "/poi/image/" + newName;
|
|
|
+ String savePath = configConstant.serverBasePath + urlPath;
|
|
|
+ log.info("保存图片路径:{}", savePath);
|
|
|
+ try {
|
|
|
+ FileUtil.writeFromStream(file.getInputStream(), savePath);
|
|
|
+
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ // step2: 调用算法,生成网络点云数据。目录是根目录/chunk1 数字递增
|
|
|
+
|
|
|
+ // step3: 上传网络点云到oss
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ return Result.success();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理上传的点云数据:siteModel -> 原点、中心点、最大点、最小点
|
|
|
+ * @param sceneCode 场景码
|
|
|
+ * @param laserDataPath 基础路径
|
|
|
+ * @param controlPoint 控制点
|
|
|
+ */
|
|
|
+ private void processCoule(String sceneCode, String laserDataPath, ControlPointEntity controlPoint){
|
|
|
+ String path = laserDataPath + "/webcloud/cloud.js";
|
|
|
+ // 处理原点,将原点坐标转为坐标, 转换后的原点只有经纬度,没有高度, 高度现在默认是0
|
|
|
+ double[] doubles = ModifyCloud.convertFromOrigin(controlPoint);
|
|
|
+ // 2021-08-4 原点默认 z:0
|
|
|
+ Double[] gpsOrigin = {doubles[0] ,doubles[1], 0.0};
|
|
|
+ // 将数据保存到db, dateSet数据location使用
|
|
|
+ saveSpecialPoint(sceneCode, TypeConstant.POI_ORIGIN, null, gpsOrigin);
|
|
|
+ log.info("原点保存成功");
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 修改cloud.js文件
|
|
|
+ JSONObject info = ModifyCloud.fixCloud(path);
|
|
|
+
|
|
|
+ cn.hutool.core.io.FileUtil.writeUtf8String(info.toString(), path);
|
|
|
+ log.info("新的cloud.js写入服务器完成:{}", path);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将boundingBox坐标转换成gis坐标, site_model需要
|
|
|
+ * boundingBox:虚拟点坐标,存特殊点, dataSet数据要使用
|
|
|
+ */
|
|
|
+ JSONObject boundingBox = ModifyCloud.getBoundingBox(info);
|
|
|
+ Double maxX = boundingBox.getDouble("maxX");
|
|
|
+ Double maxY = boundingBox.getDouble("maxY");
|
|
|
+ Double maxZ = boundingBox.getDouble("maxZ");
|
|
|
+
|
|
|
+ Double minX = boundingBox.getDouble("minX");
|
|
|
+ Double minY = boundingBox.getDouble("minY");
|
|
|
+ Double minZ = boundingBox.getDouble("minZ");
|
|
|
+
|
|
|
+ Double centreX = boundingBox.getDouble("centreX");
|
|
|
+ Double centreY = boundingBox.getDouble("centreY");
|
|
|
+ Double centreZ = boundingBox.getDouble("centreZ");
|
|
|
+
|
|
|
+
|
|
|
+ // 虚拟点坐标(四维看看坐标)
|
|
|
+ Double[] ageMax = {maxX,maxY,maxZ};
|
|
|
+ Double[] ageMin = {minX,minY,minZ};
|
|
|
+ Double[] ageCentre = {centreX,centreY,centreZ};
|
|
|
+
|
|
|
+ JSONObject resJson = ModifyCloud.convertFromBoundingBox(boundingBox, controlPoint);
|
|
|
+
|
|
|
+ Double[] gpsMax = getKey(resJson, "max");
|
|
|
+ Double[] gpsMin = getKey(resJson, "min");
|
|
|
+ Double[] gpsCentre = getKeyZ(resJson, "centre");
|
|
|
+
|
|
|
+ // 将数据保存到db
|
|
|
+ saveSpecialPoint(sceneCode, TypeConstant.POI_BOUNDINGBOX_MAX, ageMax, gpsMax);
|
|
|
+ saveSpecialPoint(sceneCode, TypeConstant.POI_BOUNDINGBOX_MIN, ageMin, gpsMin);
|
|
|
+ saveSpecialPoint(sceneCode, TypeConstant.POI_CENTRE, ageCentre, gpsCentre);
|
|
|
+ log.info("max、min、中心点保存成功");
|
|
|
+
|
|
|
+
|
|
|
+ // 创建sitModel
|
|
|
+ createSiteModel(sceneCode, gpsMax, gpsMin, gpsCentre, maxZ, minZ);
|
|
|
+
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取两个值的
|
|
|
+ * json数组转 double[]
|
|
|
+ * @param resJson
|
|
|
+ * @param key
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Double[] getKey(JSONObject resJson , String key){
|
|
|
+ JSONArray array = resJson.getJSONArray(key);
|
|
|
+ Double[] res = {array.getDouble(0), array.getDouble(1)};
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取三个值的
|
|
|
+ * @param resJson
|
|
|
+ * @param key
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Double[] getKeyZ(JSONObject resJson , String key){
|
|
|
+ JSONArray array = resJson.getJSONArray(key);
|
|
|
+ Double[] res = {array.getDouble(0), array.getDouble(1), array.getDouble(2)};
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ /***
|
|
|
+ * 保存特质点
|
|
|
+ * @param sceneCode 场景码
|
|
|
+ * @param poiKey key
|
|
|
+ * @param agePoi 虚拟点坐标(四维看看坐标)
|
|
|
+ */
|
|
|
+ private void saveSpecialPoint(String sceneCode, String poiKey, Double[] agePoi, Double[] gpsPoi){
|
|
|
+ SpecialPointEntity entity = new SpecialPointEntity();
|
|
|
+ entity.setId(SnowFlakeUUidUtils.getUuid("SP"));
|
|
|
+ entity.setUpdateTime(LocalDateTime.now());
|
|
|
+ entity.setSceneCode(sceneCode);
|
|
|
+ entity.setPoiKey(poiKey);
|
|
|
+ entity.setPoi(agePoi);
|
|
|
+ entity.setGpsPoi(gpsPoi);
|
|
|
+ specialPointService.save(entity);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void createSiteModel(String sceneCode, Double[] max, Double[] min, Double[] centre, Double maxZ, Double minZ){
|
|
|
+ //读取初始文件
|
|
|
+ String content = cn.hutool.core.io.FileUtil.readUtf8String(configConstant.templatePath + "/site_model.json");
|
|
|
+ List<SiteDto> siteModels = JSON.parseArray(content, SiteDto.class);
|
|
|
+ // z_max、z_min 替换site_model的Floor、root类型
|
|
|
+ // max、min四个顶点替换BUILDING、FLOOR 的coordinates,
|
|
|
+ // 顺时针,(x_max,y_max),(x_max,y_min),(x_min,y_min),(x_min,y_max)
|
|
|
+ // 一般参数1:x, 参数2:Y
|
|
|
+ Double[] peak_1 = {max[0],max[1]};
|
|
|
+ Double[] peak_2 = {max[0],min[1]};
|
|
|
+ Double[] peak_3 = {min[0],min[1]};
|
|
|
+ Double[] peak_4 = {min[0],max[1]};
|
|
|
+ List<List<Double[]>> doubles = Arrays.asList(Arrays.asList(peak_1, peak_2, peak_3, peak_4));
|
|
|
+
|
|
|
+ // centre 替换BUILDING、FLOOR、ROOM 的center
|
|
|
+ log.info("中心点:{}, {}, {}", centre[0], centre[1], centre[2]);
|
|
|
+ siteModels.forEach(p -> {
|
|
|
+ // 第一层:BUILDING,处理centre、coordinates
|
|
|
+ p.setCenter(centre);
|
|
|
+ SitePolygon polygon = p.getPolygon();
|
|
|
+
|
|
|
+ // BUILDING. coordinates, max、min四个顶点替换
|
|
|
+ polygon.setCoordinates(doubles);
|
|
|
+
|
|
|
+ // 第二层:FLOOR 层
|
|
|
+ List<SiteDto> children = p.getChildren();
|
|
|
+ if (children.size() > 0) {
|
|
|
+ children.forEach(c ->{
|
|
|
+ c.setCenter(centre);
|
|
|
+ c.setZ_max(maxZ);
|
|
|
+ c.setZ_min(minZ);
|
|
|
+
|
|
|
+ // 第三层: ROOM层
|
|
|
+ List<SiteDto> roomChildren = c.getChildren();
|
|
|
+ if (roomChildren.size() > 0) {
|
|
|
+ roomChildren.forEach(r -> {
|
|
|
+ r.setCenter(centre);
|
|
|
+ r.setZ_max(maxZ);
|
|
|
+ r.setZ_min(minZ);
|
|
|
+ SitePolygon rPolygon = r.getPolygon();
|
|
|
+ rPolygon.setCoordinates(doubles);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ log.info("siteMode数据解析完成");
|
|
|
+ SiteModelEntity modelEntity = siteService.findById(sceneCode);
|
|
|
+ if (modelEntity != null) {
|
|
|
+ siteService.remove(sceneCode);
|
|
|
+ log.info("删除旧siteModel数据完成");
|
|
|
+ }
|
|
|
+ SiteModelEntity entity = new SiteModelEntity();
|
|
|
+ entity.setId(sceneCode);
|
|
|
+ entity.setCreateTime(LocalDateTime.now());
|
|
|
+ // 默认热点为空
|
|
|
+ entity.setData(siteModels);
|
|
|
+ siteService.save(entity);
|
|
|
+ log.info("siteModel数据初始化创建完成");
|
|
|
+ }
|
|
|
+}
|