xiewj 4 månader sedan
förälder
incheckning
1ee5424554

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

@@ -0,0 +1,249 @@
+package com.fdkankan.fusion.common.ai;
+
+import java.util.ArrayList;
+import java.util.List;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+/**
+ * @author Xiewj
+ * @date 2025/4/16
+ */
+public class BBoxHierarchyBuilder {
+
+    static class ShapeWrapper {
+        FloorPlanTag tag;
+        Double[] xyxy;
+        JSONObject node;
+
+        ShapeWrapper(FloorPlanTag tag) {
+            this.tag = tag;
+            this.xyxy = tag.getBbox();
+            this.node = new JSONObject();
+            this.node.put("name", tag.getName());
+            this.node.put("category", tag.getCategory());
+            this.node.put("bbox", tag.getBbox());
+        }
+
+
+        boolean contains(ShapeWrapper other) {
+            return other.xyxy[0] >= xyxy[0] &&
+                    other.xyxy[1] >= xyxy[1] &&
+                    other.xyxy[2] <= xyxy[2] &&
+                    other.xyxy[3] <= xyxy[3];
+        }
+    }
+
+    public static JSONObject buildHierarchy(Floors floors) {
+        List<FloorPlanTag> shapes = floors.getShapes();
+        List<ShapeWrapper> allShapes = new ArrayList<>();
+
+        for (FloorPlanTag tag : shapes) {
+            allShapes.add(new ShapeWrapper(tag));
+        }
+        JSONObject res=new JSONObject();
+        JSONArray topLevel = new JSONArray();
+        res.put("floorsName",floors.getFloorsName());
+        for (ShapeWrapper parent : allShapes) {
+            if (!parent.tag.getCategory().startsWith("Tag_")) continue;
+
+            JSONArray children = new JSONArray();
+            for (ShapeWrapper child : allShapes) {
+                if (child == parent) continue;
+                if (parent.contains(child)) {
+                    children.add(child.node);
+                }
+            }
+
+            if (!children.isEmpty()) {
+                parent.node.put("children", children);
+            }
+
+            topLevel.add(parent.node);
+        }
+        res.put("topLevel",topLevel);
+        return res;
+    }
+    public static JSONArray buildHierarchyStart(List<Floors> floors){
+        JSONArray array=new JSONArray();
+        for (Floors floor : floors) {
+            JSONObject jsonObject = buildHierarchy(floor);
+            array.add(jsonObject);
+        }
+        return array;
+    }
+    public static void main(String[] args) {
+        // 示例:读取 Floors 对象(你可以从 JSON 文件反序列化)
+        String jsonInput = "{\n" +
+                "    \"floors\": [\n" +
+                "      {\n" +
+                "        \"imageWidth\": \"683\",\n" +
+                "        \"imageHeight\": \"637\",\n" +
+                "        \"shapes\": [\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              219.5,\n" +
+                "              221.00000000000006,\n" +
+                "              273.5,\n" +
+                "              275.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"三人沙发\",\n" +
+                "            \"category\": \"ThreeSofa\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              453,\n" +
+                "              408.50000000000006,\n" +
+                "              529,\n" +
+                "              484.5\n" +
+                "            ],\n" +
+                "            \"name\": \"双人床\",\n" +
+                "            \"category\": \"DoubleBed\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              136.50000000000003,\n" +
+                "              169.00000000000006,\n" +
+                "              185.50000000000003,\n" +
+                "              218.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"三人沙发\",\n" +
+                "            \"category\": \"ThreeSofa\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              417,\n" +
+                "              203.00000000000006,\n" +
+                "              455,\n" +
+                "              241.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"书桌\",\n" +
+                "            \"category\": \"Desk\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              218.5,\n" +
+                "              468.00000000000006,\n" +
+                "              287.50000000000006,\n" +
+                "              537.0000000000001\n" +
+                "            ],\n" +
+                "            \"name\": \"双人床\",\n" +
+                "            \"category\": \"DoubleBed\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              232.5,\n" +
+                "              160.00000000000006,\n" +
+                "              272.5,\n" +
+                "              200.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"书桌\",\n" +
+                "            \"category\": \"Desk\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              297,\n" +
+                "              171.00000000000006,\n" +
+                "              321,\n" +
+                "              195.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"椅子\",\n" +
+                "            \"category\": \"Chair\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              418.5,\n" +
+                "              181.00000000000006,\n" +
+                "              441.5,\n" +
+                "              204.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"椅子\",\n" +
+                "            \"category\": \"Chair\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              233.48909302398266,\n" +
+                "              122.51909302398272,\n" +
+                "              272.51090697601734,\n" +
+                "              161.5409069760174\n" +
+                "            ],\n" +
+                "            \"name\": \"地毯\",\n" +
+                "            \"category\": \"Carpet\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              398,\n" +
+                "              370,\n" +
+                "              549,\n" +
+                "              503\n" +
+                "            ],\n" +
+                "            \"name\": \"卧室\",\n" +
+                "            \"category\": \"Tag_bedroom\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              155,\n" +
+                "              423,\n" +
+                "              364,\n" +
+                "              587\n" +
+                "            ],\n" +
+                "            \"name\": \"卧室\",\n" +
+                "            \"category\": \"Tag_bedroom\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              499,\n" +
+                "              196,\n" +
+                "              633,\n" +
+                "              309\n" +
+                "            ],\n" +
+                "            \"name\": \"厨房\",\n" +
+                "            \"category\": \"Tag_kitchenroom\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              69,\n" +
+                "              104,\n" +
+                "              620,\n" +
+                "              279\n" +
+                "            ],\n" +
+                "            \"name\": \"客厅\",\n" +
+                "            \"category\": \"Tag_livingroom\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              540.3126453583378,\n" +
+                "              517.0000000000001,\n" +
+                "              530.1507146416621,\n" +
+                "              553.0000000000001\n" +
+                "            ],\n" +
+                "            \"name\": \"窗户\",\n" +
+                "            \"category\": \"BayWindow\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              81.08604535833786,\n" +
+                "              110.00000000000006,\n" +
+                "              70.92411464166213,\n" +
+                "              298.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"窗户\",\n" +
+                "            \"category\": \"BayWindow\"\n" +
+                "          }\n" +
+                "        ],\n" +
+                "        \"floorsName\": \"1楼\"\n" +
+                "      }\n" +
+                "    ],\n" +
+                "    \"compass\": 0\n" +
+                "  }"; // 你的 JSON 字符串
+        JSONObject input = JSON.parseObject(jsonInput);
+        Floors floor = input.getJSONArray("floors").getObject(0, Floors.class);
+
+        JSONObject hierarchy = buildHierarchy(floor);
+
+        System.out.println(JSON.toJSONString(hierarchy, true));
+    }
+}

+ 239 - 0
src/main/java/com/fdkankan/fusion/common/ai/BoxVisualizer.java

@@ -0,0 +1,239 @@
+package com.fdkankan.fusion.common.ai;
+
+/**
+ * @author Xiewj
+ * @date 2025/4/16
+ */
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+public class BoxVisualizer {
+
+    public static void drawFloors(Floors floor, String outputPath, int canvasWidth, int canvasHeight) throws IOException {
+        int imageWidth = Integer.parseInt(floor.getImageWidth());
+        int imageHeight = Integer.parseInt(floor.getImageHeight());
+
+        double scaleX = (double) canvasWidth / imageWidth;
+        double scaleY = (double) canvasHeight / imageHeight;
+
+        BufferedImage image = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_RGB);
+        Graphics2D g2d = image.createGraphics();
+
+        // 背景白色
+        g2d.setColor(Color.WHITE);
+        g2d.fillRect(0, 0, canvasWidth, canvasHeight);
+
+        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        g2d.setFont(new Font("Arial", Font.PLAIN, 12));
+
+        for (FloorPlanTag tag : floor.getShapes()) {
+            Double[] bbox = tag.getBbox();
+            if (bbox.length < 4) continue;
+
+            // 绝对坐标 bbox:[x1, y1, x2, y2]
+            double x1 = bbox[0] * scaleX;
+            double y1 = bbox[1] * scaleY;
+            double x2 = bbox[2] * scaleX;
+            double y2 = bbox[3] * scaleY;
+
+            int x = (int) Math.round(x1);
+            int y = (int) Math.round(y1);
+            int boxWidth = (int) Math.round(x2 - x1);
+            int boxHeight = (int) Math.round(y2 - y1);
+
+            Color color = tag.getCategory().startsWith("Tag_") ? Color.RED : Color.BLUE;
+            g2d.setColor(color);
+            g2d.drawRect(x, y, boxWidth, boxHeight);
+            g2d.drawString(tag.getCategory(), x + 2, y + 12);
+        }
+
+        g2d.dispose();
+
+        File output = new File(outputPath);
+        File parentDir = output.getParentFile();
+        if (parentDir != null && !parentDir.exists()) {
+            parentDir.mkdirs();
+        }
+
+        ImageIO.write(image, "png", output);
+        System.out.println("保存成功:" + output.getAbsolutePath());
+    }
+
+    public static void main(String[] args) throws IOException {
+        String jsonInput = "{\n" +
+                "    \"floors\": [\n" +
+                "      {\n" +
+                "        \"imageWidth\": \"683\",\n" +
+                "        \"imageHeight\": \"637\",\n" +
+                "        \"shapes\": [\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              219.5,\n" +
+                "              221.00000000000006,\n" +
+                "              273.5,\n" +
+                "              275.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"三人沙发\",\n" +
+                "            \"category\": \"ThreeSofa\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              453,\n" +
+                "              408.50000000000006,\n" +
+                "              529,\n" +
+                "              484.5\n" +
+                "            ],\n" +
+                "            \"name\": \"双人床\",\n" +
+                "            \"category\": \"DoubleBed\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              136.50000000000003,\n" +
+                "              169.00000000000006,\n" +
+                "              185.50000000000003,\n" +
+                "              218.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"三人沙发\",\n" +
+                "            \"category\": \"ThreeSofa\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              417,\n" +
+                "              203.00000000000006,\n" +
+                "              455,\n" +
+                "              241.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"书桌\",\n" +
+                "            \"category\": \"Desk\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              218.5,\n" +
+                "              468.00000000000006,\n" +
+                "              287.50000000000006,\n" +
+                "              537.0000000000001\n" +
+                "            ],\n" +
+                "            \"name\": \"双人床\",\n" +
+                "            \"category\": \"DoubleBed\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              232.5,\n" +
+                "              160.00000000000006,\n" +
+                "              272.5,\n" +
+                "              200.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"书桌\",\n" +
+                "            \"category\": \"Desk\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              297,\n" +
+                "              171.00000000000006,\n" +
+                "              321,\n" +
+                "              195.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"椅子\",\n" +
+                "            \"category\": \"Chair\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              418.5,\n" +
+                "              181.00000000000006,\n" +
+                "              441.5,\n" +
+                "              204.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"椅子\",\n" +
+                "            \"category\": \"Chair\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              233.48909302398266,\n" +
+                "              122.51909302398272,\n" +
+                "              272.51090697601734,\n" +
+                "              161.5409069760174\n" +
+                "            ],\n" +
+                "            \"name\": \"地毯\",\n" +
+                "            \"category\": \"Carpet\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              398,\n" +
+                "              370,\n" +
+                "              549,\n" +
+                "              503\n" +
+                "            ],\n" +
+                "            \"name\": \"卧室\",\n" +
+                "            \"category\": \"Tag_bedroom\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              155,\n" +
+                "              423,\n" +
+                "              364,\n" +
+                "              587\n" +
+                "            ],\n" +
+                "            \"name\": \"卧室\",\n" +
+                "            \"category\": \"Tag_bedroom\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              499,\n" +
+                "              196,\n" +
+                "              633,\n" +
+                "              309\n" +
+                "            ],\n" +
+                "            \"name\": \"厨房\",\n" +
+                "            \"category\": \"Tag_kitchenroom\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              69,\n" +
+                "              104,\n" +
+                "              620,\n" +
+                "              279\n" +
+                "            ],\n" +
+                "            \"name\": \"客厅\",\n" +
+                "            \"category\": \"Tag_livingroom\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              540.3126453583378,\n" +
+                "              517.0000000000001,\n" +
+                "              530.1507146416621,\n" +
+                "              553.0000000000001\n" +
+                "            ],\n" +
+                "            \"name\": \"窗户\",\n" +
+                "            \"category\": \"BayWindow\"\n" +
+                "          },\n" +
+                "          {\n" +
+                "            \"bbox\": [\n" +
+                "              81.08604535833786,\n" +
+                "              110.00000000000006,\n" +
+                "              70.92411464166213,\n" +
+                "              298.00000000000006\n" +
+                "            ],\n" +
+                "            \"name\": \"窗户\",\n" +
+                "            \"category\": \"BayWindow\"\n" +
+                "          }\n" +
+                "        ],\n" +
+                "        \"floorsName\": \"1楼\"\n" +
+                "      }\n" +
+                "    ],\n" +
+                "    \"compass\": 0\n" +
+                "  }"; // 从文件或接口获取
+        JSONObject input = JSON.parseObject(jsonInput);
+        Floors floor = input.getJSONArray("floors").getObject(0, Floors.class);
+
+// 输出路径
+        BoxVisualizer.drawFloors(floor, "I:\\prox\\4dkankan-fusion\\output\\floor_visual.png", 1024, 1024);
+
+    }
+}

+ 97 - 0
src/main/java/com/fdkankan/fusion/common/ai/FloorHierarchy.java

@@ -0,0 +1,97 @@
+package com.fdkankan.fusion.common.ai;
+
+/**
+ * @author Xiewj
+ * @date 2025/4/16
+ */
+import java.util.*;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+
+class BoundingBox {
+    double xCenter, yCenter, width, height;
+    String name, category;
+
+    public BoundingBox(double xCenter, double yCenter, double width, double height, String name, String category) {
+        this.xCenter = xCenter;
+        this.yCenter = yCenter;
+        this.width = width;
+        this.height = height;
+        this.name = name;
+        this.category = category;
+    }
+
+    // 获取左上角和右下角坐标
+    public double getLeft() { return xCenter - width / 2; }
+    public double getRight() { return xCenter + width / 2; }
+    public double getTop() { return yCenter - height / 2; }
+    public double getBottom() { return yCenter + height / 2; }
+
+    // 判断是否包含另一个 bbox
+    public boolean contains(BoundingBox other) {
+        return this.getLeft() <= other.getLeft() &&
+                this.getRight() >= other.getRight() &&
+                this.getTop() <= other.getTop() &&
+                this.getBottom() >= other.getBottom();
+    }
+}
+
+public class FloorHierarchy {
+
+    public static void main(String[] args) {
+        // 输入数据
+        List<BoundingBox> boxes = Arrays.asList(
+                new BoundingBox(70, 104, 619, 279, "客厅", "Tag_livingroom"),
+                new BoundingBox(184, 221, 307, 275, "组合沙发", "CombinationSofa"),
+                new BoundingBox(76, 107, 84, 302, "窗户", "Window"),
+                new BoundingBox(399, 370, 549, 503, "卧室", "Tag_bedroom"),
+                new BoundingBox(452, 390, 528, 503, "双人床", "DoubleBed")
+        );
+
+        // 构建父子层级
+        Map<BoundingBox, List<BoundingBox>> hierarchy = new HashMap<>();
+        for (BoundingBox parent : boxes) {
+            hierarchy.put(parent, new ArrayList<>());
+            for (BoundingBox child : boxes) {
+                if (!parent.equals(child) && parent.contains(child)) {
+                    hierarchy.get(parent).add(child);
+                }
+            }
+        }
+
+        // 去重并构建树形结构
+        List<BoundingBox> topLevel = new ArrayList<>(boxes);
+        for (List<BoundingBox> children : hierarchy.values()) {
+            topLevel.removeAll(children);
+        }
+
+        // 转换为 JSON 输出
+        JSONObject result = new JSONObject();
+        JSONArray childrenArray = new JSONArray();
+
+        for (BoundingBox box : topLevel) {
+            childrenArray.add(buildJsonTree(box, hierarchy));
+        }
+
+        result.put("children", childrenArray);
+
+        // 输出结果
+        System.out.println(result.toJSONString());
+    }
+
+    private static JSONObject buildJsonTree(BoundingBox box, Map<BoundingBox, List<BoundingBox>> hierarchy) {
+        JSONObject node = new JSONObject();
+        node.put("name", box.name);
+        node.put("category", box.category);
+        node.put("bbox", Arrays.asList(box.xCenter, box.yCenter, box.width, box.height));
+
+        JSONArray childrenArray = new JSONArray();
+        for (BoundingBox child : hierarchy.get(box)) {
+            childrenArray.add(buildJsonTree(child, hierarchy));
+        }
+        node.put("children", childrenArray);
+
+        return node;
+    }
+}

+ 51 - 0
src/main/java/com/fdkankan/fusion/common/ai/FloorPlanChild.java

@@ -0,0 +1,51 @@
+package com.fdkankan.fusion.common.ai;
+
+/**
+ * @author Xiewj
+ * @date 2025/4/15
+ */
+public class FloorPlanChild {
+
+    private String bbox;
+    private String name;
+    private String category;
+
+    // Getters and setters
+    public String getBbox() {
+        return bbox;
+    }
+
+    public void setBbox(String bbox) {
+        this.bbox = bbox;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getCategory() {
+        return category;
+    }
+
+    public void setCategory(String category) {
+        this.category = category;
+    }
+
+    public FloorPlanChild( ) {
+    }
+
+    public FloorPlanChild(String bbox, String name, String category) {
+        this.bbox = bbox;
+        this.name = name;
+        this.category = category;
+    }
+    public FloorPlanChild(String bbox, String name) {
+        this.bbox = bbox;
+        this.name = name;
+        this.category = category;
+    }
+}

+ 17 - 0
src/main/java/com/fdkankan/fusion/common/ai/FloorPlanTag.java

@@ -0,0 +1,17 @@
+package com.fdkankan.fusion.common.ai;
+
+import lombok.Data;
+
+/**
+ * @author Xiewj
+ * @date 2025/4/15
+ */
+@Data
+public class FloorPlanTag {
+
+    private Double[] bbox;
+    private String name;
+    private String category;
+
+
+}

+ 5 - 191
src/main/java/com/fdkankan/fusion/common/ai/FloorUser.java

@@ -1,5 +1,7 @@
 package com.fdkankan.fusion.common.ai;
 
+import lombok.Data;
+
 import java.util.List;
 import java.util.Map;
 
@@ -7,197 +9,9 @@ import java.util.Map;
  * @author Xiewj
  * @date 2025/4/15
  */
-class FloorUser {
-    private List<Floor> floors;
+@Data
+public class FloorUser {
+    private List<Floors> floors;
     private Integer compass;
 
-    // Getters and setters
-    public List<Floor> getFloors() {
-        return floors;
-    }
-
-    public void setFloors(List<Floor> floors) {
-        this.floors = floors;
-    }
-
-    public Integer getCompass() {
-        return compass;
-    }
-
-    public void setCompass(Integer compass) {
-        this.compass = compass;
-    }
-}
-
-class Floor {
-    private String name;
-    private Map<String, Tag> tags;
-    private Map<String, Furniture> furnitures;
-
-    // Getters and setters
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public Map<String, Tag> getTags() {
-        return tags;
-    }
-
-    public void setTags(Map<String, Tag> tags) {
-        this.tags = tags;
-    }
-
-    public Map<String, Furniture> getFurnitures() {
-        return furnitures;
-    }
-
-    public void setFurnitures(Map<String, Furniture> furnitures) {
-        this.furnitures = furnitures;
-    }
-}
-
-class Tag {
-    private String bbox;
-    private String title;
-    private String geoType;
-
-    // Getters and setters
-    public String getBbox() {
-        return bbox;
-    }
-
-    public void setBbox(String bbox) {
-        this.bbox = bbox;
-    }
-
-    public String getTitle() {
-        return title;
-    }
-
-    public void setTitle(String title) {
-        this.title = title;
-    }
-
-    public String getGeoType() {
-        return geoType;
-    }
-
-    public void setGeoType(String geoType) {
-        this.geoType = geoType;
-    }
-}
-
-class Furniture {
-    private String bbox;
-    private String title;
-    private String geoType;
-
-    // Getters and setters
-    public String getBbox() {
-        return bbox;
-    }
-
-    public void setBbox(String bbox) {
-        this.bbox = bbox;
-    }
-
-    public String getTitle() {
-        return title;
-    }
-
-    public void setTitle(String title) {
-        this.title = title;
-    }
-
-    public String getGeoType() {
-        return geoType;
-    }
-
-    public void setGeoType(String geoType) {
-        this.geoType = geoType;
-    }
-}
-
-class Compass {
-    // Define the properties and methods of Compass
-}
-
-class Child {
-    private String bbox;
-    private String name;
-    private String category;
-
-    // Getters and setters
-    public String getBbox() {
-        return bbox;
-    }
-
-    public void setBbox(String bbox) {
-        this.bbox = bbox;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getCategory() {
-        return category;
-    }
-
-    public void setCategory(String category) {
-        this.category = category;
-    }
-
-    public Child( ) {
-    }
-
-    public Child(String bbox, String name, String category) {
-        this.bbox = bbox;
-        this.name = name;
-        this.category = category;
-    }
-    public Child(String bbox, String name) {
-        this.bbox = bbox;
-        this.name = name;
-        this.category = category;
-    }
 }
-
-class Result {
-    private List<Child> childrens;
-    private Integer compass;
-    private String floorname;
-
-    // Getters and setters
-    public List<Child> getChildrens() {
-        return childrens;
-    }
-
-    public void setChildrens(List<Child> childrens) {
-        this.childrens = childrens;
-    }
-
-    public Integer getCompass() {
-        return compass;
-    }
-
-    public void setCompass(Integer compass) {
-        this.compass = compass;
-    }
-
-    public String getFloorname() {
-        return floorname;
-    }
-
-    public void setFloorname(String floorname) {
-        this.floorname = floorname;
-    }
-}

+ 23 - 0
src/main/java/com/fdkankan/fusion/common/ai/Floors.java

@@ -0,0 +1,23 @@
+package com.fdkankan.fusion.common.ai;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Xiewj
+ * @date 2025/4/15
+ */
+@Data
+public class Floors {
+
+    private String imageWidth;
+    private String imageHeight;
+    private List<FloorPlanTag> shapes;
+    @JSONField(name="name")
+    private String floorsName;
+
+    // Getters and sette
+}

+ 113 - 112
src/main/java/com/fdkankan/fusion/common/ai/test.java

@@ -1,118 +1,119 @@
-package com.fdkankan.fusion.common.ai;
-
-import cn.hutool.core.io.FileUtil;
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
-import com.alibaba.fastjson.TypeReference;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * @author Xiewj
- * @date 2025/4/15
- */
-public class test {
-    public static void main(String[] args) throws IOException {
-        // 假设从某个地方获取 FloorUser 对象
-        FloorUser cad = getFloorUserFromJson("C:\\Users\\Admin\\Downloads\\floorplan1.json");
-
-        // 处理 cad.floors 数组,生成新的数组 res
-        List<Result> res = cad.getFloors().stream().map(floor -> {
-            // 初始化 childrens 数组,用于存储楼层中的子元素
-            List<Child> childrens = new ArrayList<>();
-
-            // 获取楼层的标签对象,如果不存在则使用空对象
-            Map<String, Tag> tag = floor.getTags() != null ? floor.getTags() : new HashMap<>();
-
-            // 获取楼层的家具对象,如果不存在则使用空对象
-            Map<String, Furniture> fur = floor.getFurnitures() != null ? floor.getFurnitures() : new HashMap<>();
-
-            // 遍历标签对象,将每个标签转换为 childrens 数组中的对象
-            for (Map.Entry<String, Tag> entry : tag.entrySet()) {
-                Tag item = entry.getValue();
-                childrens.add(new Child(item.getBbox(), item.getTitle(),item.getGeoType()));
-            }
-
-            // 遍历家具对象,将每个家具转换为 childrens 数组中的对象
-            for (Map.Entry<String, Furniture> entry : fur.entrySet()) {
-                Furniture item = entry.getValue();
-                childrens.add(new Child(item.getBbox(), item.getTitle(), item.getGeoType()));
-            }
-
-            // 返回处理后的楼层对象,包含 childrens 数组、指南针信息和楼层名称
-            Result result = new Result();
-            result.setChildrens(childrens);
-            result.setCompass(cad.getCompass());
-            result.setFloorname(floor.getName());
-            return result;
-        }).collect(Collectors.toList());
-
-        // 打印结果
-        System.out.println(JSONObject.toJSONString(res));
-    }
-
-    // 从 JSON 文件中读取 FloorUser 对象
-    private static FloorUser getFloorUserFromJson(String filePath) throws IOException {
-        String s = FileUtil.readUtf8String(filePath);
-        JSONObject jsonObject = JSON.parseObject(s);
-        FloorUser floorUser =  new FloorUser();
-        if (jsonObject.containsKey("floors")) {
-            JSONArray array = jsonObject.getJSONArray("floors");
-            List<Floor> floors=new ArrayList<>();
-            for (Object o : array) {
-                JSONObject a = JSON.parseObject(JSONObject.toJSON(o).toString());
-                Floor floor = JSONObject.toJavaObject(a, Floor.class);
-                System.out.println(floor);
-                floors.add(floor);
-            }
-            floorUser.setFloors(floors);
-        }
-        if (jsonObject.containsKey("compass")) {
-            System.out.println(jsonObject.getString("compass"));
-            floorUser.setCompass(jsonObject.getInteger("compass"));
-        }
-
-        return  floorUser;
-    }
-
-    // 模拟从 SDK 获取 FloorUser 对象,
-    //
-//    private static FloorUser getFloorUserFromSdk() {
-//        FloorUser cad = new FloorUser();
-//        cad.setCompass(new Compass());
+//package com.fdkankan.fusion.common.ai;
 //
-//        List<Floor> floors = new ArrayList<>();
-//        Floor floor = new Floor();
-//        floor.setName("Floor 1");
+//import cn.hutool.core.io.FileUtil;
+//import com.alibaba.fastjson.JSON;
+//import com.alibaba.fastjson.JSONArray;
+//import com.alibaba.fastjson.JSONObject;
 //
-//        Map<String, Tag> tags = new HashMap<>();
-//        Tag tag = new Tag();
-//        tag.setBbox("bbox1");
-//        tag.setTitle("Title1");
-//        tag.setGeoType("GeoType1");
-//        tags.put("tag1", tag);
+//import java.io.IOException;
+//import java.util.ArrayList;
+//import java.util.HashMap;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.stream.Collectors;
 //
-//        Map<String, Furniture> furnitures = new HashMap<>();
-//        Furniture fur = new Furniture();
-//        fur.setBbox("bbox2");
-//        fur.setTitle("Title2");
-//        fur.setGeoType("GeoType2");
-//        furnitures.put("fur1", fur);
+///**
+// * @author Xiewj
+// * @date 2025/4/15
+// */
+//public class test {
+//    public static void main(String[] args) throws IOException {
+//        List<Result> res = coverFloorplanJson();
 //
-//        floor.setTags(tags);
-//        floor.setFurnitures(furnitures);
-//        floors.add(floor);
+//        // 打印结果
+//        System.out.println(JSONObject.toJSONString(res));
+//    }
+//
+//    private static List<Result> coverFloorplanJson() throws IOException {
+//        // 假设从某个地方获取 FloorUser 对象
+//        FloorUser cad = getFloorUserFromJson("C:\\Users\\Admin\\Downloads\\floorplan1.json");
+//
+//        // 处理 cad.floors 数组,生成新的数组 res
+//        List<Result> res = cad.getFloors().stream().map(floor -> {
+//            // 初始化 children 数组,用于存储楼层中的子元素
+//            List<FloorPlanChild> children = new ArrayList<>();
+//
+//            // 获取楼层的标签对象,如果不存在则使用空对象
+//            Map<String, Tag> tag = floor.getTags() != null ? floor.getTags() : new HashMap<>();
+//
+//            // 获取楼层的家具对象,如果不存在则使用空对象
+//            Map<String, Furniture> fur = floor.getFurnitures() != null ? floor.getFurnitures() : new HashMap<>();
+//
+//            // 遍历标签对象,将每个标签转换为 children 数组中的对象
+//            for (Map.Entry<String, Tag> entry : tag.entrySet()) {
+//                Tag item = entry.getValue();
+//                children.add(new FloorPlanChild(item.getBbox(), item.getTitle(),item.getGeoType()));
+//            }
 //
-//        cad.setFloors(floors);
-//        return cad;
+//            // 遍历家具对象,将每个家具转换为 children 数组中的对象
+//            for (Map.Entry<String, Furniture> entry : fur.entrySet()) {
+//                Furniture item = entry.getValue();
+//                children.add(new FloorPlanChild(item.getBbox(), item.getTitle(), item.getGeoType()));
+//            }
+//
+//            // 返回处理后的楼层对象,包含 children 数组、指南针信息和楼层名称
+//            Result result = new Result();
+//            result.setChildrens(children);
+//            result.setCompass(cad.getCompass());
+//            result.setFloorname(floor.getName());
+//            return result;
+//        }).collect(Collectors.toList());
+//        return res;
 //    }
-}
+//
+//    // 从 JSON 文件中读取 FloorUser 对象
+//    private static FloorUser getFloorUserFromJson(String filePath) throws IOException {
+//        String s = FileUtil.readUtf8String(filePath);
+//        JSONObject jsonObject = JSON.parseObject(s);
+//        FloorUser floorUser =  new FloorUser();
+//        if (jsonObject.containsKey("floors")) {
+//            JSONArray array = jsonObject.getJSONArray("floors");
+//            List<Floors> floors=new ArrayList<>();
+//            for (Object o : array) {
+//                JSONObject a = JSON.parseObject(JSONObject.toJSON(o).toString());
+//                Floors floor = JSONObject.toJavaObject(a, Floors.class);
+//                System.out.println(floor);
+//                floors.add(floor);
+//            }
+//            floorUser.setFloors(floors);
+//        }
+//        if (jsonObject.containsKey("compass")) {
+//            System.out.println(jsonObject.getString("compass"));
+//            floorUser.setCompass(jsonObject.getInteger("compass"));
+//        }
+//
+//        return  floorUser;
+//    }
+//
+//    // 模拟从 SDK 获取 FloorUser 对象,
+//    //
+////    private static FloorUser getFloorUserFromSdk() {
+////        FloorUser cad = new FloorUser();
+////        cad.setCompass(new Compass());
+////
+////        List<Floors> floors = new ArrayList<>();
+////        Floors floor = new Floors();
+////        floor.setName("Floors 1");
+////
+////        Map<String, Tag> tags = new HashMap<>();
+////        Tag tag = new Tag();
+////        tag.setBbox("bbox1");
+////        tag.setTitle("Title1");
+////        tag.setGeoType("GeoType1");
+////        tags.put("tag1", tag);
+////
+////        Map<String, Furniture> furnitures = new HashMap<>();
+////        Furniture fur = new Furniture();
+////        fur.setBbox("bbox2");
+////        fur.setTitle("Title2");
+////        fur.setGeoType("GeoType2");
+////        furnitures.put("fur1", fur);
+////
+////        floor.setTags(tags);
+////        floor.setFurnitures(furnitures);
+////        floors.add(floor);
+////
+////        cad.setFloors(floors);
+////        return cad;
+////    }
+//}

+ 16 - 4
src/main/java/com/fdkankan/fusion/controller/AiController.java

@@ -1,9 +1,13 @@
 package com.fdkankan.fusion.controller;
 
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 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.util.Openai;
 import com.fdkankan.fusion.common.util.UploadToOssUtil;
 import com.fdkankan.fusion.config.FusionConfig;
@@ -14,10 +18,7 @@ import com.fdkankan.fusion.entity.CaseNumEntity;
 import com.fdkankan.fusion.exception.BusinessException;
 import com.fdkankan.fusion.request.AiParam;
 import com.fdkankan.fusion.response.FloorPathVo;
-import com.fdkankan.fusion.service.ICaseFilesService;
-import com.fdkankan.fusion.service.ICaseFilesTypeService;
-import com.fdkankan.fusion.service.ICaseInquestInfoService;
-import com.fdkankan.fusion.service.ICaseNumService;
+import com.fdkankan.fusion.service.*;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.ibatis.annotations.Param;
@@ -45,6 +46,17 @@ public class AiController {
 
     @Autowired
     FusionConfig fusionConfig;
+    @Autowired
+    AiService aiService;
+
+    @PostMapping("/test")
+    public ResultData test( ) throws IOException {
+        FloorUser floorPlanResults = aiService.coverFloorPlanJson("C:\\Users\\4DAGE\\Downloads\\floorplan-ai.json");
+//        BBoxHierarchy.buildHierarchy(floorPlanResults.getFloors());
+        JSONArray jsonArray = BBoxHierarchyBuilder.buildHierarchyStart(floorPlanResults.getFloors());
+        return ResultData.ok(jsonArray);
+    }
+
 
     @PostMapping("/getByImage")
     public ResultData getByImage(@RequestBody AiParam param){

+ 61 - 0
src/main/java/com/fdkankan/fusion/entity/SceneShapeEnum.java

@@ -0,0 +1,61 @@
+package com.fdkankan.fusion.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * 标注框模型表
+ *
+ * @author Xiewj
+ * @since 2023-11-09 11:53
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@TableName("t_scene_shape_enum")
+public class SceneShapeEnum {
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 属性名
+     */
+    private String name;
+
+    /**
+     * 类名
+     */
+    private String className;
+
+    /**
+     * 资源类型ID
+     */
+    private String resourceId;
+
+    /**
+     * 设备类型ID
+     */
+    private String typeId;
+
+    /**
+     * 记录的状态,A: 生效,I: 禁用
+     */
+    private String recStatus;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+}

+ 17 - 0
src/main/java/com/fdkankan/fusion/mapper/SceneShapeEnumMapper.java

@@ -0,0 +1,17 @@
+package com.fdkankan.fusion.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.fusion.entity.SceneShapeEnum;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Component;
+
+/**
+* 标注框模型表 Mapper
+*
+* @author Xiewj
+* @since 2023-11-09 11:53
+*/
+@Mapper
+@Component("SceneShapeEnumMapper")
+public interface SceneShapeEnumMapper extends BaseMapper<SceneShapeEnum> {
+}

+ 110 - 0
src/main/java/com/fdkankan/fusion/service/AiService.java

@@ -0,0 +1,110 @@
+package com.fdkankan.fusion.service;
+
+import cn.hutool.core.io.FileUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.fdkankan.fusion.common.ai.*;
+import com.fdkankan.fusion.entity.SceneShapeEnum;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Xiewj
+ * @date 2025/4/15
+ */
+@Service
+@DS("db1")
+public class AiService {
+
+    @Autowired
+    private SceneShapeEnumService sceneShapeEnumService;
+
+    public void main() throws IOException {
+        // 主方法保留,用于测试或其他用途
+        coverFloorPlanJson("C:\\Users\\4DAGE\\Downloads\\floorplan1.json");
+    }
+
+    /**
+     * 转换楼层计划 JSON 数据
+     *
+     * @param path 输入文件路径
+     * @return 转换后的 FloorPlanResult 列表
+     * @throws IOException 如果文件读取失败
+     */
+    public FloorUser coverFloorPlanJson(String path) throws IOException {
+        if (path == null || path.isEmpty()) {
+            throw new IllegalArgumentException("路径不能为空");
+        }
+        // 获取 SceneShapeEnum 列表并生成映射
+        Map<String, String> nameToClassNameMap = new HashMap<>();
+        Map<String, String> classNameToNameMap = new HashMap<>();
+        buildMaps(sceneShapeEnumService.list(), nameToClassNameMap, classNameToNameMap);
+        // 从 JSON 文件中获取 FloorUser 对象
+        FloorUser cad = getFloorUserFromJson(path,nameToClassNameMap,classNameToNameMap);
+
+        // 处理 cad.floors 数组,生成新的数组 res
+        return cad;
+    }
+
+    /**
+     * 构建名称到类名和类名到名称的映射
+     *
+     * @param list SceneShapeEnum 列表
+     * @param nameToClassNameMap 名称到类名的映射
+     * @param classNameToNameMap 类名到名称的映射
+     */
+    private void buildMaps(List<SceneShapeEnum> list, Map<String, String> nameToClassNameMap, Map<String, String> classNameToNameMap) {
+        for (SceneShapeEnum item : list) {
+            nameToClassNameMap.put(item.getName(), item.getClassName());
+            classNameToNameMap.put(item.getClassName(), item.getName());
+        }
+    }
+
+
+    /**
+     * 从 JSON 文件中读取 FloorUser 对象
+     *
+     * @param filePath           文件路径
+     * @param nameToClassNameMap
+     * @param classNameToNameMap
+     * @return FloorUser 对象
+     * @throws IOException 如果文件读取失败
+     */
+    private static FloorUser getFloorUserFromJson(String filePath, Map<String, String> nameToClassNameMap, Map<String, String> classNameToNameMap) throws IOException {
+        String content = FileUtil.readUtf8String(filePath);
+        JSONObject jsonObject = JSON.parseObject(content);
+
+        FloorUser floorUser = new FloorUser();
+        // 处理 floors 字段
+        if (jsonObject.containsKey("floors")) {
+            JSONArray floors = jsonObject.getJSONArray("floors");
+            List<Floors> floors1 = floors.toJavaList(Floors.class);
+            for (Floors floors2 : floors1) {
+                floors2.getShapes().forEach(shape -> {
+                    if (shape.getCategory().equalsIgnoreCase("Tag")){
+                        shape.setCategory(nameToClassNameMap.get(shape.getName()));
+                    }else {
+                        shape.setName(classNameToNameMap.get(shape.getCategory()));
+                    }
+                });
+            }
+
+            floorUser.setFloors(floors1);
+        }
+
+        // 处理 compass 字段
+        if (jsonObject.containsKey("compass")) {
+            floorUser.setCompass(jsonObject.getInteger("compass"));
+        }
+
+        return floorUser;
+    }
+}

+ 17 - 0
src/main/java/com/fdkankan/fusion/service/SceneShapeEnumService.java

@@ -0,0 +1,17 @@
+package com.fdkankan.fusion.service;
+
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.fusion.entity.SceneShapeEnum;
+
+/**
+ * 标注框模型表 服务类接口
+ *
+ * @author Xiewj
+ * @since 2023-11-09 11:53
+ */
+public interface SceneShapeEnumService extends IService<SceneShapeEnum> {
+
+      SceneShapeEnum findByClassName(String className);
+}

+ 26 - 0
src/main/java/com/fdkankan/fusion/service/impl/SceneShapeEnumServiceImpl.java

@@ -0,0 +1,26 @@
+package com.fdkankan.fusion.service.impl;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.fusion.entity.SceneShapeEnum;
+import com.fdkankan.fusion.mapper.SceneShapeEnumMapper;
+import com.fdkankan.fusion.service.SceneShapeEnumService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 标注框模型表 服务实现类
+ *
+ * @author Xiewj
+ * @since 2023-11-09 11:53
+ */
+@Service
+@DS("db2")
+public class SceneShapeEnumServiceImpl extends ServiceImpl<SceneShapeEnumMapper, SceneShapeEnum> implements SceneShapeEnumService {
+    @Override
+    public SceneShapeEnum findByClassName(String className) {
+        return this.getOne(new LambdaQueryWrapper<SceneShapeEnum>().eq(SceneShapeEnum::getClassName, className));
+    }
+
+
+}