Parcourir la source

pos/filter 接口

wuweihao il y a 4 ans
Parent
commit
f4caa39ff5

+ 8 - 2
README.md

@@ -164,12 +164,18 @@ t-40 (t-vZkqRV8):
     
     
     
-    2021-09-16
+  2021-09-16
     拿dataSet.location.z 值去siteModel判断是否在z_min,z.max之间, 在的话,更新dataSet.siteMdoel_id
     然后返回siteModel值
     
     
-   
+  2021-09-16
+    需求变更
+    1. 合并数据集
+        dataSet合并,B场景的siteModelIds=[]
+        siteModel不处理
+        filter.siteModelId=10, 默认为建筑物id=10 
+        tiled_map, 只添加数据,不上传文件, flood_id = '', file_path= 最后一位也先为空
   
   
 # db

+ 4 - 8
laser/src/main/java/com/fdkankan/indoor/base/convert/DistanceUtil.java

@@ -1,7 +1,6 @@
 package com.fdkankan.indoor.base.convert;
 
 import com.fdkankan.indoor.base.util.Factors;
-import com.fdkankan.indoor.base.util.Options;
 
 import java.awt.geom.Point2D;
 import java.util.List;
@@ -17,10 +16,10 @@ public class DistanceUtil {
      * 这个只有经纬度, 没有高度
      * @param coordinates1
      * @param coordinates2
-     * @param options 单位是米
+     * @param unit 单位是米:miles
      * @return
      */
-    private static double distance(Double[] coordinates1, Double[] coordinates2, Options options) {
+    public static double distance(Double[] coordinates1, Double[] coordinates2, String unit) {
 
         double dLat = degreesToRadians(coordinates2[1] - coordinates1[1]);
         double dLon = degreesToRadians(coordinates2[0] - coordinates1[0]);
@@ -30,10 +29,7 @@ public class DistanceUtil {
         double a = Math.pow(Math.sin(dLat / 2), 2) +
                         Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2);
 
-        return radiansToLength(
-                2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)),
-                options.getUnits()
-        );
+        return radiansToLength(2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)),unit);
 
         //double l=Math.pow(coordinates1[0]-coordinates2[0],2) +Math.pow(coordinates1[1]-coordinates2[1],2);
         //return Math.sqrt(l);
@@ -46,7 +42,7 @@ public class DistanceUtil {
      * @param coordinates2
      * @return     返回值单位是米
      */
-    public  static  double distance3(Double[] coordinates1, Double[] coordinates2){
+    public  static  double distanceHigh(Double[] coordinates1, Double[] coordinates2){
 //        double[] p1= GisCoordinateTransform.Convert2000BLToGauss(coordinates1[0],coordinates1[1]);
 //        double[] p2= GisCoordinateTransform.Convert2000BLToGauss(coordinates2[0],coordinates2[1]);
 

+ 5 - 2
laser/src/main/java/com/fdkankan/indoor/base/convert/GetRoute.java

@@ -151,17 +151,20 @@ public class GetRoute {
 
 
 			if(StrUtil.isEmpty(linkedIds)){
+				System.out.println("ok 11");
 				continue;
 			}
 
 			Coord coord = new Coord(Double.valueOf(strArray[0]),Double.valueOf(strArray[1]),Double.valueOf(strArray[2]));
 			Double _startDistance = g_AStar.calcH(_start, coord);
-			if(_startDistance<startDistance) {
+//			log.warn("比较: {}", _startDistance < startDistance);
+			if(_startDistance < startDistance) {
+				System.out.println("ok 123");
 				minStartId = i;
 				startDistance = _startDistance;
 			}
 			Double _endDistance = g_AStar.calcH(_end, coord);
-			if(_endDistance<endDistance) {
+			if(_endDistance < endDistance) {
 				minEndId = i;
 				endDistance = _endDistance;
 			}

+ 5 - 3
laser/src/main/java/com/fdkankan/indoor/core/controller/PoiController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.fdkankan.indoor.base.aop.WebControllerLog;
 import com.fdkankan.indoor.base.util.Result;
 import com.fdkankan.indoor.core.entity.dto.PoiHotDto;
+import com.fdkankan.indoor.core.entity.dto.PoiQueryDto;
 import com.fdkankan.indoor.core.entity.dto.PoiSearchDto;
 import com.fdkankan.indoor.core.service.PoiService;
 import io.swagger.annotations.Api;
@@ -80,15 +81,16 @@ public class PoiController {
     }
 
     /**
-     * 2021-07-27
+     * 2021-09-18
+     * 热点分类-> 取消勾选后 -> 相应热点不显示
      * @param sceneCode
      * @return
      */
     @WebControllerLog(description = "poi热点-过滤接口")
     @ApiOperation(value = "过滤接口", notes = "code:场景码")
     @PostMapping("indoor/{sceneCode}/api/pois/filter")
-    public Object filter(@PathVariable String sceneCode){
-        Result result = poiService.filter(sceneCode);
+    public Object filter(@PathVariable String sceneCode, @RequestBody PoiQueryDto param){
+        Result result = poiService.filter(sceneCode, param);
         return result.getData();
     }
 

+ 1 - 1
laser/src/main/java/com/fdkankan/indoor/core/controller/SiteModelController.java

@@ -44,7 +44,7 @@ public class SiteModelController {
      * https://testlaser.4dkankan.com/indoor
      *
      * https://testlaser.4dkankan.com/indoor/test2/api/site_model/within?location=113.595542719717&location=22.366858049261&location=-0.299806&type=FLOOR
-     * @param location
+     * @param location gis坐标
      * @param type
      * @return
      */

+ 49 - 0
laser/src/main/java/com/fdkankan/indoor/core/entity/dto/PoiQueryDto.java

@@ -0,0 +1,49 @@
+package com.fdkankan.indoor.core.entity.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * Created by owen on 2021/9/18 0002 10:30
+ * 查询poi表, 查询参数分两组
+ */
+@Data
+public class PoiQueryDto {
+
+    // 公共参数
+    @ApiModelProperty(value = "特点类型id")
+    private List<Integer> poi_type;
+
+    @ApiModelProperty(value = "siteModelIds")
+    private List<Integer> site_model_entity;
+
+
+    // 组一
+    @ApiModelProperty(value = "半径")
+    private Double radius;
+    private Double lat;
+    private Double lon;
+
+    // 组二
+    private Double lat_max;
+    private Double lat_min;
+    private Double lon_max;
+    private Double lon_min;
+
+    /** 返回数量*/
+    private Integer limit;
+
+    /**升序还是降序*/
+    private String sort_order;
+
+    /**对应db 根据那个字段排序 importance:字段*/
+    private String sort_by;
+
+    // 组三
+    @ApiModelProperty(value = "datasetIds")
+    private List<Integer> dataset;
+
+
+}

+ 1 - 1
laser/src/main/java/com/fdkankan/indoor/core/entity/dto/RouteInputDto.java

@@ -10,7 +10,7 @@ public class RouteInputDto {
 
 
 
-    // 起始点
+    // 起始点  2021-09-18 现在使用的点是gis坐标
     private Double source_latitude;
     private Double source_longitude;
     private Double source_z;

+ 1 - 0
laser/src/main/java/com/fdkankan/indoor/core/entity/po/DataSetPo.java

@@ -32,6 +32,7 @@ public class DataSetPo {
     private Double orientation;
 
     // siteModeld.id: 自己以及父id
+    // 2021-09-18 有机会重构, 使用List<Integer>
     private Integer[] site_model_entity_ids;
 
     private String point_cloud_type;

+ 2 - 0
laser/src/main/java/com/fdkankan/indoor/core/service/DataSetService.java

@@ -25,4 +25,6 @@ public interface DataSetService {
     DataSetEntity findById(String sceneCode);
 
     Result reposes(String sceneCode) throws Exception;
+
+    Integer getSiteModelIdByDataSetId(String sceneCode, Integer  dataSetId);
 }

+ 2 - 1
laser/src/main/java/com/fdkankan/indoor/core/service/PoiService.java

@@ -2,6 +2,7 @@ package com.fdkankan.indoor.core.service;
 
 import com.fdkankan.indoor.base.util.Result;
 import com.fdkankan.indoor.core.entity.dto.PoiHotDto;
+import com.fdkankan.indoor.core.entity.dto.PoiQueryDto;
 import com.fdkankan.indoor.core.entity.dto.PoiSearchDto;
 import com.fdkankan.indoor.core.entity.PoiEntity;
 import org.springframework.web.multipart.MultipartFile;
@@ -19,7 +20,7 @@ public interface PoiService {
 
     Result saveHot(String sceneCode, List<PoiHotDto> param);
 
-    Result filter(String sceneCode);
+    Result filter(String sceneCode, PoiQueryDto param);
 
 
     void save(PoiEntity entity);

+ 154 - 16
laser/src/main/java/com/fdkankan/indoor/core/service/impl/DataSetServiceImpl.java

@@ -1,24 +1,26 @@
 package com.fdkankan.indoor.core.service.impl;
 
+import cn.hutool.core.util.StrUtil;
 import com.fdkankan.indoor.base.constant.MsgCode;
 import com.fdkankan.indoor.base.constant.TypeConstant;
 import com.fdkankan.indoor.base.convert.FixRouteMap;
 import com.fdkankan.indoor.base.convert.MergeRouteMap;
 import com.fdkankan.indoor.base.exception.BaseRuntimeException;
+import com.fdkankan.indoor.base.util.GisUtils;
 import com.fdkankan.indoor.base.util.Result;
 import com.fdkankan.indoor.core.entity.*;
-import com.fdkankan.indoor.core.entity.dto.FilterHotDto;
-import com.fdkankan.indoor.core.entity.dto.PoiHotDto;
-import com.fdkankan.indoor.core.entity.dto.SecurityDto;
-import com.fdkankan.indoor.core.entity.dto.SiteDto;
+import com.fdkankan.indoor.core.entity.dto.*;
 import com.fdkankan.indoor.core.entity.po.DataSetPo;
 import com.fdkankan.indoor.core.mapper.DataSetMapper;
 import com.fdkankan.indoor.core.service.*;
 import lombok.extern.slf4j.Slf4j;
 import net.sf.json.JSONObject;
+import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
 
+import java.awt.geom.Point2D;
 import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
@@ -55,6 +57,9 @@ public class DataSetServiceImpl extends IBaseServiceImpl implements DataSetServi
     @Autowired
     SiteModelService siteModelService;
 
+    @Autowired
+    TiledMapService tiledMapService;
+
 
     @Override
     public void save(DataSetEntity entity) {
@@ -68,6 +73,10 @@ public class DataSetServiceImpl extends IBaseServiceImpl implements DataSetServi
         return Result.success(entity.getData());
     }
 
+
+
+
+
     @Override
     public Result update(String sceneCode, List<DataSetPo> param) {
 
@@ -99,8 +108,6 @@ public class DataSetServiceImpl extends IBaseServiceImpl implements DataSetServi
         // 处理的id
         List<Integer> newIds = new ArrayList<>();
         int i = 1;
-        Double[] location = null;
-        Double orientation = null;
         for (DataSetPo dto : param) {
             if (dto.getId() == null) {
                 maxId ++;
@@ -108,10 +115,6 @@ public class DataSetServiceImpl extends IBaseServiceImpl implements DataSetServi
                 dto.setId(maxId);
             }
 
-            if (i == 1) {
-                location = dto.getLocation();
-                orientation = dto.getOrientation();
-            }
             newIds.add(dto.getId());
             data.add(dto);
             i ++;
@@ -126,7 +129,7 @@ public class DataSetServiceImpl extends IBaseServiceImpl implements DataSetServi
         log.info("更新dataSet数据完成");
 
 
-        // 2021-09-16 处理比较高度与是否在响应的楼层, 不在修改dateSet , filter表响应的siteModelId
+        // 2021-09-16 处理比较高度与是否在响应的楼层, 不在情况下修改dateSet , filter表响应的siteModelId
         executeDateSetBySetModelIds(sceneCode);
 
         return Result.success(getDataBySceneCodeAndDataSetId(sceneCode, newIds));
@@ -148,7 +151,11 @@ public class DataSetServiceImpl extends IBaseServiceImpl implements DataSetServi
 
     /**
      * 2021-9-16
-     * 处理dataSet.site_model_ids, 是否在site_model.z_min,z_max范围内,且去掉房间ids
+     * 处理dataSet.site_model_ids, 是否在site_model.z_min,z_max范围内,符合条件的房间才加进去
+     *
+     * tiledMap: 如果没有符合的楼层,运行floor_id=为空
+     *
+     * filter.site_model_id, 先不
      */
     private void executeDateSetBySetModelIds(String sceneCode){
         DataSetEntity dataSetEntity = this.findById(sceneCode);
@@ -193,11 +200,28 @@ public class DataSetServiceImpl extends IBaseServiceImpl implements DataSetServi
                             siteModelIds.add(childFloor.getId());
                         }
 
-                        // 房间id
+                        // 房间, 用DataSet.location判断, 跟SiteModel.type=room.polygon.coordinates
                         List<SiteDto> childRoom = childFloor.getChildren();
                         if (childRoom.size() > 0) {
                             for (SiteDto siteDto : childRoom) {
-                                siteModelIds.add(siteDto.getId());
+
+                                // 判断点是否在多边形内
+                                SitePolygon polygon = siteDto.getPolygon();
+                                if (polygon == null) {
+                                    continue;
+                                }
+                                List<List<Double[]>> coordinates = polygon.getCoordinates();
+                                if (CollectionUtils.isEmpty(coordinates)){
+                                    continue;
+                                }
+
+                                // 使用datSet.location做为输入参数
+                                boolean isArea = pointIsArea(location, coordinates);
+                                // 在房间内, 把房间id加入siteModelIds
+                                if (isArea) {
+                                    siteModelIds.add(siteDto.getId());
+                                }
+
                             }
                         }
 
@@ -211,8 +235,99 @@ public class DataSetServiceImpl extends IBaseServiceImpl implements DataSetServi
         dataSetEntity.setData(resDataSet);
         this.save(dataSetEntity);
 
-        // 处理Filter.site_model_id
-        executeFilterBySetModelId(sceneCode, resDataSet);
+        // 2021-09-17 先不处理Filter.site_model_id
+        // executeFilterBySetModelId(sceneCode, resDataSet);
+
+    }
+
+    private void executeTiledMapByFloorId(String sceneCode, List<DataSetPo> dataSets ){
+        TiledMapEntity mapEntity = tiledMapService.findById(sceneCode);
+        if (mapEntity == null) {
+            String msg = "TiledMap数据不存在: " + sceneCode;
+            log.error(msg);
+            throw new BaseRuntimeException(msg);
+        }
+
+        List<TiledMapDto> mapDatas = mapEntity.getData();
+
+        boolean flag = false;
+        // 循环比较
+        for (DataSetPo dataSet : dataSets) {
+            // 默认情况下,dataSetId 是跟tiledMapId是一一对应的
+            Integer dataSetId = dataSet.getId();
+            for (TiledMapDto mapData : mapDatas) {
+                Integer mapDataId = mapData.getId();
+                if (dataSetId == mapDataId) {
+                    Integer floorId = mapData.getFloor_id();
+                    if (floorId == null) {
+                        Integer[] siteModelEntityIds = dataSet.getSite_model_entity_ids();
+                        if (siteModelEntityIds != null) {
+                            List<Integer> integers = Arrays.asList(siteModelEntityIds);
+                            // 默认第二元素是楼层
+                            mapData.setFloor_id(integers.get(1));
+                            // "data/bundle_" + sceneCode +"/building_1/map_tiles/" + dto.getFloor_id()
+                            String filePath = mapData.getFile_path();
+                            filePath = StrUtil.subBefore(filePath, "map_tiles/", true);
+                            filePath = filePath + "map_tiles/" + mapData.getFile_path();
+                            mapData.setFile_path(filePath);
+
+                            // 2021-09-17 将平面图上传oss todo
+                            flag = true;
+                        }
+                    }
+
+                }
+
+            }
+        }
+
+        // tiledMap 数据更新到数据库
+        if (flag) {
+            mapEntity.setData(mapDatas);
+            tiledMapService.save(mapEntity);
+            log.info("平面图数据更新完成");
+        } else {
+            log.info("平面图数据不需要更新");
+        }
+
+    }
+
+    @Test
+    public void testsub(){
+        String str = "data/bundle_/building_1/map_tiles/111111";
+        str = StrUtil.subBefore(str, "map_tiles/", true);
+        str = str + "map_tiles/" + 222;
+        System.out.println(str);
+    }
+
+
+    /**
+     * 输入点是否在多边形内
+     * @param point 输入点
+     * @param param 多边型坐标
+     * @return
+     */
+    private boolean pointIsArea(Double[] point, List<List<Double[]>> param){
+        boolean flag = false;
+        for (List<Double[]> lists : param) {
+            Point2D.Double pointDouble = new Point2D.Double();
+            pointDouble.setLocation(point[0], point[1]);
+
+
+
+            List<Point2D.Double> allPoints = lists.stream()
+                    .map(points -> new Point2D.Double(point[0], point[1])).collect(Collectors.toList());
+
+            Boolean inArea = GisUtils.rayCasting(allPoints, pointDouble);
+            // 只要点在多边型内,证明就在此房间内, 跳出循环
+            if (inArea){
+                flag = true;
+                break;
+            }
+            log.info("是否在多边型内: {}",  inArea);
+        }
+
+        return flag;
     }
 
 
@@ -369,6 +484,29 @@ public class DataSetServiceImpl extends IBaseServiceImpl implements DataSetServi
         return Result.success();
     }
 
+    /**
+     * 2021-09-18
+     * 通过dataSetId或者SiteModelId, 获取数组的最后一个
+     * @param sceneCode
+     * @param dataSetId
+     * @return
+     */
+    @Override
+    public Integer getSiteModelIdByDataSetId(String sceneCode, Integer dataSetId) {
+        List<DataSetPo> data = getDataBySceneCode(sceneCode);
+        data = data.stream().filter(p -> dataSetId.equals(p.getId())).collect(Collectors.toList());
+        if (data.size() > 0) {
+            DataSetPo dataSetPo = data.get(0);
+            Integer[] modelEntityIds = dataSetPo.getSite_model_entity_ids();
+            List<Integer> asList = Arrays.asList(modelEntityIds);
+            // 获取最后一个id值
+            Integer integer = asList.get(modelEntityIds.length - 1);
+            return integer;
+        }
+
+        return null;
+    }
+
     // json转字符串
     private static List<String> convertToString(List<JSONObject> param){
         List<String> mergeResult =  new ArrayList<>();

+ 2 - 2
laser/src/main/java/com/fdkankan/indoor/core/service/impl/FilterServiceImpl.java

@@ -374,7 +374,7 @@ public class FilterServiceImpl implements FilterService {
             coordinates2[1] = jsonData.getLocation()[1];
             coordinates2[2] = jsonData.getLocation()[2];
 
-            Double distance = DistanceUtil.distance3(coordinates1, coordinates2);
+            Double distance = DistanceUtil.distanceHigh(coordinates1, coordinates2);
 //            log.info("计算出的距离:{}", distance);
 
             if (queryJsonData.getRadius() > distance) {
@@ -434,7 +434,7 @@ public class FilterServiceImpl implements FilterService {
             coordinates2[1] = jsonData.getLocation()[1];
             coordinates2[2] = jsonData.getLocation()[2];
 
-            Double distance = DistanceUtil.distance3(coordinates1, coordinates2);
+            Double distance = DistanceUtil.distanceHigh(coordinates1, coordinates2);
 //            log.info("计算出的距离:{}", distance);
             // 默认取第一值
             if (i==1) {

+ 94 - 15
laser/src/main/java/com/fdkankan/indoor/core/service/impl/MergeSceneServiceImpl.java

@@ -80,6 +80,82 @@ public class MergeSceneServiceImpl extends IBaseServiceImpl implements MergeScen
      * @param mergeCode
      * @return
      */
+//    @Override
+//    public Result merge(String sceneCode, String mergeCode) {
+//
+//        List<MergeInfoEntity> mergeList =  mergeInfoService.findByMergeCode(mergeCode);
+//        if (mergeList.size() > 0) {
+//            Result.failure("此场景已合并:" + mergeCode);
+//        }
+//
+//
+//        ControlPointCalculateEntity controlPoint = controlPointCalculateService.findById(sceneCode);
+//
+//        if (controlPoint == null) {
+//            String msg = "控制点计算表结果不存在,尝试重算解决";
+//            log.error(msg);
+//            return Result.failure(msg);
+//        }
+//
+//        InitEntity initEntity = initService.findById(mergeCode);
+//
+//        String mergePath = "";
+//
+//        if ("dev".equals(configConstant.active)) {
+//            mergePath = configConstant.serverBasePath  + "/" + mergeCode + "/results/laserData";
+//        } else {
+//            mergePath = redisPath(mergeCode) + "/laserData";
+//        }
+//        log.info("合并场景路径:{}", mergePath);
+//
+//        // siteMode要优先处理;
+//        Map<Object, Object> resMap = mergeSiteModelFloor(sceneCode, mergeCode, mergePath, controlPoint);
+//
+//        Integer siteModelId = (Integer)resMap.get("maxId");
+//
+//        // dateSet.siteModelId是数组, 如果siteModel的模板id改了,这里要重新设置
+//        List<Integer> siteModeIds = Arrays.asList(10, siteModelId);
+//        Integer dataSetId = mergeDateSet(sceneCode, mergeCode, siteModeIds, mergePath, controlPoint.getRotation2());
+//
+//
+//        mergeFilter(sceneCode, mergeCode, controlPoint, mergePath, siteModelId, dataSetId);
+//
+//        // 合并平面图
+//        mergeTileMap(sceneCode, mergeCode, siteModelId, mergePath);
+//
+//        // 上传数据到oss:目录pano、pano_depth、webcloud上传oss 外层目录以场景码命名
+//        // todo 本地测试,注释上传oss
+//        if (!"dev".equals(configConstant.active)) {
+//            initService.ossUploadDirByLaserData(sceneCode, mergePath, mergeCode);
+//        }
+//        log.info("文件上传oss完成, 合并数据完成");
+//
+//        // 保存合并信息
+//        MergeInfoEntity entity = new MergeInfoEntity();
+//        entity.setDataSetId(dataSetId);
+//        entity.setMergeCode(mergeCode);
+//        entity.setSiteModelId(siteModelId);
+//        entity.setTitle(initEntity.getTitle());
+//        entity.setPath(mergePath);
+//        entity.setSceneCode(sceneCode);
+//        saveMergeInfo(entity);
+//
+//
+//        return Result.success();
+//    }
+
+    /**
+     *
+     * 合并场景
+     * 2021-09-17 新需求
+     * siteModel不合并
+     * dataSet.siteModelIds=[]
+     * filter.siteModelId=10(siteModel.id(type=building))
+     * tiled_map.floor_id=null, file_path=null, 后面操作时在补上(重置时,或上传片面图时)
+     * @param sceneCode
+     * @param mergeCode
+     * @return
+     */
     @Override
     public Result merge(String sceneCode, String mergeCode) {
 
@@ -109,19 +185,19 @@ public class MergeSceneServiceImpl extends IBaseServiceImpl implements MergeScen
         log.info("合并场景路径:{}", mergePath);
 
         // siteMode要优先处理;
-        Map<Object, Object> resMap = mergeSiteModelFloor(sceneCode, mergeCode, mergePath, controlPoint);
+//        Map<Object, Object> resMap = mergeSiteModelFloor(sceneCode, mergeCode, mergePath, controlPoint);
 
-        Integer siteModelId = (Integer)resMap.get("maxId");
+//        Integer siteModelId = (Integer)resMap.get("maxId");
 
         // dateSet.siteModelId是数组, 如果siteModel的模板id改了,这里要重新设置
-        List<Integer> siteModeIds = Arrays.asList(10, siteModelId);
-        Integer dataSetId = mergeDateSet(sceneCode, mergeCode, siteModeIds, mergePath, controlPoint.getRotation2());
+//        List<Integer> siteModeIds = Arrays.asList(10, siteModelId);
+        Integer dataSetId = mergeDateSet(sceneCode, mergeCode, null, mergePath, controlPoint.getRotation2());
 
+        // siteModelId:默认试用建筑物id
+        mergeFilter(sceneCode, mergeCode, controlPoint, mergePath, 10, dataSetId);
 
-        mergeFilter(sceneCode, mergeCode, controlPoint, mergePath, siteModelId, dataSetId);
-
-        // 合并平面图
-        mergeTileMap(sceneCode, mergeCode, siteModelId, mergePath);
+        // 合并平面图, siteModelId:默认先为空
+        mergeTileMap(sceneCode, mergeCode, null, mergePath);
 
         // 上传数据到oss:目录pano、pano_depth、webcloud上传oss 外层目录以场景码命名
         // todo 本地测试,注释上传oss
@@ -134,7 +210,8 @@ public class MergeSceneServiceImpl extends IBaseServiceImpl implements MergeScen
         MergeInfoEntity entity = new MergeInfoEntity();
         entity.setDataSetId(dataSetId);
         entity.setMergeCode(mergeCode);
-        entity.setSiteModelId(siteModelId);
+//        entity.setSiteModelId(siteModelId);
+        entity.setSiteModelId(null);
         entity.setTitle(initEntity.getTitle());
         entity.setPath(mergePath);
         entity.setSceneCode(sceneCode);
@@ -257,7 +334,8 @@ public class MergeSceneServiceImpl extends IBaseServiceImpl implements MergeScen
         mergeDto.setName(mergeCode);
         mergeDto.setTitle(mergeCode);
         // new Integer[0]:实例化一个Integer类的对象,并给该对象附值为0, siteModelIds: 取它自己,以及父类
-        mergeDto.setSite_model_entity_ids(siteModeIds.toArray(new Integer[0]));
+//        mergeDto.setSite_model_entity_ids(siteModeIds.toArray(new Integer[0]));
+        mergeDto.setSite_model_entity_ids(new Integer[0]);
         mergeDto.setSceneNum(mergeCode);
 
         mergePath = StrUtil.subBefore(mergePath, "/results", true);
@@ -739,7 +817,8 @@ public class MergeSceneServiceImpl extends IBaseServiceImpl implements MergeScen
     private SiteDto initSiteModelFloor(String sceneCode){
         SiteDto dto = new SiteDto();
         dto.setType("FLOOR");
-        dto.setName("合并FLOOR_" + sceneCode);
+//        dto.setName("合并FLOOR_" + sceneCode);
+        dto.setName(sceneCode);
 //        dto.setArea(2503.30551910935);
         dto.setVolume(295513.21880627);
         dto.setGeometry_hash(-200081285L);
@@ -805,10 +884,10 @@ public class MergeSceneServiceImpl extends IBaseServiceImpl implements MergeScen
             String ossTarget = "data/" + sceneCode + "/" + mapDto.getFile_path();
             String uploadDir = path + "/cover";
             log.info("uploadDir: {}", uploadDir);
-            // todo 本地测试,需要注释;
-            if (!"dev".equals(configConstant.active)) {
-                ossUploadDir(ossTarget, uploadDir);
-            }
+            // todo 2021-09-17 目前先不上传图片,之前的某个动作在上传
+//            if (!"dev".equals(configConstant.active)) {
+//                ossUploadDir(ossTarget, uploadDir);
+//            }
         }
 
 

+ 214 - 11
laser/src/main/java/com/fdkankan/indoor/core/service/impl/PoiServiceImpl.java

@@ -1,27 +1,21 @@
 package com.fdkankan.indoor.core.service.impl;
 
-import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.fdkankan.indoor.base.constant.MsgCode;
+import com.fdkankan.indoor.base.convert.DistanceUtil;
 import com.fdkankan.indoor.base.exception.BaseRuntimeException;
 import com.fdkankan.indoor.base.util.Result;
-import com.fdkankan.indoor.core.entity.PoiTypeEntity;
-import com.fdkankan.indoor.core.entity.dto.PoiHotDto;
-import com.fdkankan.indoor.core.entity.dto.PoiSearchDto;
-import com.fdkankan.indoor.core.entity.dto.PoiTypeDto;
+import com.fdkankan.indoor.core.entity.dto.*;
 import com.fdkankan.indoor.core.entity.PoiEntity;
-import com.fdkankan.indoor.core.entity.dto.SecurityDto;
 import com.fdkankan.indoor.core.mapper.PoiMapper;
+import com.fdkankan.indoor.core.service.DataSetService;
 import com.fdkankan.indoor.core.service.PoiService;
 import com.fdkankan.indoor.core.service.PoiTypeService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoTemplate;
-import org.springframework.data.mongodb.core.query.Criteria;
-import org.springframework.data.mongodb.core.query.Query;
-import org.springframework.data.mongodb.core.query.Update;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -46,6 +40,10 @@ public class PoiServiceImpl extends IBaseServiceImpl implements PoiService {
     @Autowired
     PoiMapper entityMapper;
 
+
+    @Autowired
+    DataSetService dataSetService;
+
     @Override
     public void remove(String sceneCode) {
         entityMapper.deleteById(sceneCode);
@@ -176,6 +174,13 @@ public class PoiServiceImpl extends IBaseServiceImpl implements PoiService {
                 log.info("设置图标:{}", dto.getIcon());
             }
 
+            // 2021-09-17 前端不一定会添加这个参数,根据dataSet.id 去找siteModelId
+            if (dto.getSite_model_entity_id() == null) {
+                Integer datasetId = dto.getDataset_id();
+                Integer siteModelIdByDataSetId = dataSetService.getSiteModelIdByDataSetId(sceneCode, datasetId);
+                dto.setSite_model_entity_id(siteModelIdByDataSetId);
+            }
+
             data.add(dto);
             resIds.add(dto.getId());
         }
@@ -187,7 +192,6 @@ public class PoiServiceImpl extends IBaseServiceImpl implements PoiService {
 
         save(entity);
 
-//        return Result.success(findDataBySceneCode(sceneCode));
         return Result.success(changeById(sceneCode, resIds));
     }
 
@@ -210,9 +214,105 @@ public class PoiServiceImpl extends IBaseServiceImpl implements PoiService {
         return "";
     }
 
+//    @Override
+//    public Result filter(String sceneCode, PoiQueryDto param) {
+//        List<PoiHotDto> data = findDataBySceneCode(sceneCode);
+//        if (isLogin()) {
+//            return Result.success(data);
+//        }
+//        return Result.success(changeSecurityUnLoginList(data));
+//    }
+
+    // 查询是有优先级的
     @Override
-    public Result filter(String sceneCode) {
+    public Result filter(String sceneCode, PoiQueryDto param) {
         List<PoiHotDto> data = findDataBySceneCode(sceneCode);
+
+        // 返回dataset对应的热点
+        if (param.getDataset() != null) {
+            List<Integer> dataset = param.getDataset();
+            if (dataset.size() > 0) {
+                // 默认只有一个元素
+                Integer dataSetId = dataset.get(0);
+                data = data.stream().filter(p -> dataSetId.equals(p.getDataset_id())).collect(Collectors.toList());
+                return Result.success(data);
+            }
+        }
+
+
+
+        List<Integer> siteModelIds = param.getSite_model_entity();
+        List<Integer> poiTypeIds = param.getPoi_type();
+
+        if (siteModelIds.size() == 0 || poiTypeIds.size() == 0) {
+            return  Result.success();
+        }
+
+        data = data.stream().filter(p -> siteModelIds.contains(p.getSite_model_entity_id())).collect(Collectors.toList());
+        data = data.stream().filter(p -> poiTypeIds.contains(p.getPoi_type_id())).collect(Collectors.toList());
+
+        if (data.size() == 0) {
+            log.warn("查询结果没有符合条件的数据");
+            return Result.success();
+        }
+
+        // 处理 lat, lon
+        Double lat = param.getLat();
+        Double lon = param.getLon();
+        if (lat != null && lon != null) {
+            // 处理半径, radius:半径
+            Double radius = param.getRadius();
+            if (radius != null) {
+                data = calculate(param, data);
+            } else {
+                // 没有半径,算最近的距离, 返回值只有一条数据
+                data = calculateMin(param, data);
+            }
+            log.info("lat、lon-输出数量:{}", data.size());
+
+            if (data.size() == 0) {
+                log.warn("查询结果没有符合条件的数据");
+                return Result.success();
+            }
+        }
+
+        // 处理lon_min、lon_max, lat_min、lat_max
+        Double latMax = param.getLat_max();
+        Double latMin = param.getLat_min();
+        Double lonMax = param.getLon_max();
+        Double lonMin = param.getLon_min();
+        if (latMax != null && latMin != null && lonMax != null && lonMin != null) {
+            data = data.stream().filter(jsonData ->
+                    jsonData.getLocation()[0] >= lonMin && jsonData.getLocation()[0] <= lonMax
+                            && jsonData.getLocation()[1] >= latMin && jsonData.getLocation()[1] <= latMax).collect(Collectors.toList());
+
+            if (data.size() == 0) {
+                log.warn("查询结果没有符合条件的数据");
+                return Result.success();
+            }
+        }
+
+        // 对应db 根据那个字段排序
+        String sortOrder = param.getSort_order();
+        sortOrder = sortOrder==null ? null :sortOrder.toLowerCase();
+        // 升序还是降序
+        String sortBy = param.getSort_by();
+        sortBy = sortBy==null ? null :sortBy.toLowerCase();
+
+
+        // 处理排序reversed()降序, 默认是升序, 对
+        if ("desc".equals(sortBy) && "importance".equals(sortOrder)) {
+            data = data.stream().sorted(Comparator.comparing(PoiHotDto::getImportance).reversed()).collect(Collectors.toList());
+        } else if ("asc".equals(sortBy) && "importance".equals(sortOrder)){
+            data =  data.stream().sorted(Comparator.comparing(PoiHotDto::getImportance)).collect(Collectors.toList());
+        }
+
+
+        if (data.size() == 0) {
+            log.warn("查询结果没有符合条件的数据");
+            return Result.success();
+        }
+
         if (isLogin()) {
             return Result.success(data);
         }
@@ -220,6 +320,109 @@ public class PoiServiceImpl extends IBaseServiceImpl implements PoiService {
     }
 
 
+    /**
+     * 计算最小距离
+     * @param queryJsonData
+     * @return 获取最小值对象
+     */
+    private  List<PoiHotDto> calculateMin(PoiQueryDto queryJsonData, List<PoiHotDto> jsonDataList) {
+        log.info("run calculeMin");
+        List<PoiHotDto> newJsonData = new ArrayList<>();
+
+        // 计算距离后的结果集
+        HashMap<Double, PoiHotDto> calResultMap = new HashMap<>();
+
+        Double[] coordinates1 = new Double[3];
+        coordinates1[0] = queryJsonData.getLon();
+        coordinates1[1] = queryJsonData.getLat();
+
+//        Double z = queryJsonData.getZ();
+//        z = z == null ? 0 : z;
+//        coordinates1[2] = z;
+
+        int i = 1;
+        Double min = null;
+        for (PoiHotDto jsonData : jsonDataList) {
+
+
+            Double[] coordinates2 = new Double[3];
+            coordinates2[0] = jsonData.getLocation()[0];
+            coordinates2[1] = jsonData.getLocation()[1];
+            coordinates2[2] = jsonData.getLocation()[2];
+
+            Double distance = DistanceUtil.distance(coordinates1, coordinates2, "miles");
+//            log.info("计算出的距离:{}", distance);
+            // 默认取第一值
+            if (i==1) {
+                min = distance;
+                calResultMap.put(min, jsonData);
+            }
+
+            if (distance < min) {
+                min = distance;
+                calResultMap.put(min, jsonData);
+            }
+            i++;
+
+        }
+
+        log.info("循环次数:{}, 最小值:{}", i, min);
+        // 获取最小值
+        PoiHotDto minJson = calResultMap.get(min);
+        newJsonData.add(minJson);
+        return newJsonData;
+    }
+
+
+    private List<PoiHotDto> calculate(PoiQueryDto queryJsonData, List<PoiHotDto> jsonDataList) {
+
+        Double[] coordinates1 = new Double[3];
+        coordinates1[0] = queryJsonData.getLon();
+        coordinates1[1] = queryJsonData.getLat();
+
+//        Double z = queryJsonData.getZ();
+//        z = z == null ? 0 : z;
+//        coordinates1[2] = z;
+
+        // 计算距离后的结果集
+        Map<Double, PoiHotDto> calResultMap = new HashMap<>();
+        for (PoiHotDto jsonData : jsonDataList) {
+
+
+            Double[] coordinates2 = new Double[3];
+            coordinates2[0] = jsonData.getLocation()[0];
+            coordinates2[1] = jsonData.getLocation()[1];
+            coordinates2[2] = jsonData.getLocation()[2];
+            //计算两点的距离
+            double distance = (double) DistanceUtil.distance(coordinates1, coordinates2, "miles");
+            log.info("计算出的距离:{}", distance);
+
+            if (queryJsonData.getRadius() > distance) {
+                // 缓存对象
+                calResultMap.put(distance, jsonData);
+            }
+        }
+
+        // 从小到大排序, 冒泡排序
+        List<Double> list = new ArrayList<>();
+        calResultMap.forEach((k,v) -> {
+            list.add(k);
+        });
+        log.info("排序前: {}", list);
+        // 升序排列
+        List<Double> collect = list.stream().sorted().collect(Collectors.toList());
+        log.info("排序后: {}", collect);
+
+
+        // 通过key获取对象
+        List<PoiHotDto> result = new ArrayList<>();
+        collect.forEach(p -> {
+            result.add(calResultMap.get(p));
+        });
+
+        return result;
+    }
+
 
     private PoiEntity findById(String sceneCode){
         Optional<PoiEntity> optional = entityMapper.findById(sceneCode);

+ 111 - 17
laser/src/main/java/com/fdkankan/indoor/core/service/impl/SiteModelServiceImpl.java

@@ -68,6 +68,15 @@ public class SiteModelServiceImpl implements SiteModelService {
     public Result search(String sceneCode, SiteModelSearchDto searchDto) {
 
         List<SiteDto> data = getDataBySceneCode(sceneCode);
+        // 2021-09-18
+        if (data.size() == 0) {
+            String msg = "siteModel表数据为空, 返回一个空数组";
+            log.info(msg);
+
+            return Result.success();
+        }
+
+
         SiteDto siteDto = data.get(0);
 
         List<SiteDto> loopModel = getLoopModel(siteDto);
@@ -87,6 +96,15 @@ public class SiteModelServiceImpl implements SiteModelService {
     @Override
     public Result latest(String sceneCode, Double[] location, Double radius) {
         List<SiteDto> data = getDataBySceneCode(sceneCode);
+
+        // 2021-09-18
+        if (data.size() == 0) {
+            String msg = "siteModel表数据为空, 返回一个空数组";
+            log.info(msg);
+
+            return Result.success();
+        }
+
         SiteDto siteDto = data.get(0);
         // 递归为对象
         List<SiteDto> loopModel = getLoopModel(siteDto);
@@ -106,38 +124,71 @@ public class SiteModelServiceImpl implements SiteModelService {
 
     @Override
     public Result withinType(String sceneCode, Double[] location, String type) {
-        // 总对象
-        List<SiteDto> models = new ArrayList<>();
+
 
 
         List<SiteDto> resData = getDataBySceneCode(sceneCode);
+        // 2021-09-18
+        if (resData.size() == 0) {
+            String msg = "siteModel表数据为空, 返回一个空数组";
+            log.info(msg);
+
+            return Result.success();
+        }
         SiteDto siteModel = resData.get(0);
 
         // copy实体对象
         SiteDto newSiteModel = copyModelNotContainChildren(siteModel);
+
+        // 总对象
+        List<SiteDto> models = new ArrayList<>();
+
         // 做为父节点的低一条
         models.add(newSiteModel);
         if (!CollectionUtils.isEmpty(siteModel.getChildren())) {
             organizeModels2(siteModel, models);
         }
 
+        // 2021-09-18 将siteModel存在的类型添加
+        HashSet<String> setTypes = new HashSet<>();
+        for (SiteDto model : models) {
+            String cType = model.getType();
+            setTypes.add(cType.toUpperCase());
+        }
+
+
 
         // 按type封装成对象数组
         List<SiteDto> resultList = new ArrayList<>();
         SiteDto result = null;
 
+        ArrayList<Object> list = new ArrayList<>();
+
         Point2D.Double pointParam = new Point2D.Double(location[0], location[1]);
         log.info("pointParam: {}", pointParam);
         if ("BUILDING".equals(type)) {
+            if (!setTypes.contains(type)) {
+                log.warn(type + ": 数据不存在,返回空数组");
+                return Result.success();
+            }
             resultList =  models.stream().filter(data -> "BUILDING".equals(data.getType())).collect(Collectors.toList());
             result = resultList.stream().filter(sm -> getSm(sm, pointParam)).findAny()
                     .orElseThrow(() -> new RuntimeException("没有找到符合多边形的点"));
-        } else if ("FLOOR".equals(type)) {
+        } else if ("FLOOR".equals(type) ) {
+            if (!setTypes.contains(type)) {
+                log.warn(type + ": 数据不存在,返回空数组");
+                return Result.success();
+            }
             resultList =  models.stream().filter(data -> "FLOOR".equals(data.getType())).collect(Collectors.toList());
             log.info("resultList.size: {}", resultList.size());
 
             result = resultList.stream().filter(sm -> getSmByFloor(sm, pointParam)).findAny().orElseThrow(() -> new RuntimeException("没有找到符合多边形的点"));
         } else if ("ROOM".equals(type)) {
+            if (!setTypes.contains(type)) {
+                log.warn(type + ": 数据不存在,返回空数组");
+                return Result.success();
+            }
+
             resultList =  models.stream().filter(data -> "ROOM".equals(data.getType())).collect(Collectors.toList());
             result = resultList.stream().filter(sm -> getSm(sm, pointParam)).findAny()
                     .orElseThrow(() -> new RuntimeException("没有找到符合多边形的点"));
@@ -154,7 +205,7 @@ public class SiteModelServiceImpl implements SiteModelService {
         }
 
         log.info("result: {}", result);
-        ArrayList<Object> list = new ArrayList<>();
+//        ArrayList<Object> list = new ArrayList<>();
         list.add(result);
         return Result.success(list);
     }
@@ -168,6 +219,9 @@ public class SiteModelServiceImpl implements SiteModelService {
 
 
         List<SiteDto> resData = getDataBySceneCode(sceneCode);
+
+
+
         SiteDto siteModel = resData.get(0);
 
         if (siteModel != null) {
@@ -196,6 +250,16 @@ public class SiteModelServiceImpl implements SiteModelService {
     @Override
     public List<Integer> findBySceneCodeAndIdAndSon(String code, Integer site_model_entity) {
         List<SiteDto> data = getDataBySceneCode(code);
+
+        // 2021-09-18
+        if (data.size() == 0) {
+            String msg = "siteModel表数据为空, 返回一个空数组";
+            log.info(msg);
+            return new ArrayList<>();
+
+//            return Result.success();
+        }
+
         // 递归为对象
         SiteDto siteDto = data.get(0);
         List<Integer> result = new ArrayList<>();
@@ -295,7 +359,8 @@ public class SiteModelServiceImpl implements SiteModelService {
 
         // 去掉房间数据
         List<SiteDto> data = entity.getData();
-        recursionRemoveRoom(data);
+//        recursionRemoveRoom(data);
+        data = removeRoom(data);
 
         entity.setData(data);
         this.save(entity);
@@ -310,6 +375,8 @@ public class SiteModelServiceImpl implements SiteModelService {
     /**
      * 2021-9-16
      * 处理dataSet.site_model_ids, 是否在site_model.z_min,z_max范围内,且去掉房间ids
+     *
+     * 2021-9-17 building只留一个楼层
      */
     private void executeDateSetBySetModelIds(String sceneCode, List<SiteDto> data){
         DataSetEntity dataSetEntity = dataSetService.findById(sceneCode);
@@ -340,6 +407,7 @@ public class SiteModelServiceImpl implements SiteModelService {
                         Double z_min = childFloor.getZ_min();
                         // 高度在该楼层范围之内
                         if (z_max > z && z > z_min) {
+                            log.info("z_max:{}, z:{}, z_min:{}, id:{}", z_max, z, z_min, childFloor.getId());
                             siteModelIds.add(childFloor.getId());
                         }
                     }
@@ -400,25 +468,51 @@ public class SiteModelServiceImpl implements SiteModelService {
     }
 
 
-
     /**
-     * 2021-9-16
-     * 递归方法遍历, 删除房间
+     * 1.删除房间
+     * 2.如果有多个楼层,删除多个楼层保留第一个
+     *
+     * @param param
      */
-    private  void recursionRemoveRoom(List<SiteDto> param){
+    private  List<SiteDto> removeRoom(List<SiteDto> param){
+
+        List<SiteDto> resSite = new ArrayList<>();
+
         for (SiteDto dto : param) {
-            // 递归调用
-            List<SiteDto> children = dto.getChildren();
-            if ("FLOOR".equals(dto.getType())){
-                children = new ArrayList<>();
-                dto.setChildren(children);
-            }
-            if (children.size() > 0) {
-                recursionRemoveRoom(children);
+            List<SiteDto> childFloor = dto.getChildren();
+            // 只要一个楼层, 并情况房间
+            List<SiteDto>  newFloors = new ArrayList<>();
+            if (childFloor.size() > 0) {
+                SiteDto siteDto = childFloor.get(0);
+                siteDto.setChildren(new ArrayList<>());
+                newFloors.add(siteDto);
+                dto.setChildren(newFloors);
             }
+
+            resSite.add(dto);
+
         }
+        return resSite;
     }
 
+    /**
+     * 2021-9-16
+     * 递归方法遍历, 删除房间
+     */
+//    private  void recursionRemoveRoom(List<SiteDto> param){
+////        for (SiteDto dto : param) {
+////            // 递归调用
+////            List<SiteDto> children = dto.getChildren();
+////            if ("FLOOR".equals(dto.getType())){
+////                children = new ArrayList<>();
+////                dto.setChildren(children);
+////            }
+////            if (children.size() > 0) {
+////                recursionRemoveRoom(children);
+////            }
+////        }
+////    }
+
 
 
     // 判断的坐标在那个空间位置