Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/servers/nav_heap.h
11320 views
1
/**************************************************************************/
2
/* nav_heap.h */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#pragma once
32
33
#include "core/templates/local_vector.h"
34
35
// This file contains Heap which is used by both 2D and 3D navigation.
36
37
template <typename T>
38
struct NoopIndexer {
39
void operator()(const T &p_value, uint32_t p_index) {}
40
};
41
42
/**
43
* A max-heap implementation that notifies of element index changes.
44
*/
45
template <typename T, typename LessThan = Comparator<T>, typename Indexer = NoopIndexer<T>>
46
class Heap {
47
LocalVector<T> _buffer;
48
49
LessThan _less_than;
50
Indexer _indexer;
51
52
public:
53
static constexpr uint32_t INVALID_INDEX = UINT32_MAX;
54
void reserve(uint32_t p_size) {
55
_buffer.reserve(p_size);
56
}
57
58
uint32_t size() const {
59
return _buffer.size();
60
}
61
62
bool is_empty() const {
63
return _buffer.is_empty();
64
}
65
66
void push(const T &p_element) {
67
_buffer.push_back(p_element);
68
_indexer(p_element, _buffer.size() - 1);
69
_shift_up(_buffer.size() - 1);
70
}
71
72
T pop() {
73
ERR_FAIL_COND_V_MSG(_buffer.is_empty(), T(), "Can't pop an empty heap.");
74
T value = _buffer[0];
75
_indexer(value, INVALID_INDEX);
76
if (_buffer.size() > 1) {
77
_buffer[0] = _buffer[_buffer.size() - 1];
78
_indexer(_buffer[0], 0);
79
_buffer.remove_at(_buffer.size() - 1);
80
_shift_down(0);
81
} else {
82
_buffer.remove_at(_buffer.size() - 1);
83
}
84
return value;
85
}
86
87
/**
88
* Update the position of the element in the heap if necessary.
89
*/
90
void shift(uint32_t p_index) {
91
ERR_FAIL_UNSIGNED_INDEX_MSG(p_index, _buffer.size(), "Heap element index is out of range.");
92
if (!_shift_up(p_index)) {
93
_shift_down(p_index);
94
}
95
}
96
97
void clear() {
98
for (const T &value : _buffer) {
99
_indexer(value, INVALID_INDEX);
100
}
101
_buffer.clear();
102
}
103
104
Heap() {}
105
106
Heap(const LessThan &p_less_than) :
107
_less_than(p_less_than) {}
108
109
Heap(const Indexer &p_indexer) :
110
_indexer(p_indexer) {}
111
112
Heap(const LessThan &p_less_than, const Indexer &p_indexer) :
113
_less_than(p_less_than), _indexer(p_indexer) {}
114
115
private:
116
bool _shift_up(uint32_t p_index) {
117
T value = _buffer[p_index];
118
uint32_t current_index = p_index;
119
uint32_t parent_index = (current_index - 1) / 2;
120
while (current_index > 0 && _less_than(_buffer[parent_index], value)) {
121
_buffer[current_index] = _buffer[parent_index];
122
_indexer(_buffer[current_index], current_index);
123
current_index = parent_index;
124
parent_index = (current_index - 1) / 2;
125
}
126
if (current_index != p_index) {
127
_buffer[current_index] = value;
128
_indexer(value, current_index);
129
return true;
130
} else {
131
return false;
132
}
133
}
134
135
bool _shift_down(uint32_t p_index) {
136
T value = _buffer[p_index];
137
uint32_t current_index = p_index;
138
uint32_t child_index = 2 * current_index + 1;
139
while (child_index < _buffer.size()) {
140
if (child_index + 1 < _buffer.size() &&
141
_less_than(_buffer[child_index], _buffer[child_index + 1])) {
142
child_index++;
143
}
144
if (_less_than(_buffer[child_index], value)) {
145
break;
146
}
147
_buffer[current_index] = _buffer[child_index];
148
_indexer(_buffer[current_index], current_index);
149
current_index = child_index;
150
child_index = 2 * current_index + 1;
151
}
152
if (current_index != p_index) {
153
_buffer[current_index] = value;
154
_indexer(value, current_index);
155
return true;
156
} else {
157
return false;
158
}
159
}
160
};
161
162