lyhzzz 4 months ago
parent
commit
36cb567f3f

+ 10 - 0
src/main/java/com/fdkankan/fusion/common/ai/BBoxHierarchyBuilder.java

@@ -64,6 +64,9 @@ public class BBoxHierarchyBuilder {
 
             topLevel.add(parent.node);
         }
+        if(topLevel.isEmpty()){
+            return null;
+        }
         res.put("topLevel",topLevel);
         return res;
     }
@@ -71,10 +74,17 @@ public class BBoxHierarchyBuilder {
         JSONArray array=new JSONArray();
         for (Floors floor : floors) {
             JSONObject jsonObject = buildHierarchy(floor);
+            if(jsonObject == null){
+                continue;
+            }
             array.add(jsonObject);
         }
         return array;
     }
+
+    public static JSONObject buildHierarchyStart(Floors floor){
+        return buildHierarchy(floor);
+    }
     public static void main(String[] args) {
         // 示例:读取 Floors 对象(你可以从 JSON 文件反序列化)
         String jsonInput = "{\n" +

+ 2 - 1
src/main/java/com/fdkankan/fusion/common/ai/Floors.java

@@ -2,6 +2,7 @@ package com.fdkankan.fusion.common.ai;
 
 import com.alibaba.fastjson.annotation.JSONField;
 import lombok.Data;
+import scala.Int;
 
 import java.util.List;
 import java.util.Map;
@@ -18,6 +19,6 @@ public class Floors {
     private List<FloorPlanTag> shapes;
     @JSONField(name="name")
     private String floorsName;
-
+    private Integer subgroup;
     // Getters and sette
 }

+ 1 - 1
src/main/java/com/fdkankan/fusion/config/FusionConfig.java

@@ -13,6 +13,6 @@ public class FusionConfig {
     @Value("${fusion.ai-url:http://192.168.9.61:30000/v1/}")
     private String aiUrl;
 
-    @Value("${fusion.push-jm.url:http://123.com}")
+    @Value("${fusion.push-jm.url: }")
     private String pushJmUrl;
 }

+ 37 - 20
src/main/java/com/fdkankan/fusion/controller/AiController.java

@@ -8,13 +8,11 @@ import com.fdkankan.fusion.common.ResultCode;
 import com.fdkankan.fusion.common.ResultData;
 import com.fdkankan.fusion.common.ai.BBoxHierarchyBuilder;
 import com.fdkankan.fusion.common.ai.FloorUser;
+import com.fdkankan.fusion.common.ai.Floors;
 import com.fdkankan.fusion.common.util.Openai;
 import com.fdkankan.fusion.common.util.UploadToOssUtil;
 import com.fdkankan.fusion.config.FusionConfig;
-import com.fdkankan.fusion.entity.CaseFiles;
-import com.fdkankan.fusion.entity.CaseFilesType;
-import com.fdkankan.fusion.entity.CaseInquestInfo;
-import com.fdkankan.fusion.entity.CaseNumEntity;
+import com.fdkankan.fusion.entity.*;
 import com.fdkankan.fusion.exception.BusinessException;
 import com.fdkankan.fusion.request.AiParam;
 import com.fdkankan.fusion.response.FloorPathVo;
@@ -30,6 +28,7 @@ import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -50,8 +49,8 @@ public class AiController {
     AiService aiService;
 
     @PostMapping("/test")
-    public ResultData test( ) throws IOException {
-        FloorUser floorPlanResults = aiService.coverFloorPlanJson("C:\\Users\\4DAGE\\Downloads\\floorplan-ai.json");
+    public ResultData test(@RequestParam(required = false) String path ) throws IOException {
+        FloorUser floorPlanResults = aiService.coverFloorPlanJson(path);
 //        BBoxHierarchy.buildHierarchy(floorPlanResults.getFloors());
         JSONArray jsonArray = BBoxHierarchyBuilder.buildHierarchyStart(floorPlanResults.getFloors());
         return ResultData.ok(jsonArray);
@@ -73,24 +72,20 @@ public class AiController {
 
     @Autowired
     ICaseNumService caseNumService;
+    @Autowired
+    IScenePlusService scenePlusService;
     @GetMapping("/getFloor/{caseId}")
     public ResultData getFloor(@PathVariable Integer caseId){
         String foorPath = "/oss/4dkankan/scene_view_data/%s/user";
-        String fileName = "cad";
-        String extName = "jpg";
+        String fileName = "floorplan-ai";
+        String extName = "json";
         List<CaseNumEntity> byCaseId = caseNumService.getByCaseId(caseId);
-        List<FloorPathVo> pathVos = new ArrayList<>();
-        for (CaseNumEntity caseNumEntity : byCaseId) {
-            if(caseNumEntity.getNumType() == 3){
-                continue;
-            }
+        List<String> numList = byCaseId.stream().filter(e -> e.getNumType() != 3 && e.getNumType() != 2 && e.getNumType()!=5).map(CaseNumEntity::getNum).collect(Collectors.toList());
+        List<ScenePlus> scenePluses = scenePlusService.getByNumListAndAi(numList);
 
-            if(pathVos.stream().anyMatch(e -> e.getNum().equals(caseNumEntity.getNum()))){
-                continue;
-            };
+        List<FloorPathVo> pathVos = new ArrayList<>();
+        for (ScenePlus caseNumEntity : scenePluses) {
 
-            FloorPathVo pathVo = new FloorPathVo();
-            pathVo.setNum(caseNumEntity.getNum());
             String path = String.format(foorPath, caseNumEntity.getNum());
             File file = new File(path);
             File[] files = file.listFiles();
@@ -99,14 +94,36 @@ public class AiController {
             }
             for (File file1 : files) {
                 if(file1.getName().contains(fileName) && file1.getName().contains(extName)){
-                    pathVo.getUrls().add(file1.getPath().replace("4dkankan/",""));
+                    try {
+                        FloorUser floorPlanResults = aiService.coverFloorPlanJson(file1.getPath());
+                        for (Floors floor : floorPlanResults.getFloors()) {
+                            if(floor == null ){
+                                continue;
+                            }
+                            JSONObject jsonObject = BBoxHierarchyBuilder.buildHierarchyStart(floor);
+                            if(jsonObject == null  ){
+                                continue;
+                            }
+                            FloorPathVo pathVo = new FloorPathVo();
+                            pathVo.setNum(caseNumEntity.getNum());
+                            pathVo.setTitle(caseNumEntity.getTitle() + floor.getFloorsName());
+                            pathVo.setParams(jsonObject);
+                            pathVo.setUrl(foorPath.replace("4dkankan/","")+"/cad-style-3-"+floor.getSubgroup()+".jpg");
+                            pathVos.add(pathVo);
+                        }
+                    }catch (Exception e){
+                        log.info("getFloor-error:{}",e);
+                    }
+
+
                 }
             }
-            pathVos.add(pathVo);
+
         }
 
         return ResultData.ok(pathVos);
     }
 
+
 }
 

+ 3 - 0
src/main/java/com/fdkankan/fusion/entity/ScenePlus.java

@@ -118,4 +118,7 @@ public class ScenePlus implements Serializable {
 
     @TableField("has_ai")
     private Integer hasAi;
+
+    @TableField("has_floorplan_ai")
+    private Integer hasFloorplanAi;
 }

+ 5 - 1
src/main/java/com/fdkankan/fusion/mq/consumer/PushJMConsumer.java

@@ -3,12 +3,12 @@ package com.fdkankan.fusion.mq.consumer;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.bean.copier.MapToBeanCopier;
 import com.alibaba.fastjson.JSONObject;
-import com.fdkankan.fusion.common.util.StringUtils;
 import com.fdkankan.fusion.config.FusionConfig;
 import com.fdkankan.fusion.httpClient.client.OtherClient;
 import com.fdkankan.fusion.mq.vo.JmGaEventVo;
 import com.rabbitmq.client.Channel;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.amqp.core.Message;
 import org.springframework.amqp.rabbit.annotation.Queue;
 import org.springframework.amqp.rabbit.annotation.RabbitListener;
@@ -40,9 +40,13 @@ public class PushJMConsumer {
             String msg = new String(message.getBody(), StandardCharsets.UTF_8);
             log.info("push-jm-mq--messageId:{},msg:{}",messageId,msg);
             channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+            if(StringUtils.isBlank(fusionConfig.getPushJmUrl())){
+                return;
+            }
 
             JmGaEventVo jmGaEventVo = JSONObject.parseObject(msg, JmGaEventVo.class);
             Map<String, Object> stringObjectMap = BeanUtil.beanToMap(jmGaEventVo);
+
             String s = otherClient.postJson(fusionConfig.getPushJmUrl(), stringObjectMap);
 
         }catch (Exception e){

+ 50 - 1
src/main/java/com/fdkankan/fusion/response/FloorPathVo.java

@@ -1,5 +1,6 @@
 package com.fdkankan.fusion.response;
 
+import com.alibaba.fastjson.JSONArray;
 import lombok.Data;
 
 import java.util.ArrayList;
@@ -8,5 +9,53 @@ import java.util.List;
 @Data
 public class FloorPathVo {
     private String num;
-    private List<String> urls = new ArrayList<>();
+    private String title;
+    private String url;
+    private Object params;
+    private String paramContent ="# 角色\n" +
+            "你是一位专业的户型图分析专家,专注于解析户型图的识别结果数据,生成详细的户型结构描述,并准确判断家具所在的具体房间及其方位。\n" +
+            "\n" +
+            "## 技能\n" +
+            "### 技能1: 户型结构概述\n" +
+            "- 根据输入的识别结果数据和图片尺寸,生成整个户型的结构概述。\n" +
+            "- 描述户型的整体布局,包括主要功能区域(如卧室、客厅、厨房、卫生间等)及其分布。\n" +
+            "- 相同的房间加上序号序号输出到结果\n" +
+            "- 输出户型的基本信息,例如“[X室X厅X卫]”。\n" +
+            "### 技能2: 房间方位计算\n" +
+            "- 计算每个房间的中心点坐标,并结合给定的方向规则(上北下南左西右东)确定其具体方位。\n" +
+            "- 朝向规则;北是0度和360度,东是90度,南是180度,西是270度。Y轴向上的默认度数是0,逆时针旋转,需要根据度数方位去计算朝向\n" +
+            "- 提供每个房间的名称、方位以及相邻房间的信息。\n" +
+            "- 如果有重复的房间,请使用序号进行区分。\n" +
+            "\n" +
+            "### 技能3: 家具归属判断\n" +
+            "- 按照输入数据中的类别字段进行分析统计,确保不涉及错误分类问题。\n" +
+            "- 房间类别是Tag_开头的,家具不是tag开头。\n" +
+            "- childrens就是包含的家具,统计即可。\n" +
+            " \n" +
+            "### 技能4: 数据解析与格式化输出\n" +
+            "- 输入数据为 JSON 格式的识别结果数据,集合里面每个对象是一个对象,对象里面有childrens,compass,floorname三个字段。\n" +
+            "- floorname是楼层名称,compass是朝向的角度\n" +
+            "- 解析输入的识别结果数据(childrens对象包含 bbox、name(即是房间名称也是家具名称) 和 category 字段),并按指定模板格式化输出。\n" +
+            "- 确保输出内容清晰易读,严格遵循示例模板格式。\n" +
+            "\n" +
+            "## 限制\n" +
+            "- 输入数据必须包含完整的 bbox 坐标、名称和类别信息。若缺少必要字段,则标注为“数据错误”。\n" +
+            "- 图片尺寸和方向规则需明确提供,否则无法准确计算方位。\n" +
+            "- 输出内容严格遵循示例模板格式,包括户型结构概述、房间描述和家具归属判断。\n" +
+            "- 不涉及对户型设计的主观评价或建议,仅限于客观数据分析。\n" +
+            "\n" +
+            "## 输出模板是案例\n" +
+            "楼层 :${floorname} ,这是一个 [X室X厅X卫] 的户型。\n" +
+            "${房间名称}: 位于户型图 ${方位(例如东侧,东南侧)},,放置了 ${家具数量} 个 ${家具名称} 家具。\n" +
+            " \n" +
+            "## 注意事项:\n" +
+            "- 如何数据为空,直接返回数据为空。\n" +
+            "- 家具名称需要取name展示输出\n" +
+            "- 客厅不算室的数量\n" +
+            "- 楼层也是取floorname的value展示。不用展示key\n" +
+            "- 完全按照模板输出,无需使用 Markdown(MD)格式。\n" +
+            "- 输出内容需严格按照技能要求和限制条件执行。\n" +
+            "- 不用输出注意事项,只需要按照模板输出即可。\n" +
+            "- 不用输出提供参数。\n" +
+            "- 一定是按照模版输出。";
 }

+ 3 - 0
src/main/java/com/fdkankan/fusion/service/IScenePlusService.java

@@ -22,4 +22,7 @@ public interface IScenePlusService extends IService<ScenePlus> {
     List<DataGroupVo> groupByCameraId(DataParam param, List<Long> cameraIds);
 
     List<DataGroupVo> groupByType(DataParam param, List<Long> cameraIds);
+
+
+    List<ScenePlus> getByNumListAndAi(List<String> numList);
 }

+ 12 - 0
src/main/java/com/fdkankan/fusion/service/impl/ScenePlusServiceImpl.java

@@ -10,6 +10,7 @@ import com.fdkankan.fusion.service.IScenePlusService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -41,4 +42,15 @@ public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlu
     public List<DataGroupVo> groupByType(DataParam param, List<Long> cameraIds) {
         return getBaseMapper().groupByType(param.getStartTime(),param.getEndTime(),cameraIds);
     }
+
+    @Override
+    public List<ScenePlus> getByNumListAndAi(List<String> numList) {
+        if(numList == null || numList.isEmpty()){
+            return new ArrayList<>();
+        }
+        LambdaQueryWrapper<ScenePlus> wrapper = new LambdaQueryWrapper<>();
+        wrapper.in(ScenePlus::getNum,numList);
+        wrapper.eq(ScenePlus::getHasFloorplanAi,1);
+        return this.list(wrapper);
+    }
 }