2016-04-04 8 views
0

Ich versuche, meine eigene Octree-Klasse für räumliche Zerlegungsalgorithmen zu implementieren. Was ich tun möchte, ist, den Baum zu durchqueren und die Knoten der Blattknoten in einem Vektor zu speichern.Speichern von Scheitelpunkten von Octree-Blattknoten in separaten Datenstrukturen

Bisher habe ich die Octree auf diese Weise umgesetzt (es ist in 2D der Einfachheit halber):

class AxisAlignedBox 
{ 
public: 
AxisAlignedBox(){} 

AxisAlignedBox(Eigen::Vector2f min, Eigen::Vector2f max):_min(min),_max(max) 
{ 
    _halfWidth = (_max(0) - _min(0))/2; 
    _center << _min(0) + _halfWidth,_min(1) + _halfWidth; 
} 

AxisAlignedBox(Eigen::Vector2f center, float halfWidth):_center(center),_halfWidth(halfWidth) 
{ 
    _min << _center(0) - _halfWidth,_center(1) - _halfWidth; 
    _max << _center(0) + _halfWidth,_center(1) + _halfWidth; 
} 

void splitBox(AxisAlignedBox *boxes) 
{ 
    int idx = 0; 
    float halfWidth = _halfWidth/2; 
    for(int j = -1; j < 2; j += 2) 
     for(int i = -1; i < 2; i += 2) 
     { 
      boxes[idx] = AxisAlignedBox(Eigen::Vector2f (_center(0)+i*halfWidth,_center(1)+j*halfWidth),halfWidth); 
      idx++; 
     } 

} 

bool inRange(Eigen::Vector2f point) 
{ 
    if(point(0) > _min(0) && point(0) < _max(0) && point(1) > _min(1) && point(1) < _max(1)) 
     return true; 
    else 
     return false; 
} 

Eigen::Vector2f getMin(){return _min;} 

Eigen::Vector2f getMax(){return _max;} 

Eigen::Vector2f getCenter(){return _center;} 

private: 
Eigen::Vector2f _min; 
Eigen::Vector2f _max; 
Eigen::Vector2f _center; 
float _halfWidth; 
}; 

class OctreeNode 
{ 
public: 
OctreeNode(int depth, std::vector<Eigen::Vector2f> points, Eigen::Vector2f min, Eigen::Vector2f max):_depth(depth) 
{ 
    if(_depth < 0) 
    { 
     return; 
    } 
    else 
    { 
     _box = AxisAlignedBox(min,max); 
     _points = points; 

     AxisAlignedBox boxes[4]; 
     _box.splitBox(boxes); 

     std::vector<Eigen::Vector2f> splittedPoints [4]; 

     for(int ii=0; ii < _points.size(); ii++) 
      for(int boxId = 0; boxId < 4; boxId++) 
       if(boxes[boxId].inRange(_points.at(ii))) 
        splittedPoints[boxId].push_back(_points.at(ii)); 

     for(int i = 0; i < 4; i++) 
      if(!splittedPoints[i].empty()) 
      { 
       _children[i] = new OctreeNode(depth-1,splittedPoints[i],boxes[i].getMin(),boxes[i].getMax()); 
      } 
    } 
} 

OctreeNode* getChild1(){return _children[0];} 
OctreeNode* getChild2(){return _children[1];} 
OctreeNode* getChild3(){return _children[2];} 
OctreeNode* getChild4(){return _children[3];} 
int getDepth(){return _depth;} 
AxisAlignedBox getBox(){return _box;} 
private: 
int _depth; 
AxisAlignedBox _box; 
std::vector<Eigen::Vector2f> _points; 
OctreeNode* _children[4]; 
}; 

diese Klasse zu verwenden, ist es das, was ich in der Haupt schrieb:

#include <iostream> 
#include "AdaptiveGrid.h" 

void visit(OctreeNode* octree); 


int main() 
{ 
std::vector<Eigen::Vector2f> dataSet; 

for(float theta = 0; theta < 2*M_PI; theta += 0.034) 
    dataSet.push_back(Eigen::Vector2f(0.8*cos(theta),0.8*sin(theta))); 

Eigen::Vector2f min(-1,-1); 
Eigen::Vector2f max(1,1); 

std::cerr << "Dataset has " << dataSet.size() << " points\n"; 

OctreeNode *octree = new OctreeNode(2,dataSet,min,max); 

visit(octree); 

return 0; 
} 

void visit(OctreeNode* octree) 
{ 
if(octree) 
{ 
    if(octree->getDepth() == 0) 
    { 
     std::cerr << "Depth: " << octree->getDepth() << "\n"; 
     std::cerr << "center: " << octree->getBox().getCenter().transpose() << "\n"; 
    } 
    visit(octree->getChild1()); 
    visit(octree->getChild2()); 
    visit(octree->getChild3()); 
    visit(octree->getChild4()); 
} 
} 

aber nach dem ersten Blattknoten zu besuchen, erhalte ich einen Segmentation Fault:

dede @ dede-P35V2: ~/build/AdaptiveGrid/build $ ./adapative_grid

Datensatz hat 185 Punkte

Tiefe: 0

Zentrum: -0.75 -0.75

Segmentation fault

Bitte, könnten Sie mir erklären, was ich falsch mache?

Danke.

+0

, was Sie falsch machen: Sie haben vergessen, 'OctreeNode * _children [4] zu initialisieren;' 'mit NULL'. Ersetzen Sie die Zeile durch: 'OctreeNode * _children [4] = {NULL, NULL, NULL, NULL};' – norisknofun

+0

Hinweis: Der Compiler initialisiert keine Zeiger auf NULL. So kann die 'if (octree)' Contition auf der 'visit '-Funktion' wahr 'sein, auch wenn die Adresse falsch ist und zum seg-Fehler führt! – norisknofun

+0

Danke für die Antwort! Das hat das Problem gelöst! –

Antwort

0

was Sie falsch machen: Sie haben vergessen, OctreeNode* _children[4]; mit NULL s zu initialisieren.

Ersetzen Sie die Zeile mit: OctreeNode* _children[4] = { NULL, NULL, NULL, NULL };

Verwandte Themen