-
-
Notifications
You must be signed in to change notification settings - Fork 207
/
PathFindingEdge.vue
110 lines (96 loc) 路 3.17 KB
/
PathFindingEdge.vue
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
<script lang="ts" setup>
import type { Position } from '@vue-flow/core'
import { BezierEdge, EdgeText, getSimpleBezierPath, useVueFlow } from '@vue-flow/core'
import type { PathFindingEdgeProps } from '../types'
import { createGrid, gridRatio } from './createGrid'
import { drawSmoothLinePath } from './drawSvgPath'
import { generatePath } from './generatePath'
import { getBoundingBoxes } from './getBoundingBoxes'
import { gridToGraphPoint } from './pointConversion'
const props = withDefaults(defineProps<PathFindingEdgeProps>(), {
selected: false,
sourcePosition: 'bottom' as Position,
targetPosition: 'top' as Position,
labelStyle: () => ({}),
labelShowBg: true,
labelBgStyle: () => ({}),
})
const nodePadding = 10
const graphPadding = 20
const roundCoordinatesTo = gridRatio
const { getNodes } = useVueFlow()
const centered = computed(() =>
getSimpleBezierPath({
...props,
}),
)
const source = computed(() => ({
x: props.sourceX,
y: props.sourceY,
position: props.sourcePosition,
}))
const target = computed(() => ({
x: props.targetX,
y: props.targetY,
position: props.targetPosition,
}))
// We use the nodes' information to generate bounding boxes for them
// and the graph
const bb = computed(() => getBoundingBoxes(getNodes.value, nodePadding, graphPadding, roundCoordinatesTo))
const gridPath = computed(() => {
let path: number[][] = []
if (target.value.x && source.value.x && getNodes.value.length) {
// We then can use the grid representation to do pathfinding
// With this information, we can create a 2D grid representation of
// our graph, that tells us where in the graph there is a "free" space or not
const { grid, start, end } = createGrid(bb.value.graph, bb.value.nodes, source.value, target.value)
path = generatePath(grid, start, end)
}
return path
})
const path = computed(() => {
let svgPath = ''
if (gridPath.value?.length) {
// Here we convert the grid path to a sequence of graph coordinates.
const graphPath = gridPath.value.map((gridPoint) => {
const [x, y] = gridPoint
const graphPoint = gridToGraphPoint({ x, y }, bb.value.graph.xMin, bb.value.graph.yMin)
return [graphPoint.x, graphPoint.y]
})
// Finally, we can use the graph path to draw the edge
svgPath = drawSmoothLinePath(source.value, target.value, graphPath)
}
return svgPath
})
const attrs: any = useAttrs()
</script>
<script lang="ts">
export default {
name: 'PathFindingEdge',
compatConfig: { MODE: 3 },
inheritAttrs: false,
}
</script>
<template>
<BezierEdge v-if="gridPath && gridPath.length <= 2" v-bind="{ ...props, ...attrs }" />
<template v-else>
<path
:style="{ ...props.style, ...attrs.style }"
class="vue-flow__edge-path"
:d="path"
:marker-end="props.markerEnd"
:marker-start="props.markerStart"
/>
<EdgeText
v-if="props.label"
:x="centered[1]"
:y="centered[2]"
:label="props.label"
:label-style="props.labelStyle"
:label-show-bg="props.labelShowBg"
:label-bg-style="props.labelBgStyle"
:label-bg-padding="props.labelBgPadding"
:label-bg-border-radius="props.labelBgBorderRadius"
/>
</template>
</template>