diff --git a/src/org/oscim/utils/quadtree/QuadTree.java b/src/org/oscim/utils/quadtree/QuadTree.java new file mode 100644 index 00000000..d8bfe19b --- /dev/null +++ b/src/org/oscim/utils/quadtree/QuadTree.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013 Hannes Janetzek + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.utils.quadtree; + +public class QuadTree { + public QuadTree parent; + public QuadTree child00; + public QuadTree child10; + public QuadTree child01; + public QuadTree child11; + + public T item; + + // id of this child relative to parent + byte id; + + // number of children and grandchildren + int refs = 0; + + public T get(int i){ + switch (i) { + case 0: + return (child00 != null) ? child00.item : null; + case 1: + return (child01 != null) ? child01.item : null; + case 2: + return (child10 != null) ? child10.item : null; + case 3: + return (child11 != null) ? child11.item : null; + } + return null; + } +} diff --git a/src/org/oscim/utils/quadtree/QuadTreeIndex.java b/src/org/oscim/utils/quadtree/QuadTreeIndex.java new file mode 100644 index 00000000..02e8e6be --- /dev/null +++ b/src/org/oscim/utils/quadtree/QuadTreeIndex.java @@ -0,0 +1,193 @@ +/* + * Copyright 2013 Hannes Janetzek + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.utils.quadtree; + +public abstract class QuadTreeIndex { + + + QuadTree pool; + + QuadTree root; + + public QuadTreeIndex() { + root = new QuadTree(); + root.parent = root; + } + + static boolean checkIndex(int x, int y, int z) { + if (x < 0 || x >= 1 << z) { + //Log.d(TAG, "invalid position"); + return false; + } + if (y < 0 || y >= 1 << z) { + //Log.d(TAG, "invalid position"); + return false; + } + return true; + } + + public abstract T create(int x, int y, int z); + + public abstract void remove(T item); + + public QuadTree add(int x, int y, int z) { + + if (!checkIndex(x, y, z)) + return null; + + QuadTree leaf = root; + + for (int level = z - 1; level >= 0; level--) { + + int id = ((x >> level) & 1) | ((y >> level) & 1) << 1; + + leaf.refs++; + + QuadTree cur = null; + + switch (id) { + case 0: + cur = leaf.child00; + break; + case 1: + cur = leaf.child01; + break; + case 2: + cur = leaf.child10; + break; + case 3: + cur = leaf.child11; + break; + } + + if (cur != null) { + leaf = cur; + continue; + } + + if (pool != null) { + cur = pool; + pool = pool.parent; + } else { + cur = new QuadTree(); + } + + cur.refs = 0; + cur.id = (byte) id; + cur.parent = leaf; + + switch (id) { + case 0: + cur.parent.child00 = cur; + break; + case 1: + cur.parent.child01 = cur; + break; + case 2: + cur.parent.child10 = cur; + break; + case 3: + cur.parent.child11 = cur; + break; + } + + leaf = cur; + } + + leaf.refs++; + + return leaf; + } + + public T getTile(int x, int y, int z) { + + if (!checkIndex(x, y, z)) + return null; + + QuadTree leaf = root; + + for (int level = z - 1; level >= 0; level--) { + + int id = ((x >> level) & 1) | ((y >> level) & 1) << 1; + + switch (id) { + case 0: + leaf = leaf.child00; + break; + case 1: + leaf = leaf.child01; + break; + case 2: + leaf = leaf.child10; + break; + case 3: + leaf = leaf.child11; + break; + } + + if (leaf == null) + return null; + + if (level == 0) { + return leaf.item; + } + } + return null; + } + + public boolean remove(QuadTree item) { + + QuadTree cur = item; + QuadTree next; + + for (; cur != root;) { + if (cur == null) + throw new IllegalArgumentException("QuadTree.remove: item not in index"); + + // keep pointer to parent + next = cur.parent; + cur.refs--; + + // if current node has no children + if (cur.refs == 0) { + // unhook from parent + + switch (cur.id) { + case 0: + next.child00 = null; + break; + case 1: + next.child01 = null; + break; + case 2: + next.child10 = null; + break; + case 3: + next.child11 = null; + break; + } + + // add item back to pool + cur.parent = pool; + pool = cur; + } + cur = next; + } + + root.refs--; + + return true; + } +}