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