3dpcp/.svn/pristine/02/0266ada4f3e0365a9d424292ae86bd3186b49387.svn-base
2012-10-24 11:28:22 +02:00

849 lines
28 KiB
Text

/*
* compacttree implementation
*
* Copyright (C) Jan Elseberg, Kai Lingemann, Jan Elseberg
*
* Released under the GPL version 3.
*
*/
/**
* @file
* @brief Efficient representation of an octree
* @author Jan Elsberg. Automation Group, Jacobs University Bremen gGmbH, Germany.
* @author Kai Lingemann. Institute of Computer Science, University of Osnabrueck, Germany.
* @author Andreas Nuechter. Institute of Computer Science, University of Osnabrueck, Germany.
*/
#include <stdio.h>
#include <vector>
using std::vector;
#include <deque>
using std::deque;
#include <set>
using std::set;
#include <list>
using std::list;
#include <iostream>
#include <fstream>
#include <string>
#include "slam6d/globals.icc"
#include "slam6d/point_type.h"
#include "slam6d/Boctree.h"
#include "show/compacttree.h"
#include "show/colormanager.h"
#include "show/scancolormanager.h"
#include "show/viewcull.h"
using namespace show;
compactTree::~compactTree(){
delete alloc;
delete[] mins;
delete[] maxs;
}
void compactTree::AllPoints( cbitoct &node, vector<double*> &vp, double center[3], double size) {
double ccenter[3];
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
tshort *point = children->getPoints();
lint length = children->getLength();
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
double *p = new double[3];
//cout << point[0] << " " << point[1] << " " << point[2] << endl;
for (unsigned int k = 0; k < 3; k++){
p[k] = point[k] * precision + ccenter[k];
}
vp.push_back(p);
point+=POINTDIM;
}
} else { // recurse
AllPoints( children->node, vp, ccenter, size/2.0);
}
++children; // next child
}
}
}
void compactTree::GetOctTreeCenter(vector<double*>&c, cbitoct &node, double *center, double size) {
double ccenter[3];
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
for (unsigned char i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
double * cp = new double[POINTDIM];
for (unsigned int iterator = 0; iterator < POINTDIM; iterator++) {
cp[iterator] = ccenter[iterator];
}
c.push_back(cp);
} else { // recurse
GetOctTreeCenter(c, children->node, ccenter, size/2.0);
}
++children; // next child
}
}
}
long compactTree::countNodes(cbitoct &node) {
long result = 0;
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf
// ++result;
} else { // recurse
result += countNodes(children->node) + 1;
}
++children; // next child
}
}
return result;
}
long compactTree::countLeaves(cbitoct &node) {
long result = 0;
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf
lint nrpts = children->getLength();
result += POINTDIM*nrpts + 1;
} else { // recurse
result += countLeaves(children->node);
}
++children; // next child
}
}
return result;
}
void compactTree::deletetNodes(cbitoct &node) {
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
bool haschildren = false;
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf
tshort *points = children->getPoints();
delete [] points;
// delete [] children->points;
} else { // recurse
deletetNodes(children->node);
}
++children; // next child
haschildren = true;
}
}
// delete children
if (haschildren) {
cbitoct::getChildren(node, children);
delete[] children;
}
}
unsigned long compactTree::maxTargetPoints( cbitoct &node ) {
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
unsigned long max = 0;
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
lint length = children->getLength();
if (length > max) max = length;
} else { // recurse
unsigned long tp = maxTargetPoints( children->node);
if (tp > max) max = tp;
}
++children; // next child
}
}
return max*POPCOUNT(node.valid);
}
void compactTree::displayOctTreeAll( cbitoct &node, double *center, double size) {
double ccenter[3];
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
tshort *point = children->getPoints();
lint length = children->getLength();
glBegin(GL_POINTS);
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
//cout << "C " << point[1] << " " << cm << endl;
//glVertex3f( point[0], point[1], point[2]);
glVertex3f( point[0] * precision + ccenter[0], point[1] * precision + ccenter[1], point[2] * precision + ccenter[2]);
point+=POINTDIM;
}
glEnd();
} else { // recurse
displayOctTreeAll( children->node, ccenter, size/2.0);
}
++children; // next child
}
}
}
void compactTree::displayOctTreeAllCulled( cbitoct &node, double *center, double size ) {
int res = CubeInFrustum2(center[0], center[1], center[2], size);
if (res==0) return; // culled do not continue with this branch of the tree
if (res == 2) { // if entirely within frustrum discontinue culling
displayOctTreeAll(node, center, size);
return;
}
double ccenter[3];
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
// check if leaf is visible
if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
tshort *point = children->getPoints();
lint length = children->getLength();
glBegin(GL_POINTS);
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
//glVertex3f( point[0], point[1], point[2]);
glVertex3f( point[0] * precision + ccenter[0], point[1] * precision + ccenter[1], point[2] * precision + ccenter[2]);
point+=POINTDIM;
}
glEnd();
}
} else { // recurse
displayOctTreeAllCulled( children->node, ccenter, size/2.0);
}
++children; // next child
}
}
}
void compactTree::displayOctTreeCulledLOD(long targetpts, cbitoct &node, double *center, double size ) {
if (targetpts <= 0) return; // no need to display anything
int res = CubeInFrustum2(center[0], center[1], center[2], size);
if (res==0) return; // culled do not continue with this branch of the tree
if (res == 2) { // if entirely within frustrum discontinue culling
displayOctTreeLOD(targetpts, node, center, size);
return;
}
double ccenter[3];
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
unsigned short nc = POPCOUNT(node.valid);
long newtargetpts = targetpts;
if (nc > 0) {
newtargetpts = newtargetpts/nc;
if (newtargetpts <= 0 ) return;
}
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
// check if leaf is visible
if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
tshort *point = children->getPoints();
lint length = children->getLength();
glBegin(GL_POINTS);
if (length > 10 && !LOD(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) { // only a single pixel on screen only paint one point
if(cm) cm->setColor(point);
//glVertex3f( point[0], point[1], point[2]);
glVertex3f( point[0] * precision + ccenter[0], point[1] * precision + ccenter[1], point[2] * precision + ccenter[2]);
} else if (length <= newtargetpts) { // more points requested than possible, plot all
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
//glVertex3f( point[0], point[1], point[2]);
glVertex3f( point[0] * precision + ccenter[0], point[1] * precision + ccenter[1], point[2] * precision + ccenter[2]);
point+=POINTDIM;
}
} else { // select points to show
// TODO smarter subselection of points here
double each = (double)POINTDIM * (double)((double)length/(double)newtargetpts);
tshort *p;
int index;
for(unsigned int iterator = 0; iterator < newtargetpts; iterator++ ) {
index = (double)iterator * each;
p = point + index - index%POINTDIM;
if(cm) cm->setColor(p);
//glVertex3f( p[0], p[1], p[2]);
glVertex3f( p[0] * precision + ccenter[0], p[1] * precision + ccenter[1], p[2] * precision + ccenter[2]);
//point += each;
}
}
glEnd();
}
} else { // recurse
displayOctTreeCulledLOD(newtargetpts, children->node, ccenter, size/2.0);
}
++children; // next child
}
}
}
void compactTree::displayOctTreeLOD(long targetpts, cbitoct &node, double *center, double size ) {
if (targetpts <= 0) return; // no need to display anything
double ccenter[3];
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
unsigned short nc = POPCOUNT(node.valid);
long newtargetpts = targetpts;
if (nc > 0) {
newtargetpts = newtargetpts/nc;
if (newtargetpts <= 0 ) return;
}
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
tshort *point = children->getPoints();
lint length = children->getLength();
glBegin(GL_POINTS);
/* if (length > 10 && !LOD(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) { // only a single pixel on screen only paint one point
if(cm) cm->setColor(point);
//glVertex3f( point[0], point[1], point[2]);
glVertex3f( point[0] * precision + ccenter[0], point[1] * precision + ccenter[1], point[2] * precision + ccenter[2]);
} else*/ if (length <= newtargetpts) { // more points requested than possible, plot all
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
//glVertex3f( point[0], point[1], point[2]);
glVertex3f( point[0] * precision + ccenter[0], point[1] * precision + ccenter[1], point[2] * precision + ccenter[2]);
point+=POINTDIM;
}
} else { // select points to show
// TODO smarter subselection of points here
double each = (double)POINTDIM * (double)((double)length/(double)newtargetpts);
tshort *p;
int index;
for(unsigned int iterator = 0; iterator < newtargetpts; iterator++ ) {
index = (double)iterator * each;
p = point + index - index%POINTDIM;
if(cm) cm->setColor(p);
//glVertex3f( p[0], p[1], p[2]);
glVertex3f( p[0] * precision + ccenter[0], p[1] * precision + ccenter[1], p[2] * precision + ccenter[2]);
//point += each;
}
}
glEnd();
} else { // recurse
displayOctTreeLOD(newtargetpts, children->node, ccenter, size/2.0);
}
++children; // next child
}
}
}
void compactTree::displayOctTreeCulledLOD2(float ratio, cbitoct &node, double *center, double size ) {
int res = CubeInFrustum2(center[0], center[1], center[2], size);
if (res==0) return; // culled do not continue with this branch of the tree
if (res == 2) { // if entirely within frustrum discontinue culling
displayOctTreeLOD2(ratio, node, center, size);
return;
}
double ccenter[3];
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
// check if leaf is visible
if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
tshort *point = children->getPoints();
lint length = children->getLength();
int l = LOD2(ccenter[0], ccenter[1], ccenter[2], size/2.0); // only a single pixel on screen only paint one point
l = max((int)(l*l*ratio), 0);
if (l != 0) {
if ((int)length > l ) {
double each = (double)POINTDIM * (double)((double)length/(double)l);
tshort *p;
int index;
for(int iterator = 0; iterator < l; iterator++ ) {
index = (double)iterator * each;
p = point + index - index%POINTDIM;
if(cm) cm->setColor(p);
glVertex3f( p[0] * precision + ccenter[0], p[1] * precision + ccenter[1], p[2] * precision + ccenter[2]);
}
} else if ((int)length <= l) {
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0] * precision + ccenter[0], point[1] * precision + ccenter[1], point[2] * precision + ccenter[2]);
point+=POINTDIM;
}
} else if (l == 1) {
if(cm) cm->setColor(point);
glVertex3f( point[0] * precision + ccenter[0], point[1] * precision + ccenter[1], point[2] * precision + ccenter[2]);
}
}
}
} else { // recurse
int l = LOD2(ccenter[0], ccenter[1], ccenter[2], size/2.0); // only a single pixel on screen only paint one point
l = max((int)(l*l*ratio), 0);
if (l > 0) {
displayOctTreeCulledLOD2(ratio, children->node, ccenter, size/2.0);
}
}
++children; // next child
}
}
}
void compactTree::displayOctTreeLOD2(float ratio, cbitoct &node, double *center, double size ) {
double ccenter[3];
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf get center
tshort *point = children->getPoints();
lint length = children->getLength();
int l = LOD2(ccenter[0], ccenter[1], ccenter[2], size/2.0); // only a single pixel on screen only paint one point
l = max((int)(l*l*ratio), 0);
if (l > 1) {
if ((int)length > l ) {
double each = (double)POINTDIM * (double)((double)length/(double)l);
tshort *p;
int index;
for(int iterator = 0; iterator < l; iterator++ ) {
index = (double)iterator * each;
p = point + index - index%POINTDIM;
if(cm) cm->setColor(p);
glVertex3f( p[0] * precision + ccenter[0], p[1] * precision + ccenter[1], p[2] * precision + ccenter[2]);
}
} else if ((int)length <= l) {
for(unsigned int iterator = 0; iterator < length; iterator++ ) {
if(cm) cm->setColor(point);
glVertex3f( point[0] * precision + ccenter[0], point[1] * precision + ccenter[1], point[2] * precision + ccenter[2]);
point+=POINTDIM;
}
}
} else {
if(cm) cm->setColor(point);
glVertex3f( point[0] * precision + ccenter[0], point[1] * precision + ccenter[1], point[2] * precision + ccenter[2]);
}
} else { // recurse
int l = LOD2(ccenter[0], ccenter[1], ccenter[2], size/2.0); // only a single pixel on screen only paint one point
l = max((int)(l*l*ratio), 0);
if (l > 0) {
displayOctTreeLOD2(ratio, children->node, ccenter, size/2.0);
}
}
++children; // next child
}
}
}
void compactTree::displayOctTreeCAllCulled( cbitoct &node, double *center, double size, double minsize ) {
int res = CubeInFrustum2(center[0], center[1], center[2], size);
if (res==0) return; // culled do not continue with this branch of the tree
if (res == 2) { // if entirely within frustrum discontinue culling
displayOctTreeCAll(node, center, size, minsize);
return;
}
double ccenter[3];
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf || minsize > size ) { // if ith node is leaf get center
// check if leaf is visible
if ( CubeInFrustum(ccenter[0], ccenter[1], ccenter[2], size/2.0) ) {
showCube(ccenter, size/2.0);
}
} else { // recurse
displayOctTreeCAllCulled( children->node, ccenter, size/2.0, minsize);
}
++children; // next child
}
}
}
void compactTree::displayOctTreeCAll( cbitoct &node, double *center, double size, double minsize ) {
double ccenter[3];
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
childcenter(center, ccenter, size, i); // childrens center
if ( ( 1 << i ) & node.leaf || minsize > size ) { // if ith node is leaf get center
showCube(ccenter, size/2.0);
} else { // recurse
displayOctTreeCAll( children->node, ccenter, size/2.0, minsize);
}
++children; // next child
}
}
}
void compactTree::showCube(double *center, double size) {
glLineWidth(1.0);
glBegin(GL_QUADS); // draw a cube with 6 quads
glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
glVertex3f(center[0] + size, center[1] + size, center[2] - size);
glVertex3f(center[0] - size, center[1] + size, center[2] - size);
glVertex3f(center[0] - size, center[1] + size, center[2] + size);
glVertex3f(center[0] + size, center[1] + size, center[2] + size);
glColor3f(1.0f,0.5f,0.0f); // Set The Color To Orange
glVertex3f(center[0] + size, center[1] - size, center[2] + size);
glVertex3f(center[0] - size, center[1] - size, center[2] + size);
glVertex3f(center[0] - size, center[1] - size, center[2] - size);
glVertex3f(center[0] + size, center[1] - size, center[2] - size);
glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
glVertex3f(center[0] + size, center[1] + size, center[2] + size);
glVertex3f(center[0] - size, center[1] + size, center[2] + size);
glVertex3f(center[0] - size, center[1] - size, center[2] + size);
glVertex3f(center[0] + size, center[1] - size, center[2] + size);
glColor3f(1.0f,1.0f,0.0f); // Set The Color To Yellow
glVertex3f(center[0] + size, center[1] - size, center[2] - size);
glVertex3f(center[0] - size, center[1] - size, center[2] - size);
glVertex3f(center[0] - size, center[1] + size, center[2] - size);
glVertex3f(center[0] + size, center[1] + size, center[2] - size);
glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
glVertex3f(center[0] - size, center[1] + size, center[2] + size);
glVertex3f(center[0] - size, center[1] + size, center[2] - size);
glVertex3f(center[0] - size, center[1] - size, center[2] - size);
glVertex3f(center[0] - size, center[1] - size, center[2] + size);
glColor3f(1.0f,0.0f,1.0f); // Set The Color To Violet
glVertex3f(center[0] + size, center[1] + size, center[2] - size);
glVertex3f(center[0] + size, center[1] + size, center[2] + size);
glVertex3f(center[0] + size, center[1] - size, center[2] + size);
glVertex3f(center[0] + size, center[1] - size, center[2] - size);
glEnd();
}
template <class T>
void compactTree::selectRay(vector<T *> &points) {
//selectRay(points, *root, center, size);
}
void compactTree::childcenter(double *pcenter, double *ccenter, double size, unsigned char i) {
switch (i) {
case 0:
ccenter[0] = pcenter[0] - size / 2.0;
ccenter[1] = pcenter[1] - size / 2.0;
ccenter[2] = pcenter[2] - size / 2.0;
break;
case 1:
ccenter[0] = pcenter[0] + size / 2.0;
ccenter[1] = pcenter[1] - size / 2.0;
ccenter[2] = pcenter[2] - size / 2.0;
break;
case 2:
ccenter[0] = pcenter[0] - size / 2.0;
ccenter[1] = pcenter[1] + size / 2.0;
ccenter[2] = pcenter[2] - size / 2.0;
break;
case 3:
ccenter[0] = pcenter[0] + size / 2.0;
ccenter[1] = pcenter[1] + size / 2.0;
ccenter[2] = pcenter[2] - size / 2.0;
break;
case 4:
ccenter[0] = pcenter[0] - size / 2.0;
ccenter[1] = pcenter[1] - size / 2.0;
ccenter[2] = pcenter[2] + size / 2.0;
break;
case 5:
ccenter[0] = pcenter[0] + size / 2.0;
ccenter[1] = pcenter[1] - size / 2.0;
ccenter[2] = pcenter[2] + size / 2.0;
break;
case 6:
ccenter[0] = pcenter[0] - size / 2.0;
ccenter[1] = pcenter[1] + size / 2.0;
ccenter[2] = pcenter[2] + size / 2.0;
break;
case 7:
ccenter[0] = pcenter[0] + size / 2.0;
ccenter[1] = pcenter[1] + size / 2.0;
ccenter[2] = pcenter[2] + size / 2.0;
break;
default:
break;
}
}
void compactTree::GetOctTreeCenter(vector<double*>&c) { GetOctTreeCenter(c, *root, center, size); }
void compactTree::AllPoints(vector<double *> &vp) { AllPoints(*compactTree::root, vp, center, size); }
long compactTree::countNodes() { return 1 + countNodes(*root); }
long compactTree::countLeaves() { return 1 + countLeaves(*root); }
void compactTree::setColorManager(ColorManager *_cm) { cm = _cm; }
void compactTree::drawLOD(float ratio) {
switch (current_lod_mode) {
case 1:
glBegin(GL_POINTS);
displayOctTreeCulledLOD2(ratio , *root, center, size);
glEnd();
break;
case 2:
/*
#ifdef WITH_GLEE
if (GLEE_ARB_point_parameters) {
glPointParameterfARB(GL_POINT_SIZE_MIN_ARB, 1.0);
glPointParameterfARB(GL_POINT_SIZE_MAX_ARB, 100000.0);
GLfloat p[3] = {0.0, 0.0000, 0.0000005};
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, p);
displayOctTreeCPAllCulled(*BOctTree<T>::root, BOctTree<T>::center, BOctTree<T>::size, BOctTree<T>::size/ pow(2, min( (int)(ratio * BOctTree<T>::max_depth ), BOctTree<T>::max_depth - 3) ) );
p[0] = 1.0;
p[2] = 0.0;
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, p);
}
#endif
*/
//break;
case 0:
glBegin(GL_POINTS);
displayOctTreeCulledLOD(maxtargetpoints * ratio, *root, center, size);
glEnd();
break;
default:
break;
}
}
void compactTree::draw() {
displayOctTreeAllCulled(*root, center, size);
}
void compactTree::displayOctTree(double minsize ) {
displayOctTreeCAllCulled(*root, center, size, minsize);
}
shortpointrep* compactTree::createPoints(lint length) {
//shortpointrep *points = new shortpointrep[POINTDIM*length];
shortpointrep *points = alloc->allocate<shortpointrep> (POINTDIM*length);
return points;
}
void compactTree::deserialize(std::string filename ) {
char buffer[sizeof(float) * 20];
float *p = reinterpret_cast<float*>(buffer);
std::ifstream file;
file.open (filename.c_str(), std::ios::in | std::ios::binary);
// read magic bits
file.read(buffer, 2);
if ( buffer[0] != 'X' || buffer[1] != 'T') {
std::cerr << "Not an octree file!!" << endl;
file.close();
return;
}
// read header
pointtype = PointType::deserialize(file);
file.read(buffer, 5 * sizeof(float));
voxelSize = p[0];
center[0] = p[1];
center[1] = p[2];
center[2] = p[3];
size = p[4];
file.read(buffer, sizeof(int));
int *ip = reinterpret_cast<int*>(buffer);
POINTDIM = *ip;
float *fmins = new float[POINTDIM];
float *fmaxs = new float[POINTDIM];
mins = new double[POINTDIM];
maxs = new double[POINTDIM];
file.read(reinterpret_cast<char*>(fmins), POINTDIM * sizeof(float));
file.read(reinterpret_cast<char*>(fmaxs), POINTDIM * sizeof(float));
for (unsigned int i = 0; i < POINTDIM; i++) {
mins[i] = fmins[i];
maxs[i] = fmaxs[i];
}
double vs = size;
while (vs > voxelSize) {
vs = vs * 0.5;
}
// precision = vs / 32768; // 2^15
precision = vs / TSHORT_MAXP1; // 2^15
// read root node
//root = new cbitoct();
root = alloc->allocate<cbitoct>();
deserialize(file, *root );
file.close();
}
void compactTree::deserialize(std::ifstream &f, cbitoct &node) {
char buffer[2];
f.read(buffer, 2);
node.valid = buffer[0];
node.leaf = buffer[1];
unsigned short n_children = POPCOUNT(node.valid);
// create children
//cbitunion<tshort> *children = new cbitunion<tshort>[n_children];
cbitunion<tshort> *children = alloc->allocate<cbitunion<tshort> >(n_children);
cbitoct::link(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf read points
lint length;
f.read(reinterpret_cast<char*>(&length), sizeof(lint));
shortpointrep *points = createPoints(length);
f.read(reinterpret_cast<char*>(points), sizeof(shortpointrep) * length * POINTDIM); // read the points
children->linkPoints(points, length);
} else { // write child
deserialize(f, children->node);
}
++children; // next child
}
}
}
void compactTree::serialize(std::string filename) {
char buffer[sizeof(float) * 20];
float *p = reinterpret_cast<float*>(buffer);
std::ofstream file;
file.open (filename.c_str(), std::ios::out | std::ios::binary);
// write magic bits
buffer[0] = 'X';
buffer[1] = 'T';
file.write(buffer, 2);
// write header
pointtype.serialize(file);
p[0] = voxelSize;
p[1] = center[0];
p[2] = center[1];
p[3] = center[2];
p[4] = size;
int *ip = reinterpret_cast<int*>(&(buffer[5 * sizeof(float)]));
*ip = POINTDIM;
file.write(buffer, 5 * sizeof(float) + sizeof(int));
for (unsigned int i = 0; i < POINTDIM; i++) {
p[i] = mins[i];
}
for (unsigned int i = 0; i < POINTDIM; i++) {
p[i+POINTDIM] = maxs[i];
}
file.write(buffer, 2*POINTDIM * sizeof(float));
// write root node
serialize(file, *root);
file.close();
}
void compactTree::serialize(std::ofstream &of, cbitoct &node) {
char buffer[2];
buffer[0] = node.valid;
buffer[1] = node.leaf;
of.write(buffer, 2);
// write children
cbitunion<tshort> *children;
cbitoct::getChildren(node, children);
for (short i = 0; i < 8; i++) {
if ( ( 1 << i ) & node.valid ) { // if ith node exists
if ( ( 1 << i ) & node.leaf ) { // if ith node is leaf write points
tshort *points = children->getPoints();
lint length = children->getLength();
of.write(reinterpret_cast<char*>(&length), sizeof(lint) );
of.write(reinterpret_cast<char*>(points), POINTDIM*length*sizeof(tshort) );
} else { // write child
serialize(of, children->node);
}
++children; // next child
}
}
}