/* * 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 #include using std::vector; #include using std::deque; #include using std::set; #include using std::list; #include #include #include #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 &vp, double center[3], double size) { double ccenter[3]; cbitunion *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&c, cbitoct &node, double *center, double size) { double ccenter[3]; cbitunion *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 void compactTree::selectRay(vector &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&c) { GetOctTreeCenter(c, *root, center, size); } void compactTree::AllPoints(vector &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::root, BOctTree::center, BOctTree::size, BOctTree::size/ pow(2, min( (int)(ratio * BOctTree::max_depth ), BOctTree::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 (POINTDIM*length); return points; } void compactTree::deserialize(std::string filename) { char buffer[sizeof(float) * 20]; float *p = reinterpret_cast(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(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(fmins), POINTDIM * sizeof(float)); file.read(reinterpret_cast(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(); 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 *children = new cbitunion[n_children]; cbitunion *children = alloc->allocate >(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(&length), sizeof(lint)); shortpointrep *points = createPoints(length); f.read(reinterpret_cast(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(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(&(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 *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(&length), sizeof(lint) ); of.write(reinterpret_cast(points), POINTDIM*length*sizeof(tshort) ); } else { // write child serialize(of, children->node); } ++children; // next child } } }