#
luxiaotao1123
2024-10-24 28d9ed7bc5749bf0b20b537344573b79e142ff59
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package com.zy.acs.manager.core;
 
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zy.acs.common.utils.GsonUtils;
import com.zy.acs.framework.common.R;
import com.zy.acs.framework.common.SnowflakeIdWorker;
import com.zy.acs.manager.core.domain.Lane;
import com.zy.acs.manager.manager.entity.Code;
import com.zy.acs.manager.manager.entity.Route;
import com.zy.acs.manager.manager.service.CodeService;
import com.zy.acs.manager.manager.service.RouteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * Created by vincent on 10/24/2024
 */
@RestController
@RequestMapping("/test")
public class DispatcherTestController {
 
    @Autowired
    private CodeService codeService;
    @Autowired
    private RouteService routeService;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
 
    @GetMapping("/dfs")
    public R dfs() {
        List<Lane> lanes = new ArrayList<>();
        List<Code> codeList = codeService.list(new LambdaQueryWrapper<Code>().eq(Code::getStatus, 1));
        Map<String, List<String>> adjacencyCodeMap = new HashMap<>();
        for (Code code : codeList) {
            List<Long> adjacencyNode = routeService.getAdjacencyNode(code.getId());
            adjacencyCodeMap.put(code.getData(), adjacencyNode.stream().map(node -> {
                return codeService.getById(node).getData();
            }).collect(Collectors.toList()));
        }
        List<String> codeDataList = codeList.stream().map(Code::getData).collect(Collectors.toList());
        System.out.println(codeDataList.toString());
        System.out.println(adjacencyCodeMap.toString());
 
 
        Set<String> visited = new HashSet<>();
 
        // 遍历所有节点,寻找度数不等于2的节点作为起点
        for (String codeData : codeDataList) {
            if (adjacencyCodeMap.getOrDefault(codeData, Collections.emptyList()).size() != 2) {
                List<String> neighbors = adjacencyCodeMap.getOrDefault(codeData, Collections.emptyList());
                for (String neighbor : neighbors) {
                    // 仅遍历度数为2且未被访问的邻居
                    if (adjacencyCodeMap.getOrDefault(neighbor, Collections.emptyList()).size() == 2 && !visited.contains(neighbor)) {
                        Lane lane = new Lane(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
                        dfsCalc(neighbor, codeData, lane, visited, adjacencyCodeMap);
                        lanes.add(lane);
                    }
                }
            }
        }
 
        // 处理度数为2且连接两个拐弯点的节点(独立巷道)
        for (String codeData : codeDataList) {
            if (adjacencyCodeMap.getOrDefault(codeData, Collections.emptyList()).size() == 2 && !visited.contains(codeData)) {
                List<String> neighbors = adjacencyCodeMap.getOrDefault(codeData, Collections.emptyList());
                boolean connectedToTwoTurningPoints = true;
                for (String neighbor : neighbors) {
                    if (adjacencyCodeMap.getOrDefault(neighbor, Collections.emptyList()).size() == 2) {
                        connectedToTwoTurningPoints = false;
                        break;
                    }
                }
                if (connectedToTwoTurningPoints) {
                    Lane lane = new Lane(String.valueOf(snowflakeIdWorker.nextId()).substring(3));
                    lane.getCodes().add(codeData);
                    lanes.add(lane);
                    visited.add(codeData);
                }
            }
        }
 
 
        System.out.println(GsonUtils.toJson(lanes));
        return R.ok().add(lanes);
    }
 
 
    private void dfsCalc(String code, String parent, Lane lane, Set<String> visited, Map<String, List<String>> adjacencyCodeMap) {
        // 检查当前节点的度数是否为2
        if (adjacencyCodeMap.getOrDefault(code, Collections.emptyList()).size() != 2) {
            // 不包含拐弯点
            return;
        }
 
        // 标记为已访问并加入巷道
        visited.add(code);
        lane.getCodes().add(code);
 
        List<String> neighbors = adjacencyCodeMap.get(code);
        if (neighbors == null || neighbors.isEmpty()) {
            return;
        }
 
        for (String neighbor : neighbors) {
            if (neighbor.equals(parent)) {
                continue;
            }
 
            if (adjacencyCodeMap.getOrDefault(neighbor, Collections.emptyList()).size() == 2 && !visited.contains(neighbor)) {
                // 检查方向是否一致
                if (isSameDirection(code, neighbor, parent)) {
                    dfsCalc(neighbor, code, lane, visited, adjacencyCodeMap);
                }
            }
        }
    }
 
    public boolean isSameDirection(String code, String neighbor, String parent) {
        if (parent == null) {
            return true;
        }
 
        Code parentCode = codeService.selectByData(parent);
        Code currentCode = codeService.selectByData(code);
        Code neighborCode = codeService.selectByData(neighbor);
 
        double direction1 = calculateDirection(parentCode, currentCode);
        double direction2 = calculateDirection(currentCode, neighborCode);
        double angleDifference = Math.abs(direction1 - direction2);
 
        // 规范化角度差
        angleDifference = Math.min(angleDifference, 2 * Math.PI - angleDifference);
 
        // 设置角度差阈值为3度
        return angleDifference < Math.toRadians(3);
    }
 
    public double calculateDirection(Code from, Code to) {
        double deltaX = to.getX() - from.getX();
        double deltaY = to.getY() - from.getY();
        return Math.atan2(deltaY, deltaX);
    }
 
 
}