Post date: Aug 18, 2016 12:47:34 PM
My kdtree composes of kdnodes. Each kdnode has a struct, kd, in it which holds the pointers to Parent, Left and Right kdnodes. Following are the defintions;
struct kd {
int axis;
T x;
unsigned int ClId;
bool checked;
bool orientation;
kdnode<T>* Parent;
kdnode<T>* Left;
kdnode<T>* Right;
kd(){}
};
Note that there is no archiving in the struct. The next level is the kdnode which holds the above struct.
template <class T>
class kdnode
{
public:
friend class boost::serialization::access;
unsigned int id; // node id
kd<T> channel[KD_CHANNELS]; // B = [0]; G = [1]; R = [2];
template<class Archive>
void save(Archive& ar, const unsigned int version) const
{
// std::cout << "Save" << std::endl;
ar.register_type(static_cast<kdnode<T>*>(NULL));
ar & id;
for (int i = 0; i < KD_CHANNELS; i++)
{
ar & channel[i].axis;
ar & channel[i].x;
ar & channel[i].ClId;
ar & channel[i].checked;
ar & channel[i].orientation;
kdnode<T>* tleft = static_cast<kdnode<T>*>(channel[i].Left);
kdnode<T>* tright = static_cast<kdnode<T>*>(channel[i].Right);
ar & tleft;
ar & tright;
}
}
template<class Archive>
void load(Archive& ar, const unsigned int version)
{
// std::cout << "Load" << std::endl;
ar.register_type(static_cast<kdnode<T>*>(NULL));
ar & id;
for (int i = 0; i < KD_CHANNELS; i++)
{
ar & channel[i].axis;
ar & channel[i].x;
ar & channel[i].ClId;
ar & channel[i].checked;
ar & channel[i].orientation;
kdnode<T>* tleft;
kdnode<T>* tright;
ar & tleft;
ar & tright;
if (tleft)
{
tleft->channel[i].Parent = this;
}
if (tright)
{
tright->channel[i].Parent = this;
}
channel[i].Left = tleft;
channel[i].Right = tright;
}
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
Note that archiving of the kd struct is not done in the kd struct but in the kdnode because the kd structs are in an array. The final class is that of the kdtree.
template <class T>
class kdtree
{
public:
friend class boost::serialization::access;
kdnode<T>* Root;
float kd_min;
kdnode<T>* nearest_neighbour;
int KD_id; // stores the node id to be assigned to the next node inserted
kdnode<T>* List[KD_MAX_POINTS];
int nList;
kdnode<T>* CheckedNodes[KD_MAX_POINTS];
int checked_nodes;
T x_min, x_max;
cv::Mat max_boundary, min_boundary; // bool CV_8U
int n_boundary;
int ChannelNum;
LARGE_INTEGER TimeStart, TimeFinish;
LARGE_INTEGER CounterFreq;
template<class Archive>
void save(Archive& ar, const unsigned int version) const
{
ar & Root;
ar & kd_min;
ar & nearest_neighbour;
ar & KD_id;
ar & List;
ar & nList;
ar & CheckedNodes;
ar & checked_nodes;
ar & x_min;
ar & x_max;
ar & max_boundary;
ar & min_boundary;
ar & n_boundary;
ar & ChannelNum;
}
template<class Archive>
void load(Archive& ar, const unsigned int version)
{
ar & Root;
ar & kd_min;
ar & nearest_neighbour;
ar & KD_id;
ar & List;
ar & nList;
ar & CheckedNodes;
ar & checked_nodes;
ar & x_min;
ar & x_max;
ar & max_boundary;
ar & min_boundary;
ar & n_boundary;
ar & ChannelNum;
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
Only the Root is important. The rest are variables I use in the tree to support different methods. Now for the save and load routines.
template <class T>
void save_tree(KDTREE<T>* t, const char * filename){
// make an archive
std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);
std::cout << "save_tree with " << filename << std::endl;
oa << const_cast<const KDTREE<cv::Mat>&>(*t);
}
template <class T>
void restore_tree(KDTREE<T>* t, const char * filename)
{
// open the archive
std::ifstream ifs(filename);
try
{
boost::archive::text_iarchive ia(ifs);
// restore the schedule from the archive
std::cout << "restore_tree with " << filename << std::endl;
ia >> *t;
}
catch (boost::archive::archive_exception & ex)
{
std::cerr << ex.what() << std::endl;
}
}
The try and catch in the restore_tree routine is not strictly necessary.
Also, I started with using the binary archive, i.e.
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
instead of
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
but the restore_tree routine crashed Using the text archive routine did not show such problems. I may put this on the ToDo list but for the time being I am going with the text archive.