PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/CS/migrated/branches/R0_16/include/csengine/quadtree.h

#
C++ Header | 302 lines | 86 code | 45 blank | 171 comment | 1 complexity | f82831f9d25438ab0ae63a1bb5384683 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. Copyright (C) 1998 by Jorrit Tyberghein
  3. Copyright (C) 2000 by Wouter Wijngaards
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free
  14. Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #ifndef QUADTREE_H
  17. #define QUADTREE_H
  18. #include "csgeom/math2d.h"
  19. #include "csgeom/math3d.h"
  20. #include "csgeom/box.h"
  21. /**
  22. * A quadtree node can be in three states: empty, full, or partial.
  23. * If empty or full the state of the children does not matter.
  24. * The unknown state is an error.
  25. * 4 child node states are stored in one byte.
  26. * 2 bits per node, in sequence.
  27. */
  28. #define CS_QUAD_EMPTY 0
  29. #define CS_QUAD_PARTIAL 1
  30. #define CS_QUAD_UNKNOWN 2
  31. #define CS_QUAD_FULL 3
  32. #define CS_QUAD_ALL_EMPTY 0x0 /* because CS_QUAD_EMPTY == 0 */
  33. #define CS_QUAD_ALL_FULL 0xFF /* because CS_QUAD_FULL == 3 */
  34. #define CS_QUAD_ALL_UNKNOWN 0xAA /* because CS_QUAD_FULL == 2 */
  35. class csQuadTree;
  36. class Dumper;
  37. /**
  38. * values denoting if the tree changed.
  39. * Note that false means no change, and a true value a change.
  40. */
  41. #define CS_QUAD_NOCHANGE 0
  42. #define CS_QUAD_POSSIBLECHANGE 1
  43. #define CS_QUAD_CERTAINCHANGE 2
  44. class csQuadTree;
  45. class node_pos_info;
  46. /**
  47. * QuadTree
  48. */
  49. class csQuadTree {
  50. friend class Dumper;
  51. private:
  52. /// bounding box of the quadtree
  53. csBox2 bbox;
  54. /// depth of the tree, 1 == 1 node only, a root.
  55. int max_depth;
  56. /// the state of the root node.
  57. int root_state;
  58. /** state of all children, and their children.
  59. * they are ordered like this:
  60. * /// Old style:
  61. * ///root has children in byte 0.
  62. * ///nodes in byte 0 have children in byte 0+node_nr+1(1,2,3,4).
  63. * ///nodes in byte 1 have children in byte 4+node_nr+1.
  64. * ///nodes in byte n have children in byte 4*n+node_nr+1
  65. * ///So for byte n, take 4*n + node_nr+1 as the new byte
  66. * New style:
  67. * nodes of depth 2, then all nodes of depth 3, etc.
  68. * nodes are sequentially stored (bytepacked) in the ordering
  69. * y*plane_size+x. The root node in depth 1 is stored in variable
  70. * root_state.
  71. */
  72. unsigned char* states;
  73. /// convenience variable: how many bytes alloced in states
  74. int state_size;
  75. /// This contains the info that designates thr position of a particular node.
  76. class node_pos_info {
  77. public:
  78. int offset; // index into states array
  79. // the offset -1 denotes the root node.
  80. int bytepos; // index into byte. [0..3]
  81. int depth; // depth into tree 1==root
  82. int plane_size; // width and height of square plane of nodes.
  83. int plane_start; // index in array where the node's at depth are located
  84. int node_x, node_y; // coordinates of the node in it's plane.
  85. // integer in the plane of leaves at node_depth.
  86. // note that above values are redundant.
  87. // offset = plane_start + (node_y * plane_size + node_x) / 4
  88. // bytepos = (node_y * plane_size + node_x) % 4
  89. // plane_size = 2**(depth-1)
  90. // plane_start = (4**(depth-1) -1 ) / 3
  91. // but it is easier to pass these values along.
  92. /// construct a pos info pointing to the root node.
  93. node_pos_info(void);
  94. /// clear the node_pos_info, to point to root node.
  95. void set_root(void);
  96. /// copy constructor
  97. node_pos_info(const node_pos_info &copy);
  98. };
  99. /** this function is used for traversing the quadtree.
  100. * it will get the nodes bounding box, state, and node_pos
  101. * all these are this node's values.
  102. * and custom clientdata.
  103. * It can return an integer.
  104. * node_depth==1 means you are the root, and so on,
  105. * if the node_depth == max_depth you are a leaf.
  106. */
  107. typedef int (csQuadTree::*quad_traverse_func)(csQuadTree* pObj,
  108. const csBox2& node_bbox, int node_state, node_pos_info *node_pos,
  109. void* data);
  110. /** private functions to help dealing with quadtree.
  111. * Call all four children. Of the node at parent_pos,
  112. * box is the bounding box of the parent node.
  113. * each child will be passed the data.
  114. * returns return values of children in retval.
  115. * in order 0=topleft, 1=topright, 2=bottomleft, 3=bottomright.
  116. * note that theoretically the state of the caller could be changed.
  117. * func is of type quad_traverse_func.
  118. */
  119. void CallChildren(quad_traverse_func func, csQuadTree* pObj,
  120. const csBox2& box, node_pos_info *parent_pos, void *data, int retval[4]);
  121. /** Convenience version, the retval argument is omitted, return values
  122. * are discarded.
  123. */
  124. void CallChildren(quad_traverse_func func, csQuadTree* pObj,
  125. const csBox2& box, node_pos_info *parent_pos, void *data);
  126. /** Get the state of a node, in byte offset , nodenr given.
  127. * offset -1 means root node.
  128. */
  129. int GetNodeState(int offset, int nodenr);
  130. /// convenience function to GetNodeState at node_pos_info
  131. inline int GetNodeState(node_pos_info *pos)
  132. {return GetNodeState(pos->offset, pos->bytepos);}
  133. /** Set the state of a node, in byte offset , nodenr given.
  134. * offset -1 means root node.
  135. */
  136. void SetNodeState(int offset, int nodenr, int newstate);
  137. /// convenience function to set a node state
  138. inline void SetNodeState(node_pos_info *pos, int newstate)
  139. {SetNodeState(pos->offset, pos->bytepos, newstate);}
  140. /** for a node, check if data (a csVector2 * )
  141. * is in this node, possibly recursing.
  142. * returning the QUAD_FULL/PARTIAL/EMPTY if it hits.
  143. * returning QUAD_UNKOWN if the point is not in the node.
  144. */
  145. int test_point_func(csQuadTree* pObj, const csBox2& node_bbox,
  146. int node_state, node_pos_info *node_pos, void* data);
  147. /** gather result from retval for testpoint
  148. */
  149. int GetTestPointResult(int retval[4]);
  150. /** struct with info for polygon being inserted
  151. */
  152. struct poly_info {
  153. csVector2* verts;
  154. int num_verts;
  155. const csBox2* pol_bbox;
  156. bool test_only;
  157. };
  158. /** for a node, insert polygon into it (possibly in its children too)
  159. * expects data to be a struct poly_info*
  160. * returns true if the polygon covered previously empty space.
  161. * thus, if the tree is modified. or if PARTIAL->PARTIAL.
  162. * Returns CS_QUAD_NOCHANGE if no change to the tree.
  163. * CS_QUAD_POSSIBLECHANGE if it probably changed, and
  164. * CS_QUAD_CERTAINCHANGE if it changed for certain.
  165. */
  166. int insert_polygon_func(csQuadTree* pObj, const csBox2& node_bbox,
  167. int node_state, node_pos_info *node_pos, void* data);
  168. /** gather result from retval for insertpolygon_func
  169. * NOCHANGE < POSSIBLECHANGE < CERTAINCHANGE
  170. */
  171. int GetPolygonResult(int retval[4]);
  172. /** for a node, mark it by casting (void*)data to an int.
  173. * that is the new state.
  174. */
  175. int mark_node_func (csQuadTree* pObj, const csBox2& node_bbox,
  176. int node_state, node_pos_info *node_pos, void* data);
  177. /** for a node, give it the (int) cast of data as value and
  178. * give children a good value. CS_QUAD_UNKNOWN means the
  179. * child's value is unchanged.
  180. */
  181. int propagate_func(csQuadTree* pObj, const csBox2& node_bbox,
  182. int node_state, node_pos_info *node_pos, void* data);
  183. /** Set the state of the node based on states of child nodes.
  184. * returns new node state, leaves only return their state.
  185. */
  186. int sift_func(csQuadTree* pObj, const csBox2& node_bbox,
  187. int node_state, node_pos_info *node_pos, void* data);
  188. public:
  189. /** create a quadtree of depth, using about (4**depth-1)/3-1/3 bytes.
  190. * depth must be >= 1
  191. * depth=1 is only the root.
  192. */
  193. csQuadTree(const csBox2& the_box, int the_depth);
  194. /// destroy quadtree
  195. ~csQuadTree();
  196. /**
  197. * Is the tree full?
  198. */
  199. bool IsFull () { return root_state == CS_QUAD_FULL; }
  200. /**
  201. * Make the tree empty again
  202. */
  203. void MakeEmpty();
  204. /**
  205. * Insert a polygon into the quad-tree.
  206. * Return true if the tree was modified (i.e. if parts of the
  207. * polygon were visible. More precisely:
  208. * Returns CS_QUAD_NOCHANGE if no change to the tree.
  209. * CS_QUAD_POSSIBLECHANGE if it probably changed, and
  210. * CS_QUAD_CERTAINCHANGE if it changed for certain.
  211. */
  212. int InsertPolygon (csVector2* verts, int num_verts,
  213. const csBox2& pol_bbox);
  214. /**
  215. * Test for polygon visibility with the quad-tree.
  216. * Returns CS_QUAD_NOCHANGE if no change to the tree.
  217. * CS_QUAD_POSSIBLECHANGE if it probably changed, and
  218. * CS_QUAD_CERTAINCHANGE if it changed for certain.
  219. */
  220. int TestPolygon (csVector2* verts, int num_verts,
  221. const csBox2& pol_bbox);
  222. /**
  223. * Test if a given point is visible in the quad-tree.
  224. * Returns CS_QUAD_FULL if not visible, CS_QUAD_EMPTY
  225. * if visible and CS_QUAD_PARTIAL if undecided.
  226. * This function returns CS_QUAD_UNKNOWN if the point is not
  227. * in the quadtree.
  228. */
  229. int TestPoint (const csVector2& point);
  230. /**
  231. * 4x4 bit array (2bytes) -> Quadtree of depth 3.
  232. * depth3 quadtree->4x4 array (partial -> empty)
  233. */
  234. /** a TestRectangle function that will test on leaf-coordinates, for full.
  235. * Give depth of the node-plane to test on, the x and y integer node coords
  236. * of the topleft corner of the rectangle, and it's width and height.
  237. * Returns true if and only if all nodes at that spot are CS_QUAD_FULL.
  238. * Note: You must have called Propagate() before using this method.
  239. */
  240. bool TestRectangle(int depth, int x, int y, int w, int h);
  241. /** Propagate, makes sure that all nodes in the tree get a value
  242. * repesenting their state. For speed reasons this is not always the case
  243. * after an InsertPolygon() call.
  244. */
  245. void Propagate(void);
  246. /** The leaves must have valid values. The other nodes are
  247. * given correct values.
  248. */
  249. void Sift(void);
  250. /** This function will print the quadtree...
  251. */
  252. void Print(void);
  253. };
  254. #endif /*QUADTREE_H*/