chingu-pathfinding 1.1.2 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/chingu_pathfinding/chingu_pathfinding.cpp +57 -44
- data/ext/chingu_pathfinding/extconf.rb +1 -0
- data/lib/chingu_pathfinding.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: acbba82b0ce19c59d1968606277fca2f0ce65794
|
4
|
+
data.tar.gz: 3d4aa10838504fa9ce82a7116fcca2afe3a35868
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ba0c8c9f2905de61d1c7491fd222a073b0dc161221dc772ca6803e593d497641e46a666a7f05aa7bb97591293e678c67046616f7fd53a408ec5b768e5188898
|
7
|
+
data.tar.gz: 42bd5a22cc0b2ea8cb93b25d78e1fdd66fdc820e6c096a73fc9e86f2216a719cafc5904d65feb81e7cc20992e7233996a138f4b35120a6fec685654e9c5ff2e2
|
@@ -1,9 +1,9 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
#include <math.h>
|
3
3
|
#include <vector>
|
4
|
-
#include <
|
4
|
+
#include <unordered_map>
|
5
5
|
#include <queue>
|
6
|
-
#include <
|
6
|
+
#include <unordered_set>
|
7
7
|
#include <iostream>
|
8
8
|
#include <algorithm>
|
9
9
|
#include <functional>
|
@@ -19,16 +19,30 @@ extern "C" {
|
|
19
19
|
}
|
20
20
|
}
|
21
21
|
|
22
|
-
|
22
|
+
namespace std {
|
23
|
+
template<typename a, typename b>
|
24
|
+
struct hash< std::pair<a, b> > {
|
25
|
+
private:
|
26
|
+
const hash<a> ah;
|
27
|
+
const hash<b> bh;
|
28
|
+
public:
|
29
|
+
hash() : ah(), bh() {}
|
30
|
+
size_t operator()(const std::pair<a, b> &p) const {
|
31
|
+
return ah(p.first) ^ bh(p.second) << 5 ^ bh(p.second);
|
32
|
+
}
|
33
|
+
};
|
34
|
+
}
|
35
|
+
|
36
|
+
inline int dir(const int a, const int b) {
|
23
37
|
if (a == b) return 0;
|
24
38
|
if (a < b) return 1;
|
25
39
|
return -1;
|
26
40
|
}
|
27
41
|
|
28
42
|
struct point_t {
|
29
|
-
|
43
|
+
int x, y;
|
30
44
|
bool valid;
|
31
|
-
point_t(
|
45
|
+
point_t(int xx, int yy) {
|
32
46
|
x = xx;
|
33
47
|
y = yy;
|
34
48
|
valid = true;
|
@@ -36,7 +50,7 @@ struct point_t {
|
|
36
50
|
point_t() : x(0), y(0), valid(false) { }
|
37
51
|
point_t(const point_t& p) : x(p.x), y(p.y), valid(p.valid) { }
|
38
52
|
};
|
39
|
-
typedef std::pair<
|
53
|
+
typedef std::pair<int, int> location_t;
|
40
54
|
|
41
55
|
float dist(const location_t& a, const location_t& b) {
|
42
56
|
float dx = a.first-b.first;
|
@@ -45,19 +59,19 @@ float dist(const location_t& a, const location_t& b) {
|
|
45
59
|
}
|
46
60
|
|
47
61
|
class path_t {
|
48
|
-
std::
|
49
|
-
std::
|
62
|
+
std::unordered_map< location_t, point_t >* map_p;
|
63
|
+
std::unordered_multimap< location_t, location_t >* connectivity_p;
|
50
64
|
float cost_paid;
|
51
65
|
|
52
66
|
public:
|
53
67
|
std::vector<location_t> path;
|
54
|
-
path_t() : cost_paid(0) { }
|
68
|
+
path_t() : cost_paid(0), map_p(NULL), connectivity_p(NULL) { }
|
55
69
|
path_t(const path_t& p) : map_p(p.map_p), connectivity_p(p.connectivity_p), path(p.path), cost_paid(p.cost_paid) { }
|
56
|
-
path_t(std::
|
57
|
-
std::
|
70
|
+
path_t(std::unordered_map< location_t, point_t >* mm,
|
71
|
+
std::unordered_multimap< location_t, location_t >* cc)
|
58
72
|
: map_p(mm), connectivity_p(cc), cost_paid(0), path() { }
|
59
73
|
float get_cost_paid() const { return cost_paid; }
|
60
|
-
void add_loc(location_t l, const location_t& goal) {
|
74
|
+
void add_loc(const location_t& l, const location_t& goal) {
|
61
75
|
if (!path.empty()) {
|
62
76
|
location_t last = *path.crbegin();
|
63
77
|
cost_paid += dist(last, l);
|
@@ -87,23 +101,23 @@ class by_estimated_cost {
|
|
87
101
|
|
88
102
|
|
89
103
|
class pathfinder_t {
|
90
|
-
std::
|
91
|
-
std::
|
92
|
-
|
104
|
+
std::unordered_map< location_t, point_t > map; // Spartial hashing
|
105
|
+
std::unordered_multimap< location_t, location_t > connectivity; // sparse connectivity
|
106
|
+
int height, width, block_size;
|
93
107
|
ID blocked_method;
|
94
108
|
VALUE self;
|
95
109
|
|
96
|
-
bool is_blocked(const
|
110
|
+
bool is_blocked(const int x, const int y) {
|
97
111
|
VALUE blocked = rb_funcall(self, blocked_method, 2, INT2NUM(x), INT2NUM(y));
|
98
112
|
return blocked != Qfalse && blocked != Qnil;
|
99
113
|
}
|
100
114
|
|
101
|
-
bool line_blocked(const
|
115
|
+
bool line_blocked(const int x1, const int y1, const int x2, const int y2) {
|
102
116
|
if (block_size == 1) return false;
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
117
|
+
int dx = dir(x1, x2);
|
118
|
+
int dy = dir(y1, y2);
|
119
|
+
int runner_x = x1;
|
120
|
+
int runner_y = y1;
|
107
121
|
while (runner_x * dx <= x2 * dx &&
|
108
122
|
runner_y * dy <= y2 * dy) {
|
109
123
|
if (is_blocked(runner_x, runner_y)) {
|
@@ -116,11 +130,11 @@ class pathfinder_t {
|
|
116
130
|
}
|
117
131
|
|
118
132
|
typedef std::priority_queue<path_t, std::vector<path_t>, by_estimated_cost> queue_t;
|
119
|
-
path_t find_path_internal(queue_t queue, location_t goal) {
|
120
|
-
std::
|
133
|
+
path_t find_path_internal(queue_t& queue, location_t& goal) {
|
134
|
+
std::unordered_set<location_t> visited;
|
121
135
|
while (!queue.empty()) {
|
122
136
|
path_t current = queue.top();
|
123
|
-
location_t end = current.end();
|
137
|
+
const location_t& end = current.end();
|
124
138
|
queue.pop();
|
125
139
|
if (visited.find(end) != visited.end()) continue;
|
126
140
|
visited.insert(end);
|
@@ -136,7 +150,7 @@ class pathfinder_t {
|
|
136
150
|
if (visited.find(to) != visited.end()){
|
137
151
|
continue;
|
138
152
|
}
|
139
|
-
path_t new_path
|
153
|
+
path_t new_path(current);
|
140
154
|
new_path.add_loc(to, goal);
|
141
155
|
queue.push(new_path);
|
142
156
|
}
|
@@ -145,14 +159,14 @@ class pathfinder_t {
|
|
145
159
|
}
|
146
160
|
|
147
161
|
public:
|
148
|
-
path_t find_path(
|
162
|
+
path_t find_path(int x1, int y1, int x2, int y2) {
|
149
163
|
location_t start(x1,y1);
|
150
164
|
location_t goal(x2,y2);
|
151
165
|
by_estimated_cost estimator(goal);
|
152
166
|
queue_t queue(estimator);
|
153
167
|
path_t init_path(&map, &connectivity);
|
154
|
-
|
155
|
-
|
168
|
+
int next_node_x = (x1 / block_size)*block_size + block_size/2;
|
169
|
+
int next_node_y = (y1 / block_size)*block_size + block_size/2;
|
156
170
|
init_path.add_loc(start, goal);
|
157
171
|
location_t start_block(next_node_x, next_node_y);
|
158
172
|
if (start != start_block) {
|
@@ -162,7 +176,7 @@ class pathfinder_t {
|
|
162
176
|
return find_path_internal(queue, goal);
|
163
177
|
}
|
164
178
|
|
165
|
-
path_t find_path_update(
|
179
|
+
path_t find_path_update(int x1, int y1, int x2, int y2, std::vector<location_t> current) {
|
166
180
|
location_t start(x1,y1);
|
167
181
|
location_t goal(x2,y2);
|
168
182
|
path_t init_path;
|
@@ -190,15 +204,17 @@ class pathfinder_t {
|
|
190
204
|
return find_path_internal(queue, goal);
|
191
205
|
}
|
192
206
|
|
193
|
-
void Init(VALUE self,
|
207
|
+
void Init(VALUE self, int width, int height, int block_size) {
|
194
208
|
this->width = width;
|
195
209
|
this->height = height;
|
196
210
|
this->block_size = block_size;
|
197
211
|
this->self = self;
|
212
|
+
this->map.reserve(width/block_size * height/block_size);
|
213
|
+
this->connectivity.reserve(width/block_size * height/block_size*4);
|
198
214
|
blocked_method = rb_intern("blocked?");
|
199
215
|
// Build internal map:
|
200
|
-
for (
|
201
|
-
for (
|
216
|
+
for (int x = block_size/2; x < width; x += block_size) {
|
217
|
+
for (int y = block_size/2; y < height; y += block_size) {
|
202
218
|
// add point if it is not blocked
|
203
219
|
if (is_blocked(x, y)) continue;
|
204
220
|
auto cur_loc = location_t(x,y);
|
@@ -236,20 +252,19 @@ class pathfinder_t {
|
|
236
252
|
}
|
237
253
|
}
|
238
254
|
}
|
239
|
-
// print_map();
|
240
255
|
} // END Init
|
241
256
|
|
242
257
|
std::string print_map() {
|
243
258
|
// DEBUGGING
|
244
259
|
|
245
|
-
auto mapp = std::
|
246
|
-
for (
|
247
|
-
for (
|
260
|
+
auto mapp = std::unordered_map<location_t, char>();
|
261
|
+
for (int x = 0; x < width; x++) {
|
262
|
+
for (int y = 0; y < height; y++) {
|
248
263
|
mapp[location_t(x, y)] = ' ';
|
249
264
|
}
|
250
265
|
}
|
251
|
-
for (
|
252
|
-
for (
|
266
|
+
for (int x = block_size/2; x < width; x += block_size) {
|
267
|
+
for (int y = block_size/2; y < height; y += block_size) {
|
253
268
|
if (!map[location_t(x, y)].valid) {
|
254
269
|
mapp[location_t(x, y)] = '~';
|
255
270
|
continue;
|
@@ -269,9 +284,9 @@ class pathfinder_t {
|
|
269
284
|
}
|
270
285
|
std::stringstream out;
|
271
286
|
out << "map:";
|
272
|
-
for (
|
287
|
+
for (int y = 0; y < height; y++) {
|
273
288
|
out << std::endl;
|
274
|
-
for (
|
289
|
+
for (int x = 0; x < width; x++) {
|
275
290
|
out << mapp[location_t(x, y)];
|
276
291
|
}
|
277
292
|
}
|
@@ -293,8 +308,6 @@ static VALUE alloc_pathfinder(VALUE klass) {
|
|
293
308
|
|
294
309
|
static VALUE init(VALUE self, VALUE width_a, VALUE height_a, VALUE block_size_a) {
|
295
310
|
pathfinder_t* pf;
|
296
|
-
long int width, height, block_size;
|
297
|
-
long int x, y;
|
298
311
|
Data_Get_Struct(self, pathfinder_t, pf);
|
299
312
|
pf->Init(self, NUM2INT(width_a), NUM2INT(height_a), NUM2INT(block_size_a));
|
300
313
|
return self;
|
@@ -320,8 +333,8 @@ static VALUE find_path_update(VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2
|
|
320
333
|
std::vector<location_t> p;
|
321
334
|
for (int i = 0; i < len; i++) {
|
322
335
|
VALUE pt = rb_ary_shift(prev);
|
323
|
-
|
324
|
-
|
336
|
+
int x = NUM2INT(rb_ary_shift(pt));
|
337
|
+
int y = NUM2INT(rb_ary_shift(pt));
|
325
338
|
p.push_back(location_t(x, y));
|
326
339
|
}
|
327
340
|
path_t path = pf->find_path_update(NUM2INT(x1), NUM2INT(y1), NUM2INT(x2), NUM2INT(y2), p);
|
data/lib/chingu_pathfinding.rb
CHANGED