-
Notifications
You must be signed in to change notification settings - Fork 4
/
map2D.gd
195 lines (148 loc) · 5.16 KB
/
map2D.gd
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
tool
extends "intersections2D.gd"
# Declare member variables here. Examples:
# navigation
var ast = null
var nav = null
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
func setup_navi(samples, edges, mult=1, poisson=false):
setup_neighbors(samples, edges, mult)
nav = AStar.new()
var pts = []
var begin_id = 0
var roads_start_id = samples.size()-1 + 1
print("Roads_start_id " + str(roads_start_id))
var path_look = {}
for i in range(roads_start_id, roads_start_id+5): #samples.size()-1):
var data = setup_nav_astar(pts, i, begin_id, poisson)
#print('Begin: ' + str(begin_id) + " end: " + str(data[0]) + " inters: " + str(data[1]))
#path_data.append([data[1], [begin_id, data[0]]])
if data:
path_look[data[2]] = [begin_id, data[0]]
# just in case, map inverse too
path_look[[data[2][1], data[2][0]]] = [data[0], begin_id]
# increment begin_id
begin_id = data[1]+1
print(path_look)
if path_look.size() > 0:
# test (get path_look entry at id x)
var test = path_look[path_look.keys()[3]]
#print("Test: " + str(test))
var nav_path = nav.get_point_path(test[0], test[1])
# print("Nav path: " + str(nav_path))
var nav_path2d = PoolVector2Array()
for i in range(nav_path.size()):
# put in a 2d equivalent
nav_path2d.append(_3tov2(nav_path[i]))
# visualize
var node = Node2D.new()
var script = load("res://path_visualizer.gd")
node.set_script(script)
add_child(node)
node.set_name("Visualizer")
node.path = nav_path2d
# print(str(node.path))
node.update()
#-------------------------
# Distance map
func setup_neighbors(samples, edges, mult=1):
# we'll use AStar to have an easy map of neighbors
ast = AStar.new()
for i in range(0,samples.size()-1):
ast.add_point(i, Vector3(samples[i][0]*mult, 0, samples[i][1]*mult))
for i in range(0, edges.size()):
var ed = edges[i]
ast.connect_points(ed[0], ed[1])
# yes it could be more efficient I guess
func bfs_distances(start):
# keep track of all visited nodes
#var explored = []
var distance = {}
distance[start] = 0
# keep track of nodes to be checked
var queue = [start]
# keep looping until there are nodes still to be checked
while queue:
# pop shallowest node (first node) from queue
var node = queue.pop_front()
#print("Visiting... " + str(node))
var neighbours = ast.get_point_connections(node)
# add neighbours of node to queue
for neighbour in neighbours:
# if not visited
#if not explored.has(neighbour):
if not distance.has(neighbour):
queue.append(neighbour)
distance[neighbour] = 1 + distance[node]
return distance
# ----------------
func _3tov2(vec3):
return Vector2(vec3.x, vec3.z)
func _posto3d(pos):
return Vector3(pos.x, 0, pos.y)
func setup_nav_astar(pts, i, begin_id, poisson=true):
# catch any errors
if i >= get_child_count():
print("No child at index : " + str(i))
return
#print(get_child(i).get_name())
# extract intersection id's
var sub = get_child(i).get_name().substr(5, 3)
var nrs = sub.split("-")
var ret = []
if poisson:
for i in nrs:
# because of the poisson node that comes first
ret.append(int(i)-1)
else:
ret = nrs
print(get_child(i).get_name() + " real numbers: " + str(ret))
if not get_child(i).has_node("Road_instance 0"):
return
if not get_child(i).has_node("Road_instance 1"):
return
var turn1 = get_child(i).get_node("Road_instance 0").get_child(0).get_child(0)
var turn2 = get_child(i).get_node("Road_instance 1").get_child(0).get_child(0)
#print("Straight points_arc: " + str(get_child(i).get_node("Spatial0").get_child(0).points_arc))
#print("Turn 1 points_arc: " + str(turn1.points_arc))
#print("Turn 2 points_arc: " + str(turn2.points_arc))
#print("Turn 1 global pos: " + str(turn1.get_global_transform().origin))
#print("Turn 2 global pos: " + str(turn2.get_global_transform().origin))
# from local to global
for i in range(0,turn1.points_arc.size()):
var p = turn1.points_arc[i]
# Astar wants 3d points
pts.append(_posto3d(turn1.to_global(p)))
#print(pts)
for i in range(0,turn2.points_arc.size()):
var p = turn2.points_arc[i]
pts.append(_posto3d(turn2.to_global(p)))
#print("With turn2: " + str(pts))
# add pts to nav (road-level AStar)
for i in range(pts.size()):
nav.add_point(i, pts[i])
#print(nav.get_points())
# connect the points
var turn1_end = begin_id + turn1.points_arc.size()-1
# because of i+1
for i in range(begin_id, turn1_end):
nav.connect_points(i, i+1)
var turn2_end = begin_id + turn1.points_arc.size()+turn2.points_arc.size()-1
for i in range(begin_id + turn1.points_arc.size(), turn2_end):
nav.connect_points(i, i+1)
# because turn 2 is inverted
# connect the endpoints
nav.connect_points(turn1_end, turn2_end)
# full path
var endpoint_id = begin_id + turn1.points_arc.size() # beginning of turn2
var last_id = turn2_end
# turn1
#var endpoint_id = turn1_end
#print("Endpoint id " + str(endpoint_id))
#print("Test: " + str(nav.get_point_path(begin_id, endpoint_id)))
# turn2 only
#print("Test 2: " + str(nav.get_point_path(begin_id + turn1.points_arc.size(), turn2_end)))
# road's end, list end, intersections
return [endpoint_id, last_id, ret]