#include <stdlib.h> #include <stdio.h> #include <assert.h> // search_box 时候还需要判断是否有叶子节点。没有的话。则不返回该非叶子节点。 // delete #define QUAD_SUB_NODE_COUNT 4 enum { NE, // 0 NW, // 1 SW, // 2 SE, // 3 }; bool overlap_box (int v1_minx, int v1_miny, int v1_maxx, int v1_maxy, int v2_minx, int v2_miny, int v2_maxx, int v2_maxy) { //return (this->_min._x > rv._max._x || this->_max._x < rv._min._x || // this->_min._y > rv._max._y || this->_max._y < rv._min._y) ? // false : true; return !(v1_minx > v2_maxx || v1_maxx < v2_minx || v1_miny >v2_maxy || v1_maxy <v2_miny); // ? false : true; } bool at_point (int v1_minx, int v1_miny, int v1_maxx, int v1_maxy, int v2_minx, int v2_miny, int v2_maxx, int v2_maxy) { return (v1_minx == v2_minx && v1_maxx == v2_maxx && v1_miny == v2_miny && v1_maxy == v2_maxy); } #include <list> struct Node; struct Leaf_Node { Node * _parent; typedef std::list <void *> List; List data_list; }; struct Node { void init (Node * parent) { _parent = parent; _leaf_node = 0; _sub[NE] = 0; _sub[NW] = 0; _sub[SW] = 0; _sub[SE] = 0; } void set (int min_x, int min_y, int max_x, int max_y) { _min_x = min_x; _min_y = min_y; _max_x = max_x; _max_y = max_y; } bool has_child () { return _sub[NE] != 0; } bool is_sub_empty () { return !(_sub[NE]->_sub[NE] && //_sub[NE]->_sub[NW] && //_sub[NE]->_sub[SW] && //_sub[NE]->_sub[SE] && _sub[NW]->_sub[NE] && //_sub[NW]->_sub[NW] && //_sub[NW]->_sub[SW] && //_sub[NW]->_sub[SE] && _sub[SW]->_sub[NE] && //_sub[SW]->_sub[NW] && //_sub[SW]->_sub[SW] && //_sub[SW]->_sub[SE] && _sub[SE]->_sub[NE] //&& //_sub[SE]->_sub[NW] && //_sub[SE]->_sub[SW] && //_sub[SE]->_sub[SE] ); } void create_child () { _sub[NE] = (Node *) malloc (sizeof Node); _sub[NW] = (Node *) malloc (sizeof Node); _sub[SW] = (Node *) malloc (sizeof Node); _sub[SE] = (Node *) malloc (sizeof Node); _sub[NE]->init (this); _sub[NW]->init (this); _sub[SW]->init (this); _sub[SE]->init (this); _sub[NE]->_index_in_parent = NE; _sub[NW]->_index_in_parent = NW; _sub[SW]->_index_in_parent = SW; _sub[SE]->_index_in_parent = SE; int center_x = (_max_x + _min_x) >> 1; /// 2; int center_y = (_max_y + _min_y) >> 1; /// 2; _sub[NE]->set (center_x, center_y, _max_x, _max_y); _sub[NW]->set (_min_x, center_y, center_x, _max_y); _sub[SW]->set (_min_x, _min_y, center_x, center_y); _sub[SE]->set (center_x, _min_y, _max_x, center_y); } Node * _sub[QUAD_SUB_NODE_COUNT]; Node * _parent; int _index_in_parent; Leaf_Node * _leaf_node; int _min_x; int _min_y; int _max_x; int _max_y; //int x; //int y; }; // 回调 typedef int (* search_box_callback) (Node * node); class Quadtree { public: Quadtree () { _root = 0; _depth = 6; } // 初始化 四叉树大小 void init (int width, int height) { _width = width; _height = height; _root = (Node *) malloc (sizeof Node); _root->init (0); _root->set (0, 0, width, height); } // 递归销毁 void destroy (Node * curr_node) { if (curr_node) { if (curr_node->has_child()) { destroy (curr_node->_sub[NE]); destroy (curr_node->_sub[NW]); destroy (curr_node->_sub[SW]); destroy (curr_node->_sub[SE]); } free (curr_node); } } // 在x, y上插入四叉树 void insert (int x, int y) { assert (x <= _width && y <=_height); //int deep = 5; _insert (_root, x, y, 0, 0, _width, _height, _depth); } // 判断点在哪个象限,然后再往那个象限细分。 void _insert (Node * curr_node, int x, int y, int min_x, int min_y, int max_x, int max_y, int deep) { if (deep <= 0) { // 到了最深层了。该结束了。 if (x >= min_x && x <= max_x && y >= min_y && y <= max_y) { printf ("add leaf: (%d,%d) (%d,%d)/n", min_x, min_y, max_x, max_y); if (!curr_node->_leaf_node) { Leaf_Node * leaf = new Leaf_Node; leaf->_parent = curr_node; curr_node->_leaf_node = leaf; } } return ; } if (! curr_node->has_child ()) { curr_node->create_child (); } int center_x = (max_x + min_x) >> 1; // / 2; int center_y = (max_y + min_y) >> 1; // / 2; if (x < center_x) { if (y < center_y) { // 设置子节点 //curr_node->_sub[SW]->set (min_x, min_y, center_x, center_y); //_insert (curr_node->_sub[SW], x, y, // min_x, min_y, center_x, center_y, -- deep); _insert (curr_node->_sub[SW], x, y, curr_node->_sub[SW]->_min_x, curr_node->_sub[SW]->_min_y, curr_node->_sub[SW]->_max_x, curr_node->_sub[SW]->_max_y, -- deep); printf ("insert SW sub node: (%d, %d), (%d, %d)/n", min_x, min_y, center_x, center_y); } else { //curr_node->_sub[NW]->set (min_x, center_y, center_x, max_y); //_insert (curr_node->_sub[NW], x, y, // min_x, center_y, center_x, max_y, -- deep); _insert (curr_node->_sub[NW], x, y, curr_node->_sub[NW]->_min_x, curr_node->_sub[NW]->_min_y, curr_node->_sub[NW]->_max_x, curr_node->_sub[NW]->_max_y, -- deep); printf ("insert NW sub node: (%d, %d), (%d, %d)/n", min_x, center_y, center_x, max_y); } } else { if (y < center_y) { //curr_node->_sub[SE]->set (center_x, min_y, max_x, center_y); //_insert (curr_node->_sub[SE], x, y, // center_x, min_y, max_x, center_y, -- deep); _insert (curr_node->_sub[SE], x, y, curr_node->_sub[SE]->_min_x, curr_node->_sub[SE]->_min_y, curr_node->_sub[SE]->_max_x, curr_node->_sub[SE]->_max_y, -- deep); printf ("insert SE sub node: (%d, %d), (%d, %d)/n", center_x, min_y, max_x, center_y); } else { //curr_node->_sub[NE]->set (center_x, center_y, max_x, max_y); //_insert (curr_node->_sub[NE], x, y, // center_x, center_y, max_x, max_y, -- deep); _insert (curr_node->_sub[NE], x, y, curr_node->_sub[NE]->_min_x, curr_node->_sub[NE]->_min_y, curr_node->_sub[NE]->_max_x, curr_node->_sub[NE]->_max_y, -- deep); printf ("insert NE sub node: (%d, %d), (%d, %d)/n", center_x, center_y, max_x, max_y); } } } // 搜索的次数还是太多。当一个空节点的时候。 void search_box (int x, int y, int dx, int dy, search_box_callback cb) { _search_box (_root, /*x, y,*/ x-dx, y-dy, x+dx, y+dy, cb); } void _search_box (Node * node, /*int x, int y,*/ int min_x, int min_y, int max_x, int max_y, search_box_callback cb) { printf ("search_box/n"); if (overlap_box (min_x, min_y, max_x, max_y, node->_min_x, node->_min_y, node->_max_x, node->_max_y)) { if (node->has_child()) { _search_box (node->_sub[NE], /*x, y,*/ min_x, min_y, max_x, max_y, cb); _search_box (node->_sub[NW],/* x, y,*/ min_x, min_y, max_x, max_y, cb); _search_box (node->_sub[SW], /*x, y,*/ min_x, min_y, max_x, max_y, cb); _search_box (node->_sub[SE], /*x, y,*/ min_x, min_y, max_x, max_y, cb); } // 不再有子节点。说明已经是叶子了。可以返回给上一层了。 else { if (node->_leaf_node) { printf ("search_box finded: "); cb (node); } } } } void search_line (int x, int y, int end_x, int end_y, search_box_callback cb) { int min_x = x < end_x ? x: end_x; int min_y = y < end_y ? y: end_y; int max_x = x > end_x ? x : end_x; int max_y = y > end_y ? y : end_y; // 斜率 float h = ((float) max_y - (float)min_y) / ((float)max_x - (float)min_x); _search_line (_root, h, x, y, min_x, min_y, max_x, max_y, cb); } void _search_line (Node * curr_node, float h, int x, int y, // x, y, h用来算一个点在不在一个直线上 int min_x, int min_y, int max_x, int max_y, search_box_callback cb) { printf ("search_line/n"); if (overlap_box (min_x, min_y, max_x, max_y, curr_node->_min_x, curr_node->_min_y, curr_node->_max_x, curr_node->_max_y)) { if (curr_node->has_child()) { _search_line (curr_node->_sub[NE], h, x, y, min_x, min_y, max_x, max_y, cb); _search_line (curr_node->_sub[NW], h, x, y, min_x, min_y, max_x, max_y, cb); _search_line (curr_node->_sub[SW], h, x, y, min_x, min_y, max_x, max_y, cb); _search_line (curr_node->_sub[SE], h, x, y, min_x, min_y, max_x, max_y, cb); } // 不再有子节点。说明已经是叶子了。可以返回给上一层了。 else { // 是否在直线内,并且有叶子节点 if (abs((float)(curr_node->_min_y) - (float)y - ((float)(curr_node->_min_x) - (float)x) * h) < 0.01f) { if (curr_node->_leaf_node) { printf ("search_line finded: "); cb (curr_node); } } } } } void _delete_empty_node (Node * node) { printf ("_delete_empty_node/n"); if (_root == node) { return; } // 上一层的其他子节点没有叶子了。 if (!(node->_parent->_sub[NE]->_leaf_node || node->_parent->_sub[NW]->_leaf_node || node->_parent->_sub[SW]->_leaf_node || node->_parent->_sub[SE]->_leaf_node)) { Node * parent = node->_parent; free (parent->_sub[NE]); free (parent->_sub[NW]); free (parent->_sub[SW]); free (parent->_sub[SE]); parent->_sub[NE] = 0; parent->_sub[NW] = 0; parent->_sub[SW] = 0; parent->_sub[SE] = 0; _delete_empty_node (parent); } } void delete_node (Leaf_Node * leaf/*, Node * curr_node*/) { Node * in_node = leaf->_parent; in_node->_leaf_node = 0; delete leaf; _delete_empty_node (in_node); } Node * get_node (int x, int y) { return _search (x, y, x+1, y+1, _root); } // 搜索的次数还是太多。当一个空节点的时候。 Node * _search (int min_x, int min_y, int max_x, int max_y, Node * curr_node) { printf ("_search() /n"); if (overlap_box (min_x, min_y, max_x, max_y, curr_node->_min_x, curr_node->_min_y, curr_node->_max_x, curr_node->_max_y)) { if (curr_node->_leaf_node) { if (at_point (min_x, min_y, max_x, max_y, curr_node->_min_x, curr_node->_min_y, curr_node->_max_x, curr_node->_max_y)) { printf ("find! %d %d/n", min_x, min_y); return curr_node; } } if (curr_node->has_child()) { printf ("serach :(%d,%d):(%d,%d)/n", min_x, min_y, max_x, max_y); for (int i = 0; i < QUAD_SUB_NODE_COUNT; i ++) { Node * ret = _search(min_x, min_y, max_x, max_y, curr_node->_sub[i]); if (ret) { return ret; } } } } return 0; } // 递归打印 void dump (Node * node, int deep = 0) { if (node) { for (int i = 0; i < deep; i ++) { printf ("+"); } printf ("minx: %d, miny: %d, maxx: %d, maxy: %d/n", node->_min_x, node->_min_y, node->_max_x, node->_max_y); if (node->has_child()) { dump (node->_sub[NE], ++deep); dump (node->_sub[NW], deep); dump (node->_sub[SW], deep); dump (node->_sub[SE], deep); } } } // 获取root Node * root () { return _root; } protected: Node * _root; int _width; int _height; int _depth; };