Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
FLAGS = -std=c++11 -O3 -Wall -Werror
LIBS = -lrt

all: example.out
all: example.out wrap-example.out
example.out: test/example.cpp
${CXX} $(FLAGS) -o $@ $^ $(LIBS)
wrap-example.out: test/wrap-example.cpp
${CXX} $(FLAGS) -o $@ $^ $(LIBS)
chaff-init:
git subtree add --prefix src/chaff https://github.com/xavierholt/chaff.git master --squash
git subtree add --prefix src/chaff https://github.com/xavierholt/chaff.git master --squash
chaff-pull:
git subtree pull --prefix src/chaff https://github.com/xavierholt/chaff.git master --squash
git subtree pull --prefix src/chaff https://github.com/xavierholt/chaff.git master --squash
clean:
rm -f example.out
rm -f example.out wrap-example.out
14 changes: 9 additions & 5 deletions src/nodes/all.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,27 @@ template <typename CORE> class Node;
template <typename CORE> class Leaf;
template <typename CORE> class Tree;
template <typename CORE> class Twig;
template <typename CORE> class Wrap;

#include "node.h"
#include "leaf.h"
#include "tree.h"
#include "twig.h"
#include "wrap.h"

template <typename CORE>
Node<CORE>* Tree<CORE>::insert(const typename CORE::Item& item) {
int c = child(CORE::point(item));
if(mNodes[c]) {
mNodes[c] = mNodes[c]->insert(item);
const Coord c = CORE::coordinate(CORE::point(item), this->mAxis);
const int i = (c > this->mMidpoint);

if(mNodes[i]) {
mNodes[i] = mNodes[i]->insert(item);
}
else if(this->mDepth + 1 < CORE::MAX_DEPTH) {
mNodes[c] = new Twig<CORE>(this, item);
mNodes[i] = new Twig<CORE>(this, item);
}
else {
mNodes[c] = new Leaf<CORE>(this, item);
mNodes[i] = new Leaf<CORE>(this, item);
}

return this;
Expand Down
4 changes: 4 additions & 0 deletions src/nodes/leaf.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ template <class CORE> class Leaf : public Node<CORE>
mItems[0] = item;
}

Leaf* asLeaf() {
return this;
}

public:
~Leaf() {
delete [] mItems;
Expand Down
7 changes: 6 additions & 1 deletion src/nodes/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ template <class CORE> class Node
mMidpoint = (mMinima[mAxis] + mMaxima[mAxis]) / 2;
}

Node(const Point& min, const Point& max): mDepth(0), mAxis(0) {
Node(const Point& min, const Point& max, int depth = 0): mDepth(depth), mAxis(depth % CORE::DIMENSIONS) {
for(int i = 0; i < CORE::DIMENSIONS; ++i) {
mMinima[i] = CORE::coordinate(min, i);
mMaxima[i] = CORE::coordinate(max, i);
Expand All @@ -59,6 +59,11 @@ template <class CORE> class Node
return result;
}

virtual Leaf<CORE>* asLeaf() {return 0;}
virtual Tree<CORE>* asTree() {return 0;}
virtual Twig<CORE>* asTwig() {return 0;}
virtual Wrap<CORE>* asWrap() {return 0;}

public:
virtual ~Node() {
// Nothing to do.
Expand Down
24 changes: 13 additions & 11 deletions src/nodes/tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ template <class CORE> class Tree : public Node<CORE>
mNodes[1] = 0;
}

int child(const Point& point) const {
return (CORE::coordinate(point, this->mAxis) > this->mMidpoint);
Tree* asTree() {
return this;
}

public:
Expand All @@ -37,9 +37,11 @@ template <class CORE> class Tree : public Node<CORE>
Node<CORE>* insert(const Item& item);

Node<CORE>* remove(const Item& item) {
int c = child(CORE::point(item));
if(mNodes[c]) {
mNodes[c] = mNodes[c]->remove(item);
const Coord c = CORE::coordinate(CORE::point(item), this->mAxis);
const int i = (c > this->mMidpoint);

if(mNodes[i]) {
mNodes[i] = mNodes[i]->remove(item);
if(mNodes[0] == 0 && mNodes[1] == 0 && this->mDepth != 0) {
delete this;
return 0;
Expand All @@ -50,15 +52,15 @@ template <class CORE> class Tree : public Node<CORE>
}

void search(const Point& point, Finder& finder) const {
Coord diff = CORE::coordinate(point, this->mAxis) - this->mMidpoint;
int idx = (diff > 0);
const Coord d = CORE::coordinate(point, this->mAxis) - this->mMidpoint;
const int i = (d > 0);

if(mNodes[idx]) {
mNodes[idx]->search(point, finder);
if(mNodes[i]) {
mNodes[i]->search(point, finder);
}

if(diff * diff < finder.score() && mNodes[idx ^ 1]) {
mNodes[idx ^ 1]->search(point, finder);
if(d * d < finder.score() && mNodes[i ^ 1]) {
mNodes[i ^ 1]->search(point, finder);
}
}
};
4 changes: 4 additions & 0 deletions src/nodes/twig.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ template <class CORE> class Twig : public Node<CORE>
mItems[0] = item;
}

Twig* asTwig() {
return this;
}

public:
Node<CORE>* insert(const Item& item) {
if(mCount >= CORE::STORAGE) {
Expand Down
75 changes: 75 additions & 0 deletions src/nodes/wrap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
template <class CORE> class Wrap : public Node<CORE>
{
typedef typename CORE::Item Item;
typedef typename CORE::Point Point;
typedef typename CORE::Coord Coord;
typedef Chaff::MinFinder<Item,Coord> Finder;

protected:
Node<CORE>* mChild;

protected:
Wrap(const Point& min, const Point& max, int wraps, int depth): Node<CORE>(min, max, depth) {
if(wraps > 1) {
mChild = new Wrap<CORE>(min, max, wraps - 1, depth + 1);
}
else {
mChild = new Tree<CORE>(min, max);
}
}

Wrap* asWrap() {
return this;
}

template <class T>
static T mod(T num, T dnm) {
num -= int(num / dnm) * dnm;
return num + dnm * (num < 0);
}

public:
Wrap(const Point& min, const Point& max, int wraps = CORE::DIMENSIONS): Node<CORE>(min, max) {
if(wraps > 1) {
mChild = new Wrap<CORE>(min, max, wraps - 1, 1);
}
else {
mChild = new Tree<CORE>(min, max);
}
}

~Wrap() {
delete mChild;
}

Node<CORE>* insert(const Item& item) {
mChild->insert(item);
return this;
}

Node<CORE>* remove(const Item& item) {
mChild->remove(item);
return this;
}

void search(const Point& point, Finder& finder) const {
const Coord min = this->mMinima[this->mAxis];
const Coord max = this->mMaxima[this->mAxis];
const Coord rng = max - min;
const Coord val = mod(point[this->mAxis] - min, rng) + min;

Point scratch(point);
scratch[this->mAxis] = val;
mChild->search(scratch, finder);

if(finder.score() > val - min) {
scratch[this->mAxis] = val + rng;
mChild->search(scratch, finder);
}

if(finder.score() > max - val) {
scratch[this->mAxis] = val - rng;
mChild->search(scratch, finder);
}
}
};
46 changes: 46 additions & 0 deletions test/wrap-example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "../src/tree.h"
#include <iostream>

struct Point
{
float data[3];

Point() {}
Point(float x, float y, float z) {
data[0] = x;
data[1] = y;
data[2] = z;
}

float& operator [] (int i) {
return data[i];
}

float operator [] (int i) const {
return data[i];
}

bool operator == (const Point& p) const {
return data[0] == p[0] && data[1] == p[1] && data[2] == p[2];
}

friend std::ostream& operator << (std::ostream& s, const Point& p) {
return s << '(' << p[0] << ", " << p[1] << ", " << p[2] << ')';
}
};

int main() {
typedef KD::Core<3, Point> CORE;

Point min(0, 0, 0);
Point max(8, 8, 8);
KD::Wrap<CORE> kdtree(min, max);

kdtree.insert(Point(1, 2, 3));
kdtree.insert(Point(8, 2, 5));
kdtree.insert(Point(1, 0, 8));
kdtree.insert(Point(3, 1, 4));

std::cout << kdtree.nearest(Point(8, 8, 8)) << std::endl;
return 0;
}