69 template <
class Derived2,
class Tree2,
bool WithBounds2>
84 static constexpr MapType
const Type = MapType::DISTANCE;
93 using coord_t =
typename Tree::coord_t;
94 using depth_t =
typename Tree::depth_t;
95 using offset_t =
typename Tree::offset_t;
96 using length_t =
typename Tree::length_t;
97 using pos_t =
typename Tree::pos_t;
107 template <
class Geometry>
108 [[nodiscard]]
bool intersects(Index node, Geometry
const& query)
const
114 template <
class Geometry>
115 [[nodiscard]]
float distanceSquared(Index node, Geometry
const& query)
const
117 if (!distanceContainsSurface(node)) {
121 if (intersects(node, query)) {
125 if constexpr (2 == Dim) {
126 constexpr std::array<std::array<std::uint8_t, 25>,
ipow(2, 8)>
const lut{
127 std::array<std::uint8_t, 25>{2, 4, 4},
128 std::array<std::uint8_t, 25>{4, 0, 9, 4, 9},
129 std::array<std::uint8_t, 25>{2, 1, 4},
130 std::array<std::uint8_t, 25>{8, 0, 1, 0, 9, 1, 4, 4, 9},
131 std::array<std::uint8_t, 25>{4, 2, 10, 4, 10},
132 std::array<std::uint8_t, 25>{8, 0, 9, 2, 10, 4, 9, 4, 10},
133 std::array<std::uint8_t, 25>{8, 1, 2, 1, 4, 2, 10, 4, 10},
134 std::array<std::uint8_t, 25>{12, 0, 1, 0, 9, 1, 2, 2, 10, 4, 9, 4, 10},
135 std::array<std::uint8_t, 25>{2, 3, 4},
136 std::array<std::uint8_t, 25>{8, 0, 3, 0, 9, 3, 4, 4, 9},
137 std::array<std::uint8_t, 25>{8, 1, 4, 1, 9, 3, 4, 3, 9},
138 std::array<std::uint8_t, 25>{8, 0, 1, 0, 3, 1, 4, 3, 4},
139 std::array<std::uint8_t, 25>{6, 2, 10, 3, 4, 4, 10},
140 std::array<std::uint8_t, 25>{12, 0, 3, 0, 9, 2, 10, 3, 4, 4, 9, 4, 10},
141 std::array<std::uint8_t, 25>{12, 1, 2, 1, 9, 2, 10, 3, 4, 3, 9, 4, 10},
142 std::array<std::uint8_t, 25>{12, 0, 1, 0, 3, 1, 2, 2, 10, 3, 4, 4, 10},
143 std::array<std::uint8_t, 25>{2, 4, 5},
144 std::array<std::uint8_t, 25>{6, 0, 9, 4, 5, 4, 9},
145 std::array<std::uint8_t, 25>{8, 1, 4, 1, 10, 4, 5, 5, 10},
146 std::array<std::uint8_t, 25>{12, 0, 1, 0, 9, 1, 10, 4, 5, 4, 9, 5, 10},
147 std::array<std::uint8_t, 25>{8, 2, 5, 2, 10, 4, 5, 4, 10},
148 std::array<std::uint8_t, 25>{12, 0, 9, 2, 5, 2, 10, 4, 5, 4, 9, 4, 10},
149 std::array<std::uint8_t, 25>{8, 1, 2, 1, 4, 2, 5, 4, 5},
150 std::array<std::uint8_t, 25>{12, 0, 1, 0, 9, 1, 2, 2, 5, 4, 5, 4, 9},
151 std::array<std::uint8_t, 25>{4, 3, 4, 4, 5},
152 std::array<std::uint8_t, 25>{10, 0, 3, 0, 9, 3, 4, 4, 5, 4, 9},
153 std::array<std::uint8_t, 25>{12, 1, 9, 1, 10, 3, 4, 3, 9, 4, 5, 5, 10},
154 std::array<std::uint8_t, 25>{12, 0, 1, 0, 3, 1, 10, 3, 4, 4, 5, 5, 10},
155 std::array<std::uint8_t, 25>{10, 2, 5, 2, 10, 3, 4, 4, 5, 4, 10},
156 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 2, 5, 2, 10, 3, 4, 4, 5, 4, 9, 4,
158 std::array<std::uint8_t, 25>{12, 1, 2, 1, 9, 2, 5, 3, 4, 3, 9, 4, 5},
159 std::array<std::uint8_t, 25>{12, 0, 1, 0, 3, 1, 2, 2, 5, 3, 4, 4, 5},
160 std::array<std::uint8_t, 25>{4, 4, 11, 6, 11},
161 std::array<std::uint8_t, 25>{8, 0, 9, 4, 9, 4, 11, 6, 11},
162 std::array<std::uint8_t, 25>{6, 1, 4, 4, 11, 6, 11},
163 std::array<std::uint8_t, 25>{12, 0, 1, 0, 9, 1, 4, 4, 9, 4, 11, 6, 11},
164 std::array<std::uint8_t, 25>{8, 2, 10, 4, 10, 4, 11, 6, 11},
165 std::array<std::uint8_t, 25>{12, 0, 9, 2, 10, 4, 9, 4, 10, 4, 11, 6, 11},
166 std::array<std::uint8_t, 25>{12, 1, 2, 1, 4, 2, 10, 4, 10, 4, 11, 6, 11},
167 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 2, 2, 10, 4, 9, 4, 10, 4, 11, 6,
169 std::array<std::uint8_t, 25>{8, 3, 4, 3, 6, 4, 11, 6, 11},
170 std::array<std::uint8_t, 25>{12, 0, 3, 0, 9, 3, 6, 4, 9, 4, 11, 6, 11},
171 std::array<std::uint8_t, 25>{12, 1, 4, 1, 9, 3, 6, 3, 9, 4, 11, 6, 11},
172 std::array<std::uint8_t, 25>{12, 0, 1, 0, 3, 1, 4, 3, 6, 4, 11, 6, 11},
173 std::array<std::uint8_t, 25>{12, 2, 10, 3, 4, 3, 6, 4, 10, 4, 11, 6, 11},
174 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 2, 10, 3, 6, 4, 9, 4, 10, 4, 11, 6,
176 std::array<std::uint8_t, 25>{16, 1, 2, 1, 9, 2, 10, 3, 6, 3, 9, 4, 10, 4, 11, 6,
178 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 2, 2, 10, 3, 6, 4, 10, 4, 11, 6,
180 std::array<std::uint8_t, 25>{6, 4, 5, 4, 11, 6, 11},
181 std::array<std::uint8_t, 25>{10, 0, 9, 4, 5, 4, 9, 4, 11, 6, 11},
182 std::array<std::uint8_t, 25>{12, 1, 4, 1, 10, 4, 5, 4, 11, 5, 10, 6, 11},
183 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 10, 4, 5, 4, 9, 4, 11, 5, 10, 6,
185 std::array<std::uint8_t, 25>{12, 2, 5, 2, 10, 4, 5, 4, 10, 4, 11, 6, 11},
186 std::array<std::uint8_t, 25>{16, 0, 9, 2, 5, 2, 10, 4, 5, 4, 9, 4, 10, 4, 11, 6,
188 std::array<std::uint8_t, 25>{12, 1, 2, 1, 4, 2, 5, 4, 5, 4, 11, 6, 11},
189 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 2, 2, 5, 4, 5, 4, 9, 4, 11, 6,
191 std::array<std::uint8_t, 25>{10, 3, 4, 3, 6, 4, 5, 4, 11, 6, 11},
192 std::array<std::uint8_t, 25>{14, 0, 3, 0, 9, 3, 6, 4, 5, 4, 9, 4, 11, 6, 11},
193 std::array<std::uint8_t, 25>{16, 1, 9, 1, 10, 3, 6, 3, 9, 4, 5, 4, 11, 5, 10, 6,
195 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 10, 3, 6, 4, 5, 4, 11, 5, 10, 6,
197 std::array<std::uint8_t, 25>{16, 2, 5, 2, 10, 3, 4, 3, 6, 4, 5, 4, 10, 4, 11, 6,
199 std::array<std::uint8_t, 25>{20, 0, 3, 0, 9, 2, 5, 2, 10, 3, 6,
200 4, 5, 4, 9, 4, 10, 4, 11, 6, 11},
201 std::array<std::uint8_t, 25>{16, 1, 2, 1, 9, 2, 5, 3, 6, 3, 9, 4, 5, 4, 11, 6,
203 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 2, 2, 5, 3, 6, 4, 5, 4, 11, 6,
205 std::array<std::uint8_t, 25>{2, 4, 7},
206 std::array<std::uint8_t, 25>{6, 0, 9, 4, 7, 4, 9},
207 std::array<std::uint8_t, 25>{4, 1, 4, 4, 7},
208 std::array<std::uint8_t, 25>{10, 0, 1, 0, 9, 1, 4, 4, 7, 4, 9},
209 std::array<std::uint8_t, 25>{6, 2, 10, 4, 7, 4, 10},
210 std::array<std::uint8_t, 25>{10, 0, 9, 2, 10, 4, 7, 4, 9, 4, 10},
211 std::array<std::uint8_t, 25>{10, 1, 2, 1, 4, 2, 10, 4, 7, 4, 10},
212 std::array<std::uint8_t, 25>{14, 0, 1, 0, 9, 1, 2, 2, 10, 4, 7, 4, 9, 4, 10},
213 std::array<std::uint8_t, 25>{8, 3, 4, 3, 11, 4, 7, 7, 11},
214 std::array<std::uint8_t, 25>{12, 0, 3, 0, 9, 3, 11, 4, 7, 4, 9, 7, 11},
215 std::array<std::uint8_t, 25>{12, 1, 4, 1, 9, 3, 9, 3, 11, 4, 7, 7, 11},
216 std::array<std::uint8_t, 25>{12, 0, 1, 0, 3, 1, 4, 3, 11, 4, 7, 7, 11},
217 std::array<std::uint8_t, 25>{12, 2, 10, 3, 4, 3, 11, 4, 7, 4, 10, 7, 11},
218 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 2, 10, 3, 11, 4, 7, 4, 9, 4, 10, 7,
220 std::array<std::uint8_t, 25>{16, 1, 2, 1, 9, 2, 10, 3, 9, 3, 11, 4, 7, 4, 10, 7,
222 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 2, 2, 10, 3, 11, 4, 7, 4, 10, 7,
224 std::array<std::uint8_t, 25>{8, 4, 5, 4, 7, 5, 12, 7, 12},
225 std::array<std::uint8_t, 25>{12, 0, 9, 4, 5, 4, 7, 4, 9, 5, 12, 7, 12},
226 std::array<std::uint8_t, 25>{12, 1, 4, 1, 10, 4, 7, 5, 10, 5, 12, 7, 12},
227 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 10, 4, 7, 4, 9, 5, 10, 5, 12, 7,
229 std::array<std::uint8_t, 25>{12, 2, 5, 2, 10, 4, 7, 4, 10, 5, 12, 7, 12},
230 std::array<std::uint8_t, 25>{16, 0, 9, 2, 5, 2, 10, 4, 7, 4, 9, 4, 10, 5, 12, 7,
232 std::array<std::uint8_t, 25>{12, 1, 2, 1, 4, 2, 5, 4, 7, 5, 12, 7, 12},
233 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 2, 2, 5, 4, 7, 4, 9, 5, 12, 7,
235 std::array<std::uint8_t, 25>{12, 3, 4, 3, 11, 4, 5, 5, 12, 7, 11, 7, 12},
236 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 3, 11, 4, 5, 4, 9, 5, 12, 7, 11, 7,
238 std::array<std::uint8_t, 25>{16, 1, 9, 1, 10, 3, 9, 3, 11, 5, 10, 5, 12, 7, 11,
240 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 10, 3, 11, 5, 10, 5, 12, 7, 11,
242 std::array<std::uint8_t, 25>{16, 2, 5, 2, 10, 3, 4, 3, 11, 4, 10, 5, 12, 7, 11,
244 std::array<std::uint8_t, 25>{20, 0, 3, 0, 9, 2, 5, 2, 10, 3, 11,
245 4, 9, 4, 10, 5, 12, 7, 11, 7, 12},
246 std::array<std::uint8_t, 25>{16, 1, 2, 1, 9, 2, 5, 3, 9, 3, 11, 5, 12, 7, 11, 7,
248 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 2, 2, 5, 3, 11, 5, 12, 7, 11, 7,
250 std::array<std::uint8_t, 25>{8, 4, 7, 4, 11, 6, 7, 6, 11},
251 std::array<std::uint8_t, 25>{12, 0, 9, 4, 7, 4, 9, 4, 11, 6, 7, 6, 11},
252 std::array<std::uint8_t, 25>{10, 1, 4, 4, 7, 4, 11, 6, 7, 6, 11},
253 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 4, 4, 7, 4, 9, 4, 11, 6, 7, 6,
255 std::array<std::uint8_t, 25>{12, 2, 10, 4, 7, 4, 10, 4, 11, 6, 7, 6, 11},
256 std::array<std::uint8_t, 25>{16, 0, 9, 2, 10, 4, 7, 4, 9, 4, 10, 4, 11, 6, 7, 6,
258 std::array<std::uint8_t, 25>{16, 1, 2, 1, 4, 2, 10, 4, 7, 4, 10, 4, 11, 6, 7, 6,
260 std::array<std::uint8_t, 25>{20, 0, 1, 0, 9, 1, 2, 2, 10, 4, 7,
261 4, 9, 4, 10, 4, 11, 6, 7, 6, 11},
262 std::array<std::uint8_t, 25>{8, 3, 4, 3, 6, 4, 7, 6, 7},
263 std::array<std::uint8_t, 25>{12, 0, 3, 0, 9, 3, 6, 4, 7, 4, 9, 6, 7},
264 std::array<std::uint8_t, 25>{12, 1, 4, 1, 9, 3, 6, 3, 9, 4, 7, 6, 7},
265 std::array<std::uint8_t, 25>{12, 0, 1, 0, 3, 1, 4, 3, 6, 4, 7, 6, 7},
266 std::array<std::uint8_t, 25>{12, 2, 10, 3, 4, 3, 6, 4, 7, 4, 10, 6, 7},
267 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 2, 10, 3, 6, 4, 7, 4, 9, 4, 10, 6,
269 std::array<std::uint8_t, 25>{16, 1, 2, 1, 9, 2, 10, 3, 6, 3, 9, 4, 7, 4, 10, 6,
271 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 2, 2, 10, 3, 6, 4, 7, 4, 10, 6,
273 std::array<std::uint8_t, 25>{12, 4, 5, 4, 11, 5, 12, 6, 7, 6, 11, 7, 12},
274 std::array<std::uint8_t, 25>{16, 0, 9, 4, 5, 4, 9, 4, 11, 5, 12, 6, 7, 6, 11, 7,
276 std::array<std::uint8_t, 25>{16, 1, 4, 1, 10, 4, 11, 5, 10, 5, 12, 6, 7, 6, 11,
278 std::array<std::uint8_t, 25>{20, 0, 1, 0, 9, 1, 10, 4, 9, 4, 11,
279 5, 10, 5, 12, 6, 7, 6, 11, 7, 12},
280 std::array<std::uint8_t, 25>{16, 2, 5, 2, 10, 4, 10, 4, 11, 5, 12, 6, 7, 6, 11,
282 std::array<std::uint8_t, 25>{20, 0, 9, 2, 5, 2, 10, 4, 9, 4, 10,
283 4, 11, 5, 12, 6, 7, 6, 11, 7, 12},
284 std::array<std::uint8_t, 25>{16, 1, 2, 1, 4, 2, 5, 4, 11, 5, 12, 6, 7, 6, 11, 7,
286 std::array<std::uint8_t, 25>{20, 0, 1, 0, 9, 1, 2, 2, 5, 4, 9,
287 4, 11, 5, 12, 6, 7, 6, 11, 7, 12},
288 std::array<std::uint8_t, 25>{12, 3, 4, 3, 6, 4, 5, 5, 12, 6, 7, 7, 12},
289 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 3, 6, 4, 5, 4, 9, 5, 12, 6, 7, 7,
291 std::array<std::uint8_t, 25>{16, 1, 9, 1, 10, 3, 6, 3, 9, 5, 10, 5, 12, 6, 7, 7,
293 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 10, 3, 6, 5, 10, 5, 12, 6, 7, 7,
295 std::array<std::uint8_t, 25>{16, 2, 5, 2, 10, 3, 4, 3, 6, 4, 10, 5, 12, 6, 7, 7,
297 std::array<std::uint8_t, 25>{20, 0, 3, 0, 9, 2, 5, 2, 10, 3, 6,
298 4, 9, 4, 10, 5, 12, 6, 7, 7, 12},
299 std::array<std::uint8_t, 25>{16, 1, 2, 1, 9, 2, 5, 3, 6, 3, 9, 5, 12, 6, 7, 7,
301 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 2, 2, 5, 3, 6, 5, 12, 6, 7, 7,
303 std::array<std::uint8_t, 25>{4, 4, 12, 8, 12},
304 std::array<std::uint8_t, 25>{8, 0, 9, 4, 9, 4, 12, 8, 12},
305 std::array<std::uint8_t, 25>{6, 1, 4, 4, 12, 8, 12},
306 std::array<std::uint8_t, 25>{12, 0, 1, 0, 9, 1, 4, 4, 9, 4, 12, 8, 12},
307 std::array<std::uint8_t, 25>{8, 2, 10, 4, 10, 4, 12, 8, 12},
308 std::array<std::uint8_t, 25>{12, 0, 9, 2, 10, 4, 9, 4, 10, 4, 12, 8, 12},
309 std::array<std::uint8_t, 25>{12, 1, 2, 1, 4, 2, 10, 4, 10, 4, 12, 8, 12},
310 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 2, 2, 10, 4, 9, 4, 10, 4, 12, 8,
312 std::array<std::uint8_t, 25>{6, 3, 4, 4, 12, 8, 12},
313 std::array<std::uint8_t, 25>{12, 0, 3, 0, 9, 3, 4, 4, 9, 4, 12, 8, 12},
314 std::array<std::uint8_t, 25>{12, 1, 4, 1, 9, 3, 4, 3, 9, 4, 12, 8, 12},
315 std::array<std::uint8_t, 25>{12, 0, 1, 0, 3, 1, 4, 3, 4, 4, 12, 8, 12},
316 std::array<std::uint8_t, 25>{10, 2, 10, 3, 4, 4, 10, 4, 12, 8, 12},
317 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 2, 10, 3, 4, 4, 9, 4, 10, 4, 12, 8,
319 std::array<std::uint8_t, 25>{16, 1, 2, 1, 9, 2, 10, 3, 4, 3, 9, 4, 10, 4, 12, 8,
321 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 2, 2, 10, 3, 4, 4, 10, 4, 12, 8,
323 std::array<std::uint8_t, 25>{8, 4, 5, 4, 12, 5, 8, 8, 12},
324 std::array<std::uint8_t, 25>{12, 0, 9, 4, 5, 4, 9, 4, 12, 5, 8, 8, 12},
325 std::array<std::uint8_t, 25>{12, 1, 4, 1, 10, 4, 12, 5, 8, 5, 10, 8, 12},
326 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 10, 4, 9, 4, 12, 5, 8, 5, 10, 8,
328 std::array<std::uint8_t, 25>{12, 2, 5, 2, 10, 4, 10, 4, 12, 5, 8, 8, 12},
329 std::array<std::uint8_t, 25>{16, 0, 9, 2, 5, 2, 10, 4, 9, 4, 10, 4, 12, 5, 8, 8,
331 std::array<std::uint8_t, 25>{12, 1, 2, 1, 4, 2, 5, 4, 12, 5, 8, 8, 12},
332 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 2, 2, 5, 4, 9, 4, 12, 5, 8, 8,
334 std::array<std::uint8_t, 25>{10, 3, 4, 4, 5, 4, 12, 5, 8, 8, 12},
335 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 3, 4, 4, 5, 4, 9, 4, 12, 5, 8, 8,
337 std::array<std::uint8_t, 25>{16, 1, 9, 1, 10, 3, 4, 3, 9, 4, 12, 5, 8, 5, 10, 8,
339 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 10, 3, 4, 4, 12, 5, 8, 5, 10, 8,
341 std::array<std::uint8_t, 25>{14, 2, 5, 2, 10, 3, 4, 4, 10, 4, 12, 5, 8, 8, 12},
342 std::array<std::uint8_t, 25>{20, 0, 3, 0, 9, 2, 5, 2, 10, 3, 4,
343 4, 9, 4, 10, 4, 12, 5, 8, 8, 12},
344 std::array<std::uint8_t, 25>{16, 1, 2, 1, 9, 2, 5, 3, 4, 3, 9, 4, 12, 5, 8, 8,
346 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 2, 2, 5, 3, 4, 4, 12, 5, 8, 8,
348 std::array<std::uint8_t, 25>{8, 4, 11, 4, 12, 6, 11, 8, 12},
349 std::array<std::uint8_t, 25>{12, 0, 9, 4, 9, 4, 11, 4, 12, 6, 11, 8, 12},
350 std::array<std::uint8_t, 25>{10, 1, 4, 4, 11, 4, 12, 6, 11, 8, 12},
351 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 4, 4, 9, 4, 11, 4, 12, 6, 11, 8,
353 std::array<std::uint8_t, 25>{12, 2, 10, 4, 10, 4, 11, 4, 12, 6, 11, 8, 12},
354 std::array<std::uint8_t, 25>{16, 0, 9, 2, 10, 4, 9, 4, 10, 4, 11, 4, 12, 6, 11,
356 std::array<std::uint8_t, 25>{16, 1, 2, 1, 4, 2, 10, 4, 10, 4, 11, 4, 12, 6, 11,
358 std::array<std::uint8_t, 25>{20, 0, 1, 0, 9, 1, 2, 2, 10, 4, 9,
359 4, 10, 4, 11, 4, 12, 6, 11, 8, 12},
360 std::array<std::uint8_t, 25>{12, 3, 4, 3, 6, 4, 11, 4, 12, 6, 11, 8, 12},
361 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 3, 6, 4, 9, 4, 11, 4, 12, 6, 11, 8,
363 std::array<std::uint8_t, 25>{16, 1, 4, 1, 9, 3, 6, 3, 9, 4, 11, 4, 12, 6, 11, 8,
365 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 4, 3, 6, 4, 11, 4, 12, 6, 11, 8,
367 std::array<std::uint8_t, 25>{16, 2, 10, 3, 4, 3, 6, 4, 10, 4, 11, 4, 12, 6, 11,
369 std::array<std::uint8_t, 25>{20, 0, 3, 0, 9, 2, 10, 3, 6, 4, 9,
370 4, 10, 4, 11, 4, 12, 6, 11, 8, 12},
371 std::array<std::uint8_t, 25>{20, 1, 2, 1, 9, 2, 10, 3, 6, 3, 9,
372 4, 10, 4, 11, 4, 12, 6, 11, 8, 12},
373 std::array<std::uint8_t, 25>{20, 0, 1, 0, 3, 1, 2, 2, 10, 3, 6,
374 4, 10, 4, 11, 4, 12, 6, 11, 8, 12},
375 std::array<std::uint8_t, 25>{12, 4, 5, 4, 11, 4, 12, 5, 8, 6, 11, 8, 12},
376 std::array<std::uint8_t, 25>{16, 0, 9, 4, 5, 4, 9, 4, 11, 4, 12, 5, 8, 6, 11, 8,
378 std::array<std::uint8_t, 25>{16, 1, 4, 1, 10, 4, 11, 4, 12, 5, 8, 5, 10, 6, 11,
380 std::array<std::uint8_t, 25>{20, 0, 1, 0, 9, 1, 10, 4, 9, 4, 11,
381 4, 12, 5, 8, 5, 10, 6, 11, 8, 12},
382 std::array<std::uint8_t, 25>{16, 2, 5, 2, 10, 4, 10, 4, 11, 4, 12, 5, 8, 6, 11,
384 std::array<std::uint8_t, 25>{20, 0, 9, 2, 5, 2, 10, 4, 9, 4, 10,
385 4, 11, 4, 12, 5, 8, 6, 11, 8, 12},
386 std::array<std::uint8_t, 25>{16, 1, 2, 1, 4, 2, 5, 4, 11, 4, 12, 5, 8, 6, 11, 8,
388 std::array<std::uint8_t, 25>{20, 0, 1, 0, 9, 1, 2, 2, 5, 4, 9,
389 4, 11, 4, 12, 5, 8, 6, 11, 8, 12},
390 std::array<std::uint8_t, 25>{16, 3, 4, 3, 6, 4, 5, 4, 11, 4, 12, 5, 8, 6, 11, 8,
392 std::array<std::uint8_t, 25>{20, 0, 3, 0, 9, 3, 6, 4, 5, 4, 9,
393 4, 11, 4, 12, 5, 8, 6, 11, 8, 12},
394 std::array<std::uint8_t, 25>{20, 1, 9, 1, 10, 3, 6, 3, 9, 4, 11,
395 4, 12, 5, 8, 5, 10, 6, 11, 8, 12},
396 std::array<std::uint8_t, 25>{20, 0, 1, 0, 3, 1, 10, 3, 6, 4, 11,
397 4, 12, 5, 8, 5, 10, 6, 11, 8, 12},
398 std::array<std::uint8_t, 25>{20, 2, 5, 2, 10, 3, 4, 3, 6, 4, 10,
399 4, 11, 4, 12, 5, 8, 6, 11, 8, 12},
400 std::array<std::uint8_t, 25>{24, 0, 3, 0, 9, 2, 5, 2, 10, 3, 6, 4, 9,
401 4, 10, 4, 11, 4, 12, 5, 8, 6, 11, 8, 12},
402 std::array<std::uint8_t, 25>{20, 1, 2, 1, 9, 2, 5, 3, 6, 3, 9,
403 4, 11, 4, 12, 5, 8, 6, 11, 8, 12},
404 std::array<std::uint8_t, 25>{20, 0, 1, 0, 3, 1, 2, 2, 5, 3, 6,
405 4, 11, 4, 12, 5, 8, 6, 11, 8, 12},
406 std::array<std::uint8_t, 25>{8, 4, 7, 4, 12, 7, 8, 8, 12},
407 std::array<std::uint8_t, 25>{12, 0, 9, 4, 7, 4, 9, 4, 12, 7, 8, 8, 12},
408 std::array<std::uint8_t, 25>{10, 1, 4, 4, 7, 4, 12, 7, 8, 8, 12},
409 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 4, 4, 7, 4, 9, 4, 12, 7, 8, 8,
411 std::array<std::uint8_t, 25>{12, 2, 10, 4, 7, 4, 10, 4, 12, 7, 8, 8, 12},
412 std::array<std::uint8_t, 25>{16, 0, 9, 2, 10, 4, 7, 4, 9, 4, 10, 4, 12, 7, 8, 8,
414 std::array<std::uint8_t, 25>{16, 1, 2, 1, 4, 2, 10, 4, 7, 4, 10, 4, 12, 7, 8, 8,
416 std::array<std::uint8_t, 25>{20, 0, 1, 0, 9, 1, 2, 2, 10, 4, 7,
417 4, 9, 4, 10, 4, 12, 7, 8, 8, 12},
418 std::array<std::uint8_t, 25>{12, 3, 4, 3, 11, 4, 12, 7, 8, 7, 11, 8, 12},
419 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 3, 11, 4, 9, 4, 12, 7, 8, 7, 11, 8,
421 std::array<std::uint8_t, 25>{16, 1, 4, 1, 9, 3, 9, 3, 11, 4, 12, 7, 8, 7, 11, 8,
423 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 4, 3, 11, 4, 12, 7, 8, 7, 11, 8,
425 std::array<std::uint8_t, 25>{16, 2, 10, 3, 4, 3, 11, 4, 10, 4, 12, 7, 8, 7, 11,
427 std::array<std::uint8_t, 25>{20, 0, 3, 0, 9, 2, 10, 3, 11, 4, 9,
428 4, 10, 4, 12, 7, 8, 7, 11, 8, 12},
429 std::array<std::uint8_t, 25>{20, 1, 2, 1, 9, 2, 10, 3, 9, 3, 11,
430 4, 10, 4, 12, 7, 8, 7, 11, 8, 12},
431 std::array<std::uint8_t, 25>{20, 0, 1, 0, 3, 1, 2, 2, 10, 3, 11,
432 4, 10, 4, 12, 7, 8, 7, 11, 8, 12},
433 std::array<std::uint8_t, 25>{8, 4, 5, 4, 7, 5, 8, 7, 8},
434 std::array<std::uint8_t, 25>{12, 0, 9, 4, 5, 4, 7, 4, 9, 5, 8, 7, 8},
435 std::array<std::uint8_t, 25>{12, 1, 4, 1, 10, 4, 7, 5, 8, 5, 10, 7, 8},
436 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 10, 4, 7, 4, 9, 5, 8, 5, 10, 7,
438 std::array<std::uint8_t, 25>{12, 2, 5, 2, 10, 4, 7, 4, 10, 5, 8, 7, 8},
439 std::array<std::uint8_t, 25>{16, 0, 9, 2, 5, 2, 10, 4, 7, 4, 9, 4, 10, 5, 8, 7,
441 std::array<std::uint8_t, 25>{12, 1, 2, 1, 4, 2, 5, 4, 7, 5, 8, 7, 8},
442 std::array<std::uint8_t, 25>{16, 0, 1, 0, 9, 1, 2, 2, 5, 4, 7, 4, 9, 5, 8, 7,
444 std::array<std::uint8_t, 25>{12, 3, 4, 3, 11, 4, 5, 5, 8, 7, 8, 7, 11},
445 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 3, 11, 4, 5, 4, 9, 5, 8, 7, 8, 7,
447 std::array<std::uint8_t, 25>{16, 1, 9, 1, 10, 3, 9, 3, 11, 5, 8, 5, 10, 7, 8, 7,
449 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 10, 3, 11, 5, 8, 5, 10, 7, 8, 7,
451 std::array<std::uint8_t, 25>{16, 2, 5, 2, 10, 3, 4, 3, 11, 4, 10, 5, 8, 7, 8, 7,
453 std::array<std::uint8_t, 25>{20, 0, 3, 0, 9, 2, 5, 2, 10, 3, 11,
454 4, 9, 4, 10, 5, 8, 7, 8, 7, 11},
455 std::array<std::uint8_t, 25>{16, 1, 2, 1, 9, 2, 5, 3, 9, 3, 11, 5, 8, 7, 8, 7,
457 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 2, 2, 5, 3, 11, 5, 8, 7, 8, 7,
459 std::array<std::uint8_t, 25>{12, 4, 11, 4, 12, 6, 7, 6, 11, 7, 8, 8, 12},
460 std::array<std::uint8_t, 25>{16, 0, 9, 4, 9, 4, 11, 4, 12, 6, 7, 6, 11, 7, 8, 8,
462 std::array<std::uint8_t, 25>{14, 1, 4, 4, 11, 4, 12, 6, 7, 6, 11, 7, 8, 8, 12},
463 std::array<std::uint8_t, 25>{20, 0, 1, 0, 9, 1, 4, 4, 9, 4, 11,
464 4, 12, 6, 7, 6, 11, 7, 8, 8, 12},
465 std::array<std::uint8_t, 25>{16, 2, 10, 4, 10, 4, 11, 4, 12, 6, 7, 6, 11, 7, 8,
467 std::array<std::uint8_t, 25>{20, 0, 9, 2, 10, 4, 9, 4, 10, 4, 11,
468 4, 12, 6, 7, 6, 11, 7, 8, 8, 12},
469 std::array<std::uint8_t, 25>{20, 1, 2, 1, 4, 2, 10, 4, 10, 4, 11,
470 4, 12, 6, 7, 6, 11, 7, 8, 8, 12},
471 std::array<std::uint8_t, 25>{24, 0, 1, 0, 9, 1, 2, 2, 10, 4, 9, 4, 10,
472 4, 11, 4, 12, 6, 7, 6, 11, 7, 8, 8, 12},
473 std::array<std::uint8_t, 25>{12, 3, 4, 3, 6, 4, 12, 6, 7, 7, 8, 8, 12},
474 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 3, 6, 4, 9, 4, 12, 6, 7, 7, 8, 8,
476 std::array<std::uint8_t, 25>{16, 1, 4, 1, 9, 3, 6, 3, 9, 4, 12, 6, 7, 7, 8, 8,
478 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 4, 3, 6, 4, 12, 6, 7, 7, 8, 8,
480 std::array<std::uint8_t, 25>{16, 2, 10, 3, 4, 3, 6, 4, 10, 4, 12, 6, 7, 7, 8, 8,
482 std::array<std::uint8_t, 25>{20, 0, 3, 0, 9, 2, 10, 3, 6, 4, 9,
483 4, 10, 4, 12, 6, 7, 7, 8, 8, 12},
484 std::array<std::uint8_t, 25>{20, 1, 2, 1, 9, 2, 10, 3, 6, 3, 9,
485 4, 10, 4, 12, 6, 7, 7, 8, 8, 12},
486 std::array<std::uint8_t, 25>{20, 0, 1, 0, 3, 1, 2, 2, 10, 3, 6,
487 4, 10, 4, 12, 6, 7, 7, 8, 8, 12},
488 std::array<std::uint8_t, 25>{12, 4, 5, 4, 11, 5, 8, 6, 7, 6, 11, 7, 8},
489 std::array<std::uint8_t, 25>{16, 0, 9, 4, 5, 4, 9, 4, 11, 5, 8, 6, 7, 6, 11, 7,
491 std::array<std::uint8_t, 25>{16, 1, 4, 1, 10, 4, 11, 5, 8, 5, 10, 6, 7, 6, 11,
493 std::array<std::uint8_t, 25>{20, 0, 1, 0, 9, 1, 10, 4, 9, 4, 11,
494 5, 8, 5, 10, 6, 7, 6, 11, 7, 8},
495 std::array<std::uint8_t, 25>{16, 2, 5, 2, 10, 4, 10, 4, 11, 5, 8, 6, 7, 6, 11,
497 std::array<std::uint8_t, 25>{20, 0, 9, 2, 5, 2, 10, 4, 9, 4, 10,
498 4, 11, 5, 8, 6, 7, 6, 11, 7, 8},
499 std::array<std::uint8_t, 25>{16, 1, 2, 1, 4, 2, 5, 4, 11, 5, 8, 6, 7, 6, 11, 7,
501 std::array<std::uint8_t, 25>{20, 0, 1, 0, 9, 1, 2, 2, 5, 4, 9,
502 4, 11, 5, 8, 6, 7, 6, 11, 7, 8},
503 std::array<std::uint8_t, 25>{12, 3, 4, 3, 6, 4, 5, 5, 8, 6, 7, 7, 8},
504 std::array<std::uint8_t, 25>{16, 0, 3, 0, 9, 3, 6, 4, 5, 4, 9, 5, 8, 6, 7, 7,
506 std::array<std::uint8_t, 25>{16, 1, 9, 1, 10, 3, 6, 3, 9, 5, 8, 5, 10, 6, 7, 7,
508 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 10, 3, 6, 5, 8, 5, 10, 6, 7, 7,
510 std::array<std::uint8_t, 25>{16, 2, 5, 2, 10, 3, 4, 3, 6, 4, 10, 5, 8, 6, 7, 7,
512 std::array<std::uint8_t, 25>{20, 0, 3, 0, 9, 2, 5, 2, 10, 3, 6,
513 4, 9, 4, 10, 5, 8, 6, 7, 7, 8},
514 std::array<std::uint8_t, 25>{16, 1, 2, 1, 9, 2, 5, 3, 6, 3, 9, 5, 8, 6, 7, 7,
516 std::array<std::uint8_t, 25>{16, 0, 1, 0, 3, 1, 2, 2, 5, 3, 6, 5, 8, 6, 7, 7,
519 QuadKey key = derived().key(node);
520 auto depth = derived().depth(key);
521 auto center = derived().center(key);
522 auto half_length = derived().halfLength(key);
538 for (
unsigned i{}; 8 > i; ++i) {
539 idx |=
static_cast<unsigned>(distanceContainsSurface(nodes[i])) << i;
542 std::array<Point, 13> points{distance_[nodes[0].pos][nodes[0].offset].point,
543 distance_[nodes[1].pos][nodes[1].offset].point,
544 distance_[nodes[2].pos][nodes[2].offset].point,
545 distance_[nodes[3].pos][nodes[3].offset].point,
546 distance_[node.pos][node.offset].point,
547 distance_[nodes[4].pos][nodes[4].offset].point,
548 distance_[nodes[5].pos][nodes[5].offset].point,
549 distance_[nodes[6].pos][nodes[6].offset].point,
550 distance_[nodes[7].pos][nodes[7].offset].point,
551 center + Point(-half_length, -half_length),
552 center + Point(half_length, -half_length),
553 center + Point(-half_length, half_length),
554 center + Point(half_length, half_length)};
556 float distance = std::numeric_limits<float>::max();
557 for (
unsigned i = 1u; lut[idx][0] > i; i += 2) {
563 }
else if constexpr (3 == Dim) {
568 template <
class Geometry>
569 [[nodiscard]]
float distanceSomething(Index node, Geometry
const& query)
const
571 return std::sqrt(distanceSquared(node, query));
574 template <
class Geometry,
class Predicate =
pred::Leaf,
575 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
576 [[nodiscard]]
float distance(
577 Geometry
const& query, Predicate
const& pred =
pred::Leaf(),
578 DistanceInterpolate interpolate = DistanceInterpolate::ALL,
579 float max_distance = std::numeric_limits<float>::max(),
float epsilon = 0.0f,
580 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST)
const
582 return distance(derived().
index(), pred, query, interpolate, max_distance, epsilon,
586 template <
class NodeType,
class Pred,
class Geometry,
587 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true,
588 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
589 [[nodiscard]]
float distance(
590 NodeType node, Predicate
const& pred, Geometry
const& query,
591 DistanceInterpolate interpolate = DistanceInterpolate::ALL,
592 float max_distance = std::numeric_limits<float>::max(),
float epsilon = 0.0f,
593 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST)
const
599 template <
bool FastAsSonic,
class Geometry>
600 [[nodiscard]]
float distance(
601 Geometry
const& query, DistanceInterpolate interpolate = DistanceInterpolate::ALL,
602 float max_distance = std::numeric_limits<float>::max(),
float epsilon = 0.0f,
603 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST)
const
605 return distance<FastAsSonic>(derived().
index(), query, interpolate, max_distance,
606 epsilon, search_alg);
609 template <
bool FastAsSonic,
class NodeType,
class Geometry,
610 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true>
611 [[nodiscard]]
float distance(
612 NodeType node, Geometry
const& query,
613 DistanceInterpolate interpolate = DistanceInterpolate::ALL,
614 float max_distance = std::numeric_limits<float>::max(),
float epsilon = 0.0f,
615 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST)
const
617 auto n = derived().index(node);
621 auto value_f = [
this, &query](Index node) {
622 return derived().isLeaf(node)
623 ? std::numeric_limits<float>::infinity()
624 : [
this, &query](Index node) {
625 if constexpr (std::is_same_v<Vec<Dim, float>,
626 std::decay_t<Geometry>>) {
627 auto p = distance_[node.pos][node.offset].point;
641 auto inner_f = [
this, &query](Index node) {
642 if constexpr (std::is_same_v<Vec<Dim, float>, std::decay_t<Geometry>>) {
643 float x = UFO_CLAMP(query.x, distance_[node.pos].bounds(node.offset).min.x,
644 distance_[node.pos].bounds(node.offset).max.x);
645 float y = UFO_CLAMP(query.y, distance_[node.pos].bounds(node.offset).min.y,
646 distance_[node.pos].bounds(node.offset).max.y);
663 return std::sqrt(derived().
template nearest<true, FastAsSonic>(
664 n, search_alg, value_f, inner_f, max_distance, epsilon));
667 template <
class Predicate,
class Geometry,
668 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
669 [[nodiscard]] std::pair<float, Point> distancePoint(
670 Predicate
const& pred, Geometry
const& query,
671 DistanceInterpolate interpolate = DistanceInterpolate::ALL,
672 float max_distance = std::numeric_limits<float>::max(),
float epsilon = 0.0f,
673 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST)
const
675 return distancePoint(derived().
index(), pred, query, interpolate, max_distance,
676 epsilon, search_alg);
679 template <
class NodeType,
class Predicate,
class Geometry,
680 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true,
681 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
682 [[nodiscard]] std::pair<float, Point> distancePoint(
683 NodeType node, Predicate
const& pred, Geometry
const& query,
684 DistanceInterpolate interpolate = DistanceInterpolate::ALL,
685 float max_distance = std::numeric_limits<float>::max(),
float epsilon = 0.0f,
686 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST)
const
688 auto n = derived().index(node);
693 template <
bool FastAsSonic,
class Geometry>
694 [[nodiscard]] std::pair<float, Index> distancePoint(
695 Geometry
const& query, DistanceInterpolate interpolate = DistanceInterpolate::ALL,
696 float max_distance = std::numeric_limits<float>::max(),
float epsilon = 0.0f,
697 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST)
const
699 return distancePoint<FastAsSonic>(derived().
index(), query, interpolate, max_distance,
700 epsilon, search_alg);
703 template <
bool FastAsSonic,
class NodeType,
class Geometry,
704 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true>
705 [[nodiscard]] std::pair<float, Index> distancePoint(
706 NodeType node, Geometry
const& query,
707 DistanceInterpolate interpolate = DistanceInterpolate::ALL,
708 float max_distance = std::numeric_limits<float>::max(),
float epsilon = 0.0f,
709 NearestSearchAlgorithm search_alg = NearestSearchAlgorithm::DEPTH_FIRST)
const
711 auto n = derived().index(node);
715 auto value_f = [
this, &query](Index node) {
716 if constexpr (std::is_same_v<Vec<Dim, float>, std::decay_t<Geometry>>) {
717 auto p = distance_[node.pos][node.offset].point;
730 auto inner_f = [
this, &query](Index node) {
731 if constexpr (std::is_same_v<Vec<Dim, float>, std::decay_t<Geometry>>) {
732 float x = UFO_CLAMP(query.x, distance_[node.pos].bounds(node.offset).min.x,
733 distance_[node.pos].bounds(node.offset).max.x);
734 float y = UFO_CLAMP(query.y, distance_[node.pos].bounds(node.offset).min.y,
735 distance_[node.pos].bounds(node.offset).max.y);
752 auto [c_dist, c_node] = derived().template nearest<false, FastAsSonic>(
753 n, search_alg, value_f, inner_f, max_distance, epsilon);
756 return std::pair(std::sqrt(c_dist), c_node);
759 template <
class NodeType,
760 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true>
761 [[nodiscard]]
bool distanceContainsSurface(NodeType node)
const
763 auto n = derived().index(node);
764 return 0.0f < distance_[node.pos][node.offset].weight;
767 template <
class NodeType,
768 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true>
771 auto n = derived().index(node);
772 return distance_[n.pos][n.offset];
775 template <
class NodeType,
776 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true>
777 [[nodiscard]] DistanceBounds distanceBounds(NodeType node)
const
779 if constexpr (WithBounds) {
780 auto n = derived().index(node);
781 return distance_[n.pos].bounds(n.offset);
783 return derived().bounds(node);
793 template <
class NodeType,
794 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true>
798 assert(std::isfinite(info.weight));
800 DistanceBounds bounds;
802 if (0.0f >= info.weight) {
803 info = Block::resetInfo();
804 bounds = Block::resetBounds();
806 bounds = DistanceBounds(info.point, info.point);
809 auto node_f = [
this, &info, &bounds](Index node) {
810 distance_[node.pos][node.offset] = info;
811 distance_[node.pos].bounds(node.offset) = bounds;
814 auto block_f = [
this, &info, &bounds](pos_t pos) {
815 distance_[pos].fill(info, bounds);
818 if constexpr (std::is_same_v<std::decay_t<NodeType>, Index>) {
820 derived().recursParentFirst(node, node_f, block_f);
822 derived().recursLeaves(node, node_f, block_f);
826 auto update_f = [
this](Index node, pos_t children) {
827 onUpdateNode(node, children);
830 derived().recursLeaves(derived().code(node), node_f, block_f, update_f,
833 derived().recursParentFirst(derived().code(node), node_f, block_f);
838 template <
class NodeType,
839 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true>
840 void distanceSet(NodeType node, Point
const& point,
float weight = 1.0f,
841 bool propagate =
true)
846 template <
class NodeType,
class UnaryOp,
847 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true,
848 std::enable_if_t<std::is_invocable_r_v<DistanceInfo<Dim>, UnaryOp, Index>,
850 void distanceSet(NodeType node, UnaryOp unary_op,
bool propagate =
true)
852 auto node_f = [
this, unary_op](Index node) {
856 assert(std::isfinite(info.weight));
858 if (0.0f >= info.weight) {
859 distance_[node.pos].reset(node.offset);
861 distance_[node.pos][node.offset] = info;
862 distance_[node.pos].bounds(node.offset) = DistanceBounds(info.point, info.point);
866 auto block_f = [
this, node_f](pos_t pos) {
867 for (std::size_t i{}; BF > i; ++i) {
868 node_f(Index(pos, i));
872 auto update_f = [
this](Index node, pos_t children) { onUpdateNode(node, children); };
874 if constexpr (std::is_same_v<Index, std::decay_t<NodeType>>) {
876 derived().recursLeaves(node, node_f, block_f, update_f);
878 derived().recursLeaves(node, node_f, block_f);
881 derived().recursLeaves(derived().code(node), node_f, block_f, update_f, propagate);
885 template <
class NodeType,
886 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true>
887 void distanceUpdate(NodeType node, Point
const& point,
float weight = 1.0f,
888 bool propagate =
true)
891 assert(std::isfinite(
weight));
893 auto node_f = [
this, &point,
weight](Index node) {
896 auto w = cur.weight +
weight;
899 distance_[node.pos].reset(node.offset);
901 cur.point = cur.point * (cur.weight / w) + point * (
weight / w);
903 if constexpr (WithBounds) {
904 distance_[node.pos].bounds(node.offset) = DistanceBounds(cur.point, cur.point);
909 assert(std::isfinite(cur.weight));
912 auto block_f = [
this, node_f](pos_t pos) {
913 for (std::size_t i{}; BF > i; ++i) {
914 node_f(Index(pos, i));
918 auto update_f = [
this](Index node, pos_t children) { onUpdateNode(node, children); };
920 if constexpr (std::is_same_v<Index, std::decay_t<NodeType>>) {
922 derived().recursLeaves(node, node_f, block_f, update_f);
924 derived().recursLeaves(node, node_f, block_f);
927 derived().recursLeaves(derived().code(node), node_f, block_f, update_f, propagate);
931 template <
class NodeType,
932 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true>
933 void distanceReset(NodeType node,
bool propagate =
true)
935 auto info = Block::resetInfo();
936 distanceSet(node, info.point, info.weight, propagate);
939 template <
class NodeType,
class UnaryPred,
940 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true,
941 std::enable_if_t<std::is_invocable_r_v<bool, UnaryPred, Index>,
bool> =
true>
942 void distanceResetIf(NodeType node, UnaryPred p,
bool propagate =
true)
944 auto node_f = [
this, p](Index node) {
946 distance_[node.pos].reset(node.offset);
950 auto block_f = [
this, node_f](pos_t pos) {
951 for (std::size_t i{}; BF > i; ++i) {
952 node_f(Index(pos, i));
956 auto update_f = [
this](Index node, pos_t children) { onUpdateNode(node, children); };
958 if constexpr (std::is_same_v<Index, std::decay_t<NodeType>>) {
960 derived().recursLeaves(node, node_f, block_f, update_f);
962 derived().recursLeaves(node, node_f, block_f);
965 derived().recursLeaves(derived().code(node), node_f, block_f, update_f, propagate);
982 template <
class Derived2,
class Tree2,
bool WithBounds2>
984 : distance_(other.distance_)
988 template <
class Derived2,
class Tree2,
bool WithBounds2>
990 : distance_(std::move(other.distance_))
1012 template <
class Derived2,
class Tree2,
bool WithBounds2>
1015 distance_ = rhs.distance_;
1019 template <
class Derived2,
class Tree2,
bool WithBounds2>
1022 distance_ = std::move(rhs.distance_);
1032 void swap(
DistanceMap& other)
noexcept(
noexcept(distance_.swap(other.distance_)))
1034 distance_.swap(other.distance_);
1043 void createRoot() { distance_.emplace_back(); }
1051 [[nodiscard]]
constexpr Derived& derived() {
return *
static_cast<Derived*
>(
this); }
1053 [[nodiscard]]
constexpr Derived
const& derived()
const
1055 return *
static_cast<Derived const*
>(
this);
1070 void onCreateChildren(Index node)
1072 distance_.emplace_back(distance_[node.pos], node.offset);
1075 void onFillChildren(Index node, pos_t children)
1077 distance_[children].fill(distance_[node.pos], node.offset);
1080 void onPruneChildren(Index node, pos_t )
1083 auto const& info = distance_[node.pos][node.offset];
1084 distance_[node.pos].bounds(node.offset) =
1085 0.0f == info.weight ? Block::resetBounds()
1086 : DistanceBounds(info.point, info.point);
1089 void onReserve(std::size_t cap) { distance_.reserve(cap); }
1091 void onSetSize(std::size_t size) { distance_.setSize(size); }
1093 void onEnable(std::size_t num_blocks)
1096 distance_.resize(num_blocks, distance_[0]);
1099 void onDisable() { distance_.clear(); }
1101 void onUpdateNode(Index node, pos_t children)
1104 DistanceBounds bounds = Block::resetBounds();
1106 auto& c = distance_[children];
1107 for (std::size_t i{}; BF > i; ++i) {
1108 info.point += c[i].point * c[i].weight;
1109 info.weight += c[i].weight;
1110 if constexpr (WithBounds) {
1111 bounds.min =
min(bounds.min, c.bounds(i).min);
1112 bounds.max =
max(bounds.max, c.bounds(i).max);
1117 0.0f == info.weight ? Block::resetInfo().point : info.point / info.weight;
1119 distance_[node.pos][node.offset] = info;
1120 if constexpr (WithBounds) {
1121 distance_[node.pos].bounds(node.offset) = bounds;
1125 [[nodiscard]]
bool isPrunable(pos_t block)
const
1129 return std::all_of(begin(distance_[block].info()) + 1, end(distance_[block].info()),
1130 [v = distance_[block][0]](
auto const& e) {
return v == e; });
1137 [[nodiscard]]
static constexpr std::size_t serializedSizeNode()
noexcept
1142 [[nodiscard]]
constexpr std::size_t serializedSize(
1143 std::vector<std::pair<pos_t,
BitSet<BF>>>
const& ,
1144 std::size_t num_nodes)
const
1146 return num_nodes * serializedSizeNode();
1151 for (
auto [block, offset] : nodes) {
1153 in.read(distance_[block].info());
1154 for (offset_t i{}; BF > i; ++i) {
1155 distance_[block].bounds(i) =
1156 0.0f == distance_[block][i].weight
1157 ? Block::resetBounds()
1158 : DistanceBounds(distance_[block][i].point, distance_[block][i].point);
1161 for (offset_t i{}; BF > i; ++i) {
1163 in.read(distance_[block][i]);
1164 distance_[block].bounds(i) = 0.0f == distance_[block][i].weight
1165 ? Block::resetBounds()
1166 : DistanceBounds(distance_[block][i].point,
1167 distance_[block][i].point);
1176 for (
auto [block, offset] : nodes) {
1178 out.write(distance_[block].info());
1180 for (offset_t i{}; BF > i; ++i) {
1182 out.write(distance_[block][i]);
1193 void onDotFileInfo(std::ostream& out, Index node)
const
1195 out <<
"Distance: " << distanceInfo(node);