216 | | return GetInRange(pos - CFixedVector2D(range, range), pos + CFixedVector2D(range, range)); |
| 215 | ENSURE(range >= entity_pos_t::FromInt(0)); |
| 216 | |
| 217 | u32 i0 = GetI0(pos.X - range); |
| 218 | u32 j0 = GetJ0(pos.Y - range); |
| 219 | u32 i1 = GetI1(pos.X + range); |
| 220 | u32 j1 = GetJ1(pos.Y + range); |
| 221 | for (u32 j = j0; j <= j1; ++j) |
| 222 | { |
| 223 | for (u32 i = i0; i <= i1; ++i) |
| 224 | { |
| 225 | std::vector<T>& div = m_Divisions.at(i + j*m_DivisionsW); |
| 226 | if (!div.empty()) |
| 227 | { |
| 228 | if (OverlapBoxCircle(GetPos0(i,j), GetPos1(i,j), pos, range)) |
| 229 | { |
| 230 | ret.insert(ret.end(), div.begin(), div.end()); |
| 231 | } |
| 232 | } |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | // Remove duplicates |
| 237 | std::sort(ret.begin(), ret.end()); |
| 238 | ret.erase(std::unique(ret.begin(), ret.end()), ret.end()); |
| 239 | |
| 240 | return ret; |
| 278 | // Helper functions for translating division indexes into the coordinates |
| 279 | // of the corresponding division rectangle. |
| 280 | CFixedVector2D GetPos0(u32 i, u32 j) |
| 281 | { |
| 282 | return CFixedVector2D(m_DivisionSize * (int)i, m_DivisionSize * (int)j); |
| 283 | } |
| 284 | |
| 285 | CFixedVector2D GetPos1(u32 i, u32 j) |
| 286 | { |
| 287 | return CFixedVector2D(m_DivisionSize * (int)(i+1), m_DivisionSize * (int)(j+1)); |
| 288 | } |
| 289 | |
| 290 | // Helper function to determine whether (the area of) an axis aligned box specified |
| 291 | // by posMin and posMax overlaps with (the area of) a circle defined by center and radius. |
| 292 | bool OverlapBoxCircle(CFixedVector2D posMin, CFixedVector2D posMax, CFixedVector2D c, entity_pos_t r) |
| 293 | { |
| 294 | // distance of c from X/Y slab corresponding to the box (negative if inside) |
| 295 | entity_pos_t distX = std::max(posMin.X - c.X, c.X - posMax.X); |
| 296 | entity_pos_t distY = std::max(posMin.Y - c.Y, c.Y - posMax.Y); |
| 297 | |
| 298 | if (distX <= entity_pos_t::Zero()) |
| 299 | { |
| 300 | // within X slab; overlap if not too far from Y-boundary of box |
| 301 | return distY <= r; |
| 302 | } |
| 303 | else if (distY <= entity_pos_t::Zero()) |
| 304 | { |
| 305 | // within Y slab; overlap if not too far from X-boundary of box |
| 306 | return distX <= r; |
| 307 | } |
| 308 | else |
| 309 | { |
| 310 | // neither within X or Y slab; overlap if not too far from corner point |
| 311 | return CFixedVector2D(distX, distY).CompareLength(r) <= 0; |
| 312 | } |
| 313 | } |
| 314 | |