00001
00024 #ifndef GALOIS_GRAPH_SPATIALTREE_H
00025 #define GALOIS_GRAPH_SPATIALTREE_H
00026
00027 namespace Galois {
00028 namespace Graph {
00029
00032 template<typename T>
00033 class SpatialTree2d {
00034 struct Box2d {
00035 double xmin;
00036 double ymin;
00037 double xmax;
00038 double ymax;
00039
00040 double xmid() const { return (xmin + xmax) / 2.0; }
00041 double ymid() const { return (ymin + ymax) / 2.0; }
00042
00043 void decimate(int quad, double midx, double midy) {
00044 if (quad & 1)
00045 xmin = midx;
00046 else
00047 xmax = midx;
00048 if (quad & 2)
00049 ymin = midy;
00050 else
00051 ymax = midy;
00052 }
00053 };
00054 struct Node {
00055
00056 T val;
00057 double x, y;
00058
00059
00060 double midx, midy;
00061
00062 Node* children[4];
00063
00064 Node(const T& v, double _x, double _y) :val(v), x(_x), y(_y) {
00065 children[0] = children[1] = children[2] = children[3] = 0;
00066 }
00067
00068 void setCenter(double cx, double cy) {
00069 midx = cx;
00070 midy = cy;
00071 }
00072
00073 int getQuad(double _x, double _y) {
00074 int retval = 0;
00075 if (_x > midx) retval += 1;
00076 if (_y > midy) retval += 2;
00077 return retval;
00078 }
00079 };
00080
00081 Galois::Runtime::MM::FSBGaloisAllocator<Node> nodeAlloc;
00082
00083 Node* root;
00084 Box2d bounds;
00085
00086
00087 bool closer(double x, double y, double testx, double testy, double oldx, double oldy) const {
00088 double doldx = x - oldx;
00089 double doldy = y - oldy;
00090 double dtestx = x - testx;
00091 double dtesty = y - testy;
00092 doldx *= doldx;
00093 doldy *= doldy;
00094 dtestx *= dtestx;
00095 dtesty *= dtesty;
00096 return (dtestx + dtesty) < (doldx + doldy);
00097 }
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 T* recfind(Node* n, double x, double y) {
00115 Node* best = 0;
00116 while (n) {
00117 if (!best || closer(x, y, n->x, n->y, best->x, best->y))
00118 best = n;
00119
00120 int quad = n->getQuad(x,y);
00121 n = n->children[quad];
00122 }
00123 return &best->val;
00124 }
00125
00126 void recinsert(Node** pos, Box2d b, Node* node) {
00127 if (!*pos) {
00128
00129 node->setCenter(b.xmid(), b.ymid());
00130 if (__sync_bool_compare_and_swap(pos, 0, node))
00131 return;
00132 }
00133
00134 int quad = (*pos)->getQuad(node->x, node->y);
00135 b.decimate(quad, (*pos)->midx, (*pos)->midy);
00136 recinsert(&(*pos)->children[quad], b, node);
00137 }
00138
00139 Node* mkNode(const T& v, double x, double y) {
00140 Node* n = nodeAlloc.allocate(1);
00141 nodeAlloc.construct(n, Node(v,x,y));
00142 return n;
00143
00144 }
00145
00146 void delNode(Node* n) {
00147 nodeAlloc.destroy(n);
00148 nodeAlloc.deallocate(n, 1);
00149
00150 }
00151
00152 void freeTree(Node* n) {
00153 if (!n) return;
00154 for (int x = 0; x < 4; ++x)
00155 freeTree(n->children[x]);
00156 delNode(n);
00157 }
00158
00159 public:
00160 SpatialTree2d(double xmin = 0.0, double ymin = 0.0, double xmax = 0.0, double ymax = 0.0)
00161 :root(0) {
00162 init(xmin, ymin, xmax, ymax);
00163 }
00164
00165 ~SpatialTree2d() {
00166 freeTree(root);
00167 root = 0;
00168 }
00169
00170 void init(double xmin, double ymin, double xmax, double ymax) {
00171 bounds.xmin = xmin;
00172 bounds.ymin = ymin;
00173 bounds.xmax = xmax;
00174 bounds.ymax = ymax;
00175 }
00176
00178 T* find(double x, double y) {
00179 assert(root);
00180 return recfind(root, x, y);
00181 }
00182
00185 void insert(double x, double y, const T& v) {
00186 recinsert(&root, bounds, mkNode(v,x,y));
00187 }
00188
00189 };
00190
00191 }
00192 }
00193
00194 #endif