188# define JPS_ASSERT(cond) assert(cond)
190# define JPS_ASSERT(cond)
196#if !defined(JPS_realloc) || !defined(JPS_free)
199# define JPS_realloc(p, newsize, oldsize, user) realloc(p, newsize)
202# define JPS_free(p, oldsize, user) free(p)
207#define JPS_HEURISTIC_ACCURATE(a, b) (Heuristic::Chebyshev(a, b))
212# define JPS_sqrt(x) sqrtf(float(x))
222#ifndef JPS_HEURISTIC_ACCURATE
223#define JPS_HEURISTIC_ACCURATE(a, b) (Heuristic::Euclidean(a, b))
226#ifndef JPS_HEURISTIC_ESTIMATE
227#define JPS_HEURISTIC_ESTIMATE(a, b) (Heuristic::Manhattan(a, b))
304#define JPS_PLACEMENT_NEW(p) new(JPS__NewDummy(), p)
315 return x == p.
x &&
y == p.
y;
319 return x != p.
x ||
y != p.
y;
338 template<
typename T>
inline static T Max(T a, T b) {
return a < b ? b : a; }
339 template<
typename T>
inline static T Min(T a, T b) {
return a < b ? a : b; }
340 template<
typename T>
inline static T Abs(T a) {
return a < T(0) ? -a : a; }
341 template<
typename T>
inline static int Sgn(T val) {
return (T(0) < val) - (val < T(0)); }
349 const int dx = Abs(
int(a.
x - b.
x));
350 const int dy = Abs(
int(a.
y - b.
y));
356 const int dx = Abs(
int(a.
x - b.
x));
357 const int dy = Abs(
int(a.
y - b.
y));
358 return static_cast<ScoreType>(Max(dx, dy));
363 const int dx = (int(a.
x - b.
x));
364 const int dy = (int(a.
y - b.
y));
365 return static_cast<ScoreType>(JPS_sqrt(dx*dx + dy*dy));
402 : _data(0), used(0), cap(0),
_user(user)
419 if(used < cap || _grow())
434 inline bool empty()
const {
return !used; }
435 inline T *
data() {
return _data; }
436 inline const T *
data()
const {
return _data; }
440 JPS_ASSERT(e && _data <= e && e < _data + used);
441 return static_cast<SizeT>(e - _data);
446 return cap < newcap ? _grow(newcap) : _data;
455 return cap *
sizeof(T);
469 void *_grow(
SizeT newcap)
481 const SizeT newcap = cap + (cap / 2) + 32;
482 return _grow(newcap);
497 inline static void Swap(T& a, T& b)
504 template<
typename IT>
505 inline static void Reverse(IT first, IT last)
507 while((first != last) && (first != --last))
520 static const unsigned LOAD_FACTOR = 8;
521 static const unsigned INITIAL_BUCKETS = 16;
539 return (y << 16) ^ x;
545 : _storageRef(storage), _buckets(storage._user)
550 for(
SizeT i = 0; i < _buckets.
size(); ++i)
557 for(
SizeT i = 0; i < _buckets.
size(); ++i)
563 const unsigned h = Hash(x, y);
564 const unsigned h2 = Hash2(x, y);
569 b = &_buckets[h & (ksz - 1)];
571 const HashLoc *
const bdata = b->
data();
572 for (
SizeT i = 0; i < bsz; ++i)
579 if (bdata[i].hash2 == h2)
581 Node &n = _storageRef[bdata[i].idx];
589 SizeT newbsz = _enlarge();
591 b = &_buckets[h & (newbsz - 1)];
595 HashLoc *loc = b->
alloc();
601 loc->idx = _storageRef.
size();
621 sum += it->_getMemSize();
632 if (n < oldsz * LOAD_FACTOR)
636 const SizeT newsz = oldsz ? oldsz * 2 : INITIAL_BUCKETS;
642 for(
SizeT i = 0; i < oldsz; ++i)
646 for(
SizeT i = oldsz; i < newsz; ++i)
648 void *p = _buckets.
alloc();
653 for(
SizeT i = 0; i < n; ++i)
655 const Position p = _storageRef[i].pos;
656 HashLoc *loc = _buckets[Hash(p.
x, p.
y) & mask].
alloc();
660 loc->hash2 = Hash2(p.
x, p.
y);
667 typedef PodVec<Bucket> Buckets;
680 : _storageRef(storage), idxHeap(storage._user)
686 _heapPushIdx(_storageRef.
getindex(n));
691 return _storageRef[_popIdx()];
697 const unsigned ni = _storageRef.
getindex(&n);
698 const unsigned sz = idxHeap.
size();
699 unsigned *p = idxHeap.
data();
700 for(
unsigned i = 0; i < sz; ++i)
722 return _storageRef[idxHeap[a]].f > _storageRef[idxHeap[b]].f;
727 return _storageRef[idxHeap[a]].f > _storageRef[idx].f;
730 void _percolateUp(
SizeT i)
732 const SizeT idx = idxHeap[i];
737 idxHeap[i] = idxHeap[p];
742 while(i && _heapLessIdx(p, idx));
746 void _percolateDown(
SizeT i)
748 const SizeT idx = idxHeap[i];
755 if(child + 1 < sz && !_heapLess(child+1, child))
757 idxHeap[i] = idxHeap[child];
760 child = (i << 1) + 1;
767 void _heapPushIdx(
SizeT idx)
778 const SizeT root = idxHeap[0];
779 idxHeap[0] = idxHeap[--sz];
787 inline void _fixIdx(
SizeT i)
794#undef JPS_PLACEMENT_NEW
836 if(!jn.
isOpen() || newG < jn.
g)
853 template <
typename PV>
885 template<
typename PV>
892 template<
typename PV>
900 bool identifySuccessors(
const Node& n);
902 bool findPathGreedy(
Node *start,
Node *end);
904 unsigned findNeighborsAStar(
const Node& n,
Position *wptr);
906 unsigned findNeighborsJPS(
const Node& n,
Position *wptr)
const;
924 const SizeT offset = path.size();
927 const Node *next = &endNode;
937 const unsigned x = next->
pos.
x, y = next->
pos.
y;
938 int dx = int(prev->
pos.
x - x);
939 int dy = int(prev->
pos.
y - y);
940 const int adx = Abs(dx);
941 const int ady = Abs(dy);
943 const int steps = Max(adx, ady);
944 dx = int(step) * Sgn(dx);
945 dy = int(step) * Sgn(dy);
946 int dxa = 0, dya = 0;
947 for(
int i = 0; i < steps; i += step)
949 path.push_back(Pos(x+dxa, y+dya));
964 path.push_back(next->
pos);
973 if(path.size() != offset + added)
980 Reverse(path.begin() + offset, path.end());
989 return nodemap(pos.
x, pos.
y);
996 int dx = int(p.
x - src.
x);
997 int dy = int(p.
y - src.
y);
1001 return jumpD(p, dx, dy);
1003 return jumpX(p, dx);
1005 return jumpY(p, dy);
1012 template <
typename GRID>
Position Searcher<GRID>::jumpD(
Position p,
int dx,
int dy)
1029 if( (grid(x-dx, y+dy) && !grid(x-dx, y)) || (grid(x+dx, y-dy) && !grid(x, y-dy)) )
1032 const bool gdx = !!grid(x+dx, y);
1033 const bool gdy = !!grid(x, y+dy);
1035 if(gdx && jumpX(Pos(x+dx, y), dx).isValid())
1038 if(gdy && jumpY(Pos(x, y+dy), dy).isValid())
1041 if((gdx || gdy) && grid(x+dx, y+dy))
1053 stepsRemain -= steps;
1057 template <
typename GRID>
inline Position Searcher<GRID>::jumpX(
Position p,
int dx)
1066 unsigned a = ~((!!grid(p.
x, y+1)) | ((!!grid(p.
x, y-1)) << 1));
1070 const unsigned xx = p.
x + dx;
1071 const unsigned b = (!!grid(xx, y+1)) | ((!!grid(xx, y-1)) << 1);
1073 if((b & a) || p == endpos)
1087 stepsRemain -= steps;
1091 template <
typename GRID>
inline Position Searcher<GRID>::jumpY(
Position p,
int dy)
1100 unsigned a = ~((!!grid(x+1, p.
y)) | ((!!grid(x-1, p.
y)) << 1));
1104 const unsigned yy = p.
y + dy;
1105 const unsigned b = (!!grid(x+1, yy)) | ((!!grid(x-1, yy)) << 1);
1107 if((a & b) || p == endpos)
1121 stepsRemain -= steps;
1125#define JPS_CHECKGRID(dx, dy) (grid(x+(dx), y+(dy)))
1126#define JPS_ADDPOS(dx, dy) do { *w++ = Pos(x+(dx), y+(dy)); } while(0)
1127#define JPS_ADDPOS_CHECK(dx, dy) do { if(JPS_CHECKGRID(dx, dy)) JPS_ADDPOS(dx, dy); } while(0)
1128#define JPS_ADDPOS_NO_TUNNEL(dx, dy) do { if(grid(x+(dx),y) || grid(x,y+(dy))) JPS_ADDPOS_CHECK(dx, dy); } while(0)
1130 template <
typename GRID>
unsigned Searcher<GRID>::findNeighborsJPS(
const Node& n,
Position *wptr)
const
1133 const unsigned x = n.pos.
x;
1134 const unsigned y = n.pos.y;
1150 return unsigned(w - wptr);
1152 const Node& p = n.getParent();
1154 const int dx = Sgn<int>(x - p.pos.x);
1155 const int dy = Sgn<int>(y - p.pos.y);
1161 const bool walkX = !!grid(x+dx, y);
1163 *w++ = Pos(x+dx, y);
1164 const bool walkY = !!grid(x, y+dy);
1166 *w++ = Pos(x, y+dy);
1207 return unsigned(w - wptr);
1211 template <
typename GRID>
unsigned Searcher<GRID>::findNeighborsAStar(
const Node& n,
Position *wptr)
1214 const int x = n.pos.
x;
1215 const int y = n.pos.y;
1226 return unsigned(w - wptr);
1231#undef JPS_ADDPOS_CHECK
1232#undef JPS_ADDPOS_NO_TUNNEL
1236 template <
typename GRID>
bool Searcher<GRID>::identifySuccessors(
const Node& n_)
1238 const SizeT nidx = storage.getindex(&n_);
1243 ? findNeighborsAStar(n_, &buf[0])
1244 : findNeighborsJPS(n_, &buf[0]);
1246 for(
int i = num-1; i >= 0; --i)
1254 jp = jumpP(buf[i], np);
1259 Node *jn = getNode(jp);
1263 Node& n = storage[nidx];
1266 _expandNode(jp, *jn, n);
1273 JPS_Result res = findPathInit(start, end, flags);
1284 res = findPathStep(0);
1305 this->flags = flags;
1317 if(!grid(start.
x, start.
y))
1321 if(!grid(end.
x, end.
y))
1324 Node *endNode = getNode(end);
1327 endNodeIdx = storage.getindex(endNode);
1329 Node *startNode = getNode(start);
1332 endNode = &storage[endNodeIdx];
1337 if(findPathGreedy(startNode, endNode))
1341 open.pushNode(startNode);
1348 stepsRemain = limit;
1353 Node& n = open.popNode();
1357 if(!identifySuccessors(n))
1360 while(stepsRemain >= 0);
1366 return this->generatePath(path, step);
1379 int dx = int(endpos.
x - x);
1380 int dy = int(endpos.
y - y);
1381 const int adx = Abs(dx);
1382 const int ady = Abs(dy);
1387 if(x != endpos.
x && y != endpos.
y)
1390 const int minlen = Min(adx, ady);
1391 const PosType tx = x + dx * minlen;
1394 if(grid(x, y) && (grid(x+dx, y) || grid(x, y+dy)))
1412 if(!(x == endpos.
x && y == endpos.
y))
1414 while(x != endpos.
x)
1415 if(!grid(x += dx, y))
1418 while(y != endpos.
y)
1419 if(!grid(x, y += dy))
1427 const unsigned nidx = storage.getindex(n);
1428 Node *mid = getNode(midpos);
1432 endnode = &storage[endNodeIdx];
1448#undef JPS_HEURISTIC_ACCURATE
1449#undef JPS_HEURISTIC_ESTIMATE
1454 using Internal::Searcher;
1478 template <
typename GRID,
typename PV>
1485 if(!search.
findPath(path, Pos(startx, starty), Pos(endx, endy), step, flags))
1488 return done + !done;
JPS_Flags_
Definition: JPS.h:260
@ JPS_Flag_AStarOnly
Definition: JPS.h:277
@ JPS_Flag_Default
Definition: JPS.h:262
@ JPS_Flag_NoGreedy
Definition: JPS.h:270
@ JPS_Flag_NoStartCheck
Definition: JPS.h:281
@ JPS_Flag_NoEndCheck
Definition: JPS.h:284
#define JPS_ADDPOS_NO_TUNNEL(dx, dy)
Definition: JPS.h:1128
#define JPS_HEURISTIC_ACCURATE(a, b)
Definition: JPS.h:207
#define JPS_PLACEMENT_NEW(p)
Definition: JPS.h:304
#define JPS_ADDPOS(dx, dy)
Definition: JPS.h:1126
unsigned JPS_Flags
Definition: JPS.h:258
#define JPS_ADDPOS_CHECK(dx, dy)
Definition: JPS.h:1127
JPS_Result
Definition: JPS.h:288
@ JPS_EMPTY_PATH
Definition: JPS.h:292
@ JPS_NEED_MORE_STEPS
Definition: JPS.h:291
@ JPS_NO_PATH
Definition: JPS.h:289
@ JPS_OUT_OF_MEMORY
Definition: JPS.h:293
@ JPS_FOUND_PATH
Definition: JPS.h:290
#define JPS_HEURISTIC_ESTIMATE(a, b)
Definition: JPS.h:227
#define JPS_free(p, oldsize, user)
Definition: JPS.h:202
#define JPS_realloc(p, newsize, oldsize, user)
Definition: JPS.h:199
#define JPS_CHECKGRID(dx, dy)
Definition: JPS.h:1125
#define JPS_ASSERT(cond)
Definition: JPS.h:190
NodeMap(Storage &storage)
Definition: JPS.h:544
void dealloc()
Definition: JPS.h:548
SizeT _getMemSize() const
Definition: JPS.h:617
Node * operator()(PosType x, PosType y)
Definition: JPS.h:561
void clear()
Definition: JPS.h:554
void pushNode(Node *n)
Definition: JPS.h:684
SizeT _getMemSize() const
Definition: JPS.h:713
OpenList(const Storage &storage)
Definition: JPS.h:679
bool empty() const
Definition: JPS.h:711
void fixNode(const Node &n)
Definition: JPS.h:695
Node & popNode()
Definition: JPS.h:689
void dealloc()
Definition: JPS.h:709
void clear()
Definition: JPS.h:710
bool empty() const
Definition: JPS.h:434
void clear()
Definition: JPS.h:405
void pop_back()
Definition: JPS.h:431
T value_type
Definition: JPS.h:462
void dealloc()
Definition: JPS.h:409
SizeT size() const
Definition: JPS.h:433
const_iterator cbegin() const
Definition: JPS.h:465
T & operator[](size_t idx) const
Definition: JPS.h:437
void resize(SizeT sz)
Definition: JPS.h:448
const_iterator cend() const
Definition: JPS.h:466
iterator end()
Definition: JPS.h:464
SizeT getindex(const T *e) const
Definition: JPS.h:438
void * _reserve(SizeT newcap)
Definition: JPS.h:444
T * data()
Definition: JPS.h:435
void *const _user
Definition: JPS.h:488
T & back()
Definition: JPS.h:432
SizeT _getMemSize() const
Definition: JPS.h:453
T * alloc()
Definition: JPS.h:416
const T * data() const
Definition: JPS.h:436
PodVec(void *user=0)
Definition: JPS.h:401
const T * const_iterator
Definition: JPS.h:460
T * iterator
Definition: JPS.h:459
~PodVec()
Definition: JPS.h:404
void push_back(const T &e)
Definition: JPS.h:426
SizeT size_type
Definition: JPS.h:461
iterator begin()
Definition: JPS.h:463
JPS_Flags flags
Definition: JPS.h:808
OpenList open
Definition: JPS.h:803
void clear()
Definition: JPS.h:822
SizeT getTotalMemoryInUse() const
Definition: JPS.h:869
void freeMemory()
Definition: JPS.h:856
Position endPos
Definition: JPS.h:806
SizeT stepsDone
Definition: JPS.h:810
SizeT getStepsDone() const
Definition: JPS.h:866
SizeT getNodesExpanded() const
Definition: JPS.h:867
SearcherBase(void *user)
Definition: JPS.h:813
void _expandNode(const Position jp, Node &jn, const Node &parent)
Definition: JPS.h:831
JPS_Result generatePath(PV &path, unsigned step) const
Definition: JPS.h:920
int stepsRemain
Definition: JPS.h:809
SizeT endNodeIdx
Definition: JPS.h:807
Storage storage
Definition: JPS.h:802
NodeMap nodemap
Definition: JPS.h:804
bool findPath(PV &path, Position start, Position end, unsigned step, JPS_Flags flags=JPS_Flag_Default)
Definition: JPS.h:1271
JPS_Result findPathStep(int limit)
Definition: JPS.h:1346
JPS_Result findPathFinish(PV &path, unsigned step) const
Definition: JPS.h:1364
JPS_Result findPathInit(Position start, Position end, JPS_Flags flags=JPS_Flag_Default)
Definition: JPS.h:1300
Searcher(const GRID &g, void *user=0)
Definition: JPS.h:880
ScoreType Manhattan(const Position &a, const Position &b)
Definition: JPS.h:347
ScoreType Chebyshev(const Position &a, const Position &b)
Definition: JPS.h:354
PodVec< Node > Storage
Definition: JPS.h:514
unsigned SizeT
Definition: JPS.h:248
unsigned PosType
Definition: JPS.h:236
Internal::PodVec< Position > PathVector
Definition: JPS.h:1456
int ScoreType
Definition: JPS.h:242
SizeT findPath(PV &path, const GRID &grid, PosType startx, PosType starty, PosType endx, PosType endy, unsigned step=0, JPS_Flags flags=JPS_Flag_Default, void *user=0)
Definition: JPS.h:1479
void setClosed()
Definition: JPS.h:386
Position pos
Definition: JPS.h:380
void setParent(const Node &p)
Definition: JPS.h:394
const Node * getParentOpt() const
Definition: JPS.h:393
int parentOffs
Definition: JPS.h:381
unsigned isClosed() const
Definition: JPS.h:388
Node & getParent()
Definition: JPS.h:391
const Node & getParent() const
Definition: JPS.h:392
int hasParent() const
Definition: JPS.h:384
ScoreType f
Definition: JPS.h:379
unsigned _flags
Definition: JPS.h:382
unsigned isOpen() const
Definition: JPS.h:387
void setOpen()
Definition: JPS.h:385
ScoreType g
Definition: JPS.h:379
bool operator==(const Position &p) const
Definition: JPS.h:313
PosType y
Definition: JPS.h:311
bool isValid() const
Definition: JPS.h:322
bool operator!=(const Position &p) const
Definition: JPS.h:317
PosType x
Definition: JPS.h:311
int y
Definition: Position.h:13
int x
Definition: Position.h:10