Advertisement
Guest User

Untitled

a guest
Mar 11th, 2020
2,280
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.00 KB | None | 0 0
  1. // *****************************************************************************
  2. // SmallList.hpp:
  3. // *****************************************************************************
  4. #ifndef SMALL_LIST_HPP
  5. #define SMALL_LIST_HPP
  6.  
  7. #include <cstdlib>
  8. #include <cstring>
  9. #include <cassert>
  10. #include <vector>
  11.  
  12. /// Stores a random-access sequence of elements similar to vector, but avoids
  13. /// heap allocations for small lists. T must be trivially constructible and
  14. /// destructible.
  15. template <class T>
  16. class SmallList
  17. {
  18. public:
  19.     // Creates an empty list.
  20.     SmallList();
  21.  
  22.     // Creates a copy of the specified list.
  23.     SmallList(const SmallList& other);
  24.  
  25.     // Copies the specified list.
  26.     SmallList& operator=(const SmallList& other);
  27.  
  28.     // Destroys the list.
  29.     ~SmallList();
  30.  
  31.     // Returns the number of agents in the list.
  32.     int size() const;
  33.  
  34.     // Returns the nth element.
  35.     T& operator[](int n);
  36.  
  37.     // Returns the nth element in the list.
  38.     const T& operator[](int n) const;
  39.  
  40.     // Returns an index to a matching element in the list or -1
  41.     // if the element is not found.
  42.     int find_index(const T& element) const;
  43.  
  44.     // Clears the list.
  45.     void clear();
  46.  
  47.     // Reserves space for n elements.
  48.     void reserve(int n);
  49.  
  50.     // Inserts an element to the back of the list.
  51.     void push_back(const T& element);
  52.  
  53.     /// Pops an element off the back of the list.
  54.     T pop_back();
  55.  
  56.     // Swaps the contents of this list with the other.
  57.     void swap(SmallList& other);
  58.  
  59.     // Returns a pointer to the underlying buffer.
  60.     T* data();
  61.  
  62.     // Returns a pointer to the underlying buffer.
  63.     const T* data() const;
  64.  
  65. private:
  66.     enum {fixed_cap = 256};
  67.     struct ListData
  68.     {
  69.         ListData();
  70.         T buf[fixed_cap];
  71.         T* data;
  72.         int num;
  73.         int cap;
  74.     };
  75.     ListData ld;
  76. };
  77.  
  78. /// Provides an indexed free list with constant-time removals from anywhere
  79. /// in the list without invalidating indices. T must be trivially constructible
  80. /// and destructible.
  81. template <class T>
  82. class FreeList
  83. {
  84. public:
  85.     /// Creates a new free list.
  86.     FreeList();
  87.  
  88.     /// Inserts an element to the free list and returns an index to it.
  89.     int insert(const T& element);
  90.  
  91.     // Removes the nth element from the free list.
  92.     void erase(int n);
  93.  
  94.     // Removes all elements from the free list.
  95.     void clear();
  96.  
  97.     // Returns the range of valid indices.
  98.     int range() const;
  99.  
  100.     // Returns the nth element.
  101.     T& operator[](int n);
  102.  
  103.     // Returns the nth element.
  104.     const T& operator[](int n) const;
  105.  
  106.     // Reserves space for n elements.
  107.     void reserve(int n);
  108.  
  109.     // Swaps the contents of the two lists.
  110.     void swap(FreeList& other);
  111.  
  112. private:
  113.     union FreeElement
  114.     {
  115.         T element;
  116.         int next;
  117.     };
  118.     SmallList<FreeElement> data;
  119.     int first_free;
  120. };
  121.  
  122. // ---------------------------------------------------------------------------------
  123. // SmallList Implementation
  124. // ---------------------------------------------------------------------------------
  125. template <class T>
  126. SmallList<T>::ListData::ListData(): data(buf), num(0), cap(fixed_cap)
  127. {
  128. }
  129.  
  130. template <class T>
  131. SmallList<T>::SmallList()
  132. {
  133. }
  134.  
  135. template <class T>
  136. SmallList<T>::SmallList(const SmallList& other)
  137. {
  138.     if (other.ld.cap == fixed_cap)
  139.     {
  140.         ld = other.ld;
  141.         ld.data = ld.buf;
  142.     }
  143.     else
  144.     {
  145.         reserve(other.ld.num);
  146.         for (int j=0; j < other.size(); ++j)
  147.             ld.data[j] = other.ld.data[j];
  148.         ld.num = other.ld.num;
  149.         ld.cap = other.ld.cap;
  150.     }
  151. }
  152.  
  153. template <class T>
  154. SmallList<T>& SmallList<T>::operator=(const SmallList<T>& other)
  155. {
  156.     SmallList(other).swap(*this);
  157.     return *this;
  158. }
  159.  
  160. template <class T>
  161. SmallList<T>::~SmallList()
  162. {
  163.     if (ld.data != ld.buf)
  164.         free(ld.data);
  165. }
  166.  
  167. template <class T>
  168. int SmallList<T>::size() const
  169. {
  170.     return ld.num;
  171. }
  172.  
  173. template <class T>
  174. T& SmallList<T>::operator[](int n)
  175. {
  176.     assert(n >= 0 && n < ld.num);
  177.     return ld.data[n];
  178. }
  179.  
  180. template <class T>
  181. const T& SmallList<T>::operator[](int n) const
  182. {
  183.     assert(n >= 0 && n < ld.num);
  184.     return ld.data[n];
  185. }
  186.  
  187. template <class T>
  188. int SmallList<T>::find_index(const T& element) const
  189. {
  190.     for (int j=0; j < ld.num; ++j)
  191.     {
  192.         if (ld.data[j] == element)
  193.             return j;
  194.     }
  195.     return -1;
  196. }
  197.  
  198. template <class T>
  199. void SmallList<T>::clear()
  200. {
  201.     ld.num = 0;
  202. }
  203.  
  204. template <class T>
  205. void SmallList<T>::reserve(int n)
  206. {
  207.     enum {type_size = sizeof(T)};
  208.     if (n > ld.cap)
  209.     {
  210.         if (ld.cap == fixed_cap)
  211.         {
  212.             ld.data = static_cast<T*>(malloc(n * type_size));
  213.             memcpy(ld.data, ld.buf, sizeof(ld.buf));
  214.         }
  215.         else
  216.             ld.data = static_cast<T*>(realloc(ld.data, n * type_size));
  217.         ld.cap = n;
  218.     }
  219. }
  220.  
  221. template <class T>
  222. void SmallList<T>::push_back(const T& element)
  223. {
  224.     if (ld.num >= ld.cap)
  225.         reserve(ld.cap * 2);
  226.     ld.data[ld.num++] = element;
  227. }
  228.  
  229. template <class T>
  230. T SmallList<T>::pop_back()
  231. {
  232.     return ld.data[--ld.num];
  233. }
  234.  
  235. template <class T>
  236. void SmallList<T>::swap(SmallList& other)
  237. {
  238.     ListData& ld1 = ld;
  239.     ListData& ld2 = other.ld;
  240.  
  241.     const int use_fixed1 = ld1.data == ld1.buf;
  242.     const int use_fixed2 = ld2.data == ld2.buf;
  243.  
  244.     const ListData temp = ld1;
  245.     ld1 = ld2;
  246.     ld2 = temp;
  247.  
  248.     if (use_fixed1)
  249.         ld2.data = ld2.buf;
  250.     if (use_fixed2)
  251.         ld1.data = ld1.buf;
  252. }
  253.  
  254. template <class T>
  255. T* SmallList<T>::data()
  256. {
  257.     return ld.data;
  258. }
  259.  
  260. template <class T>
  261. const T* SmallList<T>::data() const
  262. {
  263.     return ld.data;
  264. }
  265.  
  266. // ---------------------------------------------------------------------------------
  267. // FreeList Implementation
  268. // ---------------------------------------------------------------------------------
  269. template <class T>
  270. FreeList<T>::FreeList(): first_free(-1)
  271. {
  272. }
  273.  
  274. template <class T>
  275. int FreeList<T>::insert(const T& element)
  276. {
  277.     if (first_free != -1)
  278.     {
  279.         const int index = first_free;
  280.         first_free = data[first_free].next;
  281.         data[index].element = element;
  282.         return index;
  283.     }
  284.     else
  285.     {
  286.         FreeElement fe;
  287.         fe.element = element;
  288.         data.push_back(fe);
  289.         return data.size() - 1;
  290.     }
  291. }
  292.  
  293. template <class T>
  294. void FreeList<T>::erase(int n)
  295. {
  296.     assert(n >= 0 && n < data.size());
  297.     data[n].next = first_free;
  298.     first_free = n;
  299. }
  300.  
  301. template <class T>
  302. void FreeList<T>::clear()
  303. {
  304.     data.clear();
  305.     first_free = -1;
  306. }
  307.  
  308. template <class T>
  309. int FreeList<T>::range() const
  310. {
  311.     return data.size();
  312. }
  313.  
  314. template <class T>
  315. T& FreeList<T>::operator[](int n)
  316. {
  317.     return data[n].element;
  318. }
  319.  
  320. template <class T>
  321. const T& FreeList<T>::operator[](int n) const
  322. {
  323.     return data[n].element;
  324. }
  325.  
  326. template <class T>
  327. void FreeList<T>::reserve(int n)
  328. {
  329.     data.reserve(n);
  330. }
  331.  
  332. template <class T>
  333. void FreeList<T>::swap(FreeList& other)
  334. {
  335.     const int temp = first_free;
  336.     data.swap(other.data);
  337.     first_free = other.first_free;
  338.     other.first_free = temp;
  339. }
  340.  
  341. #endif
  342.  
  343. // *****************************************************************************
  344. // UGrid.hpp
  345. // *****************************************************************************
  346. #ifndef UGRID_HPP
  347. #define UGRID_HPP
  348.  
  349. #include "SmallList.hpp"
  350.  
  351. struct UGridElt
  352. {
  353.     // Stores the next element in the cell.
  354.     int next;
  355.  
  356.     // Stores the ID of the element. This can be used to associate external
  357.     // data to the element.
  358.     int id;
  359.  
  360.     // Stores the center position of the uniformly-sized element.
  361.     float mx, my;
  362. };
  363.  
  364. struct UGridRow
  365. {
  366.     // Stores all the elements in the grid row.
  367.     FreeList<UGridElt> elts;
  368.  
  369.     // Stores all the cells in the row. Each cell stores an index pointing to
  370.     // the first element in that cell, or -1 if the cell is empty.
  371.     int* cells;
  372.  
  373.     // Stores the number of elements in the row.
  374.     int num_elts;
  375. };
  376.  
  377. struct UGrid
  378. {
  379.     // Stores all the rows in the grid.
  380.     UGridRow* rows;
  381.  
  382.     // Stores the number of columns, rows, and cells in the grid.
  383.     int num_cols, num_rows, num_cells;
  384.  
  385.     // Stores the inverse size of a cell.
  386.     float inv_cell_w, inv_cell_h;
  387.  
  388.     // Stores the half-size of all elements stored in the grid.
  389.     float hx, hy;
  390.  
  391.     // Stores the upper-left corner of the grid.
  392.     float x, y;
  393.  
  394.     // Stores the size of the grid.
  395.     float w, h;
  396. };
  397.  
  398. // Returns a new grid storing elements that have a uniform upper-bound size. Because
  399. // all elements are treated uniformly-sized for the sake of search queries, each one
  400. // can be stored as a single point in the grid.
  401. UGrid* ugrid_create(float hx, float hy, float cell_w, float cell_h,
  402.                     float l, float t, float r, float b);
  403.  
  404. // Destroys the grid.
  405. void ugrid_destroy(UGrid* grid);
  406.  
  407. // Returns the grid cell X index for the specified position.
  408. int ugrid_cell_x(const UGrid* grid, float x);
  409.  
  410. // Returns the grid cell Y index for the specified position.
  411. int ugrid_cell_y(const UGrid* grid, float y);
  412.  
  413. // Inserts an element to the grid.
  414. void ugrid_insert(UGrid* grid, int id, float mx, float my);
  415.  
  416. // Removes an element from the grid.
  417. void ugrid_remove(UGrid* grid, int id, float mx, float my);
  418.  
  419. // Moves an element in the grid from the former position to the new one.
  420. void ugrid_move(UGrid* grid, int id, float prev_mx, float prev_my, float mx, float my);
  421.  
  422. // Returns all the element IDs that intersect the specified rectangle excluding
  423. // elements with the specified ID to omit.
  424. SmallList<int> ugrid_query(const UGrid* grid, float mx, float my, float hx, float hy, int omit_id);
  425.  
  426. // Returns true if the specified element position is inside the grid boundaries.
  427. bool ugrid_in_bounds(const UGrid* grid, float mx, float my);
  428.  
  429. // Optimizes the grid, rearranging the memory of the grid to allow cache-friendly
  430. // cell traversal.
  431. void ugrid_optimize(UGrid* grid);
  432.  
  433. #endif
  434.  
  435. // *****************************************************************************
  436. // UGrid.cpp
  437. // *****************************************************************************
  438. #include "UGrid.hpp"
  439. #include <cmath>
  440.  
  441. static int ceil_div(float value, float divisor)
  442. {
  443.     // Returns the value divided by the divisor rounded up.
  444.     const float resultf = value / divisor;
  445.     const int result = (int)resultf;
  446.     return result < resultf ? result+1: result;
  447. }
  448.  
  449. static int min_int(int a, int b)
  450. {
  451.     assert(sizeof(int) == 4);
  452.     a -= b;
  453.     a &= a >> 31;
  454.     return a + b;
  455. }
  456.  
  457. static int max_int(int a, int b)
  458. {
  459.     assert(sizeof(int) == 4);
  460.     a -= b;
  461.     a &= (~a) >> 31;
  462.     return a + b;
  463. }
  464.  
  465. static int to_cell_idx(float val, float inv_cell_size, int num_cells)
  466. {
  467.     const int cell_pos = (int)(val * inv_cell_size);
  468.     return min_int(max_int(cell_pos, 0), num_cells - 1);
  469. }
  470.  
  471. UGrid* ugrid_create(float hx, float hy, float cell_w, float cell_h,
  472.                     float l, float t, float r, float b)
  473. {
  474.     const float w = r - l, h = b - t;
  475.     const int num_cols = ceil_div(w, cell_w), num_rows = ceil_div(h, cell_h);
  476.  
  477.     UGrid* grid = new UGrid;
  478.     grid->num_cols = num_cols;
  479.     grid->num_rows = num_rows;
  480.     grid->num_cells = num_cols * num_rows;
  481.     grid->inv_cell_w = 1.0f / cell_w;
  482.     grid->inv_cell_h = 1.0f / cell_w;
  483.     grid->x = l;
  484.     grid->y = t;
  485.     grid->h = w;
  486.     grid->w = h;
  487.     grid->hx = hx;
  488.     grid->hy = hy;
  489.  
  490.     grid->rows = new UGridRow[num_rows];
  491.     for (int r=0; r < num_rows; ++r)
  492.     {
  493.         grid->rows[r].cells = new int[num_cols];
  494.         for (int c=0; c < num_cols; ++c)
  495.             grid->rows[r].cells[c] = -1;
  496.     }
  497.     return grid;
  498. }
  499.  
  500. void ugrid_destroy(UGrid* grid)
  501. {
  502.     for (int r=0; r < grid->num_rows; ++r)
  503.         delete[] grid->rows[r].cells;
  504.     delete[] grid->rows;
  505.     delete grid;
  506. }
  507.  
  508. int ugrid_cell_x(const UGrid* grid, float x)
  509. {
  510.     return to_cell_idx(x - grid->x, grid->inv_cell_w, grid->num_cols);
  511. }
  512.  
  513. int ugrid_cell_y(const UGrid* grid, float y)
  514. {
  515.     return to_cell_idx(y - grid->y, grid->inv_cell_h, grid->num_rows);
  516. }
  517.  
  518. void ugrid_insert(UGrid* grid, int id, float mx, float my)
  519. {
  520.     const int cell_x = ugrid_cell_x(grid, mx);
  521.     const int cell_y = ugrid_cell_y(grid, my);
  522.     UGridRow* row = &grid->rows[cell_y];
  523.     int* cell = &row->cells[cell_x];
  524.  
  525.     const UGridElt new_elt = {*cell, id, mx, my};
  526.     *cell = row->elts.insert(new_elt);
  527. }
  528.  
  529. void ugrid_remove(UGrid* grid, int id, float mx, float my)
  530. {
  531.     const int cell_x = ugrid_cell_x(grid, mx);
  532.     const int cell_y = ugrid_cell_y(grid, my);
  533.     UGridRow* row = &grid->rows[cell_y];
  534.  
  535.     int* link = &row->cells[cell_x];
  536.     while (row->elts[*link].id != id)
  537.         link = &row->elts[*link].next;
  538.  
  539.     const int idx = *link;
  540.     *link = row->elts[idx].next;
  541.     row->elts.erase(idx);
  542. }
  543.  
  544. void ugrid_move(UGrid* grid, int id, float prev_mx, float prev_my, float mx, float my)
  545. {
  546.     const int prev_cell_x = ugrid_cell_x(grid, prev_mx);
  547.     const int prev_cell_y = ugrid_cell_y(grid, prev_my);
  548.     const int next_cell_x = ugrid_cell_x(grid, mx);
  549.     const int next_cell_y = ugrid_cell_y(grid, my);
  550.     UGridRow* prev_row = &grid->rows[prev_cell_y];
  551.  
  552.     if (next_cell_x == prev_cell_y && next_cell_x == next_cell_y)
  553.     {
  554.         // If the element will still belong in the same cell, simply update its position.
  555.         int elt_idx = prev_row->cells[prev_cell_x];
  556.         while (prev_row->elts[elt_idx].id != id)
  557.             elt_idx = prev_row->elts[elt_idx].next;
  558.  
  559.         // Update the element's position.
  560.         prev_row->elts[elt_idx].mx = mx;
  561.         prev_row->elts[elt_idx].my = my;
  562.     }
  563.     else
  564.     {
  565.         // Otherwise if the element will move to another cell, remove it first from the
  566.         // previous cell and insert it to the new one.
  567.         UGridRow* next_row = &grid->rows[next_cell_y];
  568.         int* link = &prev_row->cells[prev_cell_x];
  569.         while (prev_row->elts[*link].id != id)
  570.             link = &prev_row->elts[*link].next;
  571.  
  572.         // Remove the element from the previous cell and row.
  573.         const int elt_idx = *link;
  574.         UGridElt elt = prev_row->elts[elt_idx];
  575.         *link = prev_row->elts[elt_idx].next;
  576.         prev_row->elts.erase(elt_idx);
  577.  
  578.         // Update the element's position.
  579.         prev_row->elts[elt_idx].mx = mx;
  580.         prev_row->elts[elt_idx].my = my;
  581.  
  582.         // Insert it to the new row and cell.
  583.         elt.next = next_row->cells[next_cell_x];
  584.         next_row->cells[next_cell_x] = next_row->elts.insert(elt);
  585.     }
  586. }
  587.  
  588. SmallList<int> ugrid_query(const UGrid* grid, float mx, float my, float hx, float hy, int omit_id)
  589. {
  590.     // Expand the size of the query by the upper-bound uniform size of the elements. This
  591.     // expansion is what allows us to find elements based only on their point.
  592.     const float fx = hx + grid->hx;
  593.     const float fy = hy + grid->hy;
  594.  
  595.     // Find the cells that intersect the search query.
  596.     const int min_x = ugrid_cell_x(grid, mx - fx);
  597.     const int min_y = ugrid_cell_y(grid, my - fy);
  598.     const int max_x = ugrid_cell_x(grid, mx + fx);
  599.     const int max_y = ugrid_cell_y(grid, my + fy);
  600.  
  601.     // Find the elements that intersect the search query.
  602.     SmallList<int> res;
  603.     for (int y = min_y; y <= max_y; ++y)
  604.     {
  605.         const UGridRow* row = &grid->rows[y];
  606.         for (int x = min_x; x <= max_x; ++x)
  607.         {
  608.             int elt_idx = row->cells[x];
  609.             while (elt_idx != -1)
  610.             {
  611.                 const UGridElt* elt = &row->elts[elt_idx];
  612.                 if (elt_idx != omit_id && fabs(mx - elt->mx) <= fx && fabs(my - elt->my) <= fy)
  613.                     res.push_back(elt_idx);
  614.                 elt_idx = row->elts[elt_idx].next;
  615.             }
  616.         }
  617.     }
  618.     return res;
  619. }
  620.  
  621. bool ugrid_in_bounds(const UGrid* grid, float mx, float my)
  622. {
  623.     mx -= grid->x;
  624.     my -= grid->y;
  625.     const float x1 = mx-grid->hx, y1 = my-grid->hy;
  626.     const float x2 = mx+grid->hx, y2 = my+grid->hy;
  627.     return x1 >= 0.0f && x2 < grid->w && y1 >= 0.0f && y2 < grid->h;
  628. }
  629.  
  630. void ugrid_optimize(UGrid* grid)
  631. {
  632.     for (int r=0; r < grid->num_rows; ++r)
  633.     {
  634.         FreeList<UGridElt> new_elts;
  635.         UGridRow* row = &grid->rows[r];
  636.         new_elts.reserve(row->num_elts);
  637.         for (int c=0; c < grid->num_cols; ++c)
  638.         {
  639.             // Replace links to the old elements list to links in the new
  640.             // cache-friendly element list.
  641.             SmallList<int> new_elt_idxs;
  642.             int* link = &row->cells[c];
  643.             while (*link != -1)
  644.             {
  645.                 const UGridElt* elt = &row->elts[*link];
  646.                 new_elt_idxs.push_back(new_elts.insert(*elt));
  647.                 *link = elt->next;
  648.             }
  649.             for (int j=0; j < new_elt_idxs.size(); ++j)
  650.             {
  651.                 const int new_elt_idx = new_elt_idxs[j];
  652.                 new_elts[new_elt_idx].next = *link;
  653.                 *link = new_elt_idx;
  654.             }
  655.         }
  656.         // Swap the new element list with the old one.
  657.         row->elts.swap(new_elts);
  658.     }
  659. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement