这是我的第一个c ++项目,因此可能会出现初学者失败。还是要学到很多东西。
我通过将连接的圆柱体与点云库拟合来建模树木(真正的室外树木)。在我的真实场景中,我检测到大约3000个柱面,我想将它存储到具有两个层次的树(信息树)结构中。
我建立父母< - >子关系,如果两个圆柱的终点和起点重合。我从根筒开始检测它的孩子。对于每个孩子,这也是递归地执行的。只要一个圆柱体只有一个子圆柱体,我就将它添加到一个带有圆柱矢量的所谓的圆弧体中。如果孩子的孩子大小也是1,则孙子被添加到同一个片段,依此类推。如果圆柱体具有多个子节点,则当前节段将停止,并且为每个子节点创建新的节段。所有段都有父和子信息,所以我可以在两个方向迭代树。
我已经设置了一个最小的运行示例来重现错误。而不是7个参数柱面,我的测试柱面只有一个start int和一个end int。标题和cpp文件:
TestCylinder.h
#ifndef TESTCYLINDER_H
#define TESTCYLINDER_H
class TestCylinder
{
public:
int start;
int end;
TestCylinder(int a, int b);
virtual ~TestCylinder();
protected:
private:
};
#endif // TESTCYLINDER_H
TestCylinder.cpp
#include "TestCylinder.h"
TestCylinder::TestCylinder(int a, int b)
{
start = a;
end = b;
}
TestCylinder::~TestCylinder()
{
//dtor
}
段(它们代表两个分支部分之间的分支部分或茎部分)。使用指针引用父段,子段存储在向量中:
TestSegment.h:
#ifndef TESTSEGMENT_H
#define TESTSEGMENT_H
#include "TestCylinder.h"
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
class TestSegment
{
public:
TestSegment(TestCylinder cylinder, boost::shared_ptr<TestSegment> parent);
TestSegment(TestCylinder cylinder);
TestSegment();
virtual ~TestSegment();
std::vector<TestCylinder> getCylinders();
boost::shared_ptr<TestSegment> getParentSegment();
std::vector<TestSegment> getChildSegments();
bool addCylinder(TestCylinder nextCylinder);
protected:
private:
std::vector<TestCylinder> cylinders;
std::vector<TestSegment> childSegments;
boost::shared_ptr<TestSegment> parentSegment;
};
#endif // TESTSEGMENT_H
TestSegment.cpp:
#include "TestSegment.h"
TestSegment::TestSegment(TestCylinder cylinder)
{
cylinders.empty();
cylinders.push_back(cylinder);
}
TestSegment::TestSegment(TestCylinder cylinder, boost::shared_ptr<TestSegment> parent)
{
cylinders.empty();
cylinders.push_back(cylinder);
parentSegment = parent;
}
TestSegment::~TestSegment()
{
}
std::vector<TestCylinder>
TestSegment::getCylinders()
{
return cylinders;
}
boost::shared_ptr<TestSegment>
TestSegment::getParentSegment()
{
return parentSegment;
}
std::vector<TestSegment>
TestSegment::getChildSegments()
{
return childSegments;
}
bool TestSegment::addCylinder(TestCylinder nextCylinder)
{
TestCylinder endCylinder = cylinders.back();
int x1 = endCylinder.end;
int x2 = nextCylinder.start;
if(x1==x2)
{
cylinders.push_back(nextCylinder);
return true;
}
return false;
}
树类,它构建树结构并提供一些迭代段/柱面的方法:
TestTree.h:
#ifndef TESTTREE_H
#define TESTTREE_H
#include "TestSegment.h"
class TestTree
{
public:
TestTree(std::vector<TestCylinder> cylinders_in);
virtual ~TestTree();
/*
* Getters and Setters
*/
TestCylinder&
getRootCylinder ();
void
setRootCylinder (TestCylinder rootCylinderNew);
boost::shared_ptr<TestSegment>&
getRootSegment ();
void
setRootSegment (boost::shared_ptr<TestSegment> rootSegmentNew);
void addChildCylinders(TestCylinder& currentCylinder, TestSegment& segment);
std::vector<TestCylinder>
getChildCylinders(TestCylinder& currentCylinder);
std::vector<TestSegment>
getSegmentList ();
std::vector<TestCylinder>
getCylinderList ();
protected:
private:
std::vector<TestCylinder> cylinders ;
boost::shared_ptr<TestSegment> rootSegment;
std::vector<TestSegment> getChildSegmentsRecursively(TestSegment parent);
};
#endif // TESTTREE_H
TestTree.cpp
#include "TestTree.h"
TestTree::TestTree(std::vector<TestCylinder> cylinders_in)
{
cylinders = cylinders_in;
TestCylinder rootCylinder = cylinders.at(0);
TestSegment root(rootCylinder);
rootSegment = boost::make_shared<TestSegment>(root);
addChildCylinders(rootCylinder,*rootSegment);
}
TestTree::~TestTree()
{
//dtor
}
std::vector<TestCylinder>
TestTree::getCylinderList ()
{
std::vector<TestCylinder> cylinders;
std::cout << "GetCylinderList before getSegmentsList" << "\n";
std::vector<TestSegment> allSegments = getSegmentList();
std::cout << "GetCylinderList after getSegmentsList" << allSegments.size()<<"\n";
for(std::vector<TestSegment>::iterator it = allSegments.begin(); it!= allSegments.end(); ++it)
{
TestSegment segment = *it;
//std::cout << segment.getSegmentCylinders().size();
cylinders.insert(cylinders.end(),segment.getCylinders().begin(), segment.getCylinders().end());
}
return cylinders;
}
std::vector<TestSegment>
TestTree::getSegmentList ()
{
// std::cout<<"GetSegmentList rootsegment size :"<< rootSegment->get.size()<<"\n";
return getChildSegmentsRecursively(*rootSegment);
}
std::vector<TestSegment>
TestTree::getChildSegmentsRecursively(TestSegment parent)
{
std::vector<TestSegment> allSegments;
allSegments.push_back(parent);
for(std::vector<TestSegment>::iterator it = parent.getChildSegments().begin (); it != parent.getChildSegments().end (); ++it)
{
TestSegment child = *it;
std::vector<TestSegment> children = getChildSegmentsRecursively(child);
allSegments.insert(allSegments.end(),children.begin(),children.end());
}
//std::cout << "TestTree geChildSegmentsRecursively" << parent.getChildSegments().size()<< "\n";
return allSegments;
}
void TestTree::addChildCylinders(TestCylinder& currentCylinder, TestSegment& segment)
{
std::vector<TestCylinder> children = getChildCylinders(currentCylinder);
if(children.size()==1)
{
TestCylinder child = children.at(0);
if(segment.addCylinder(child))
{
addChildCylinders(child,segment);
}
}
else if (children.size()>1)
{
for (std::vector<TestCylinder>::iterator it = children.begin (); it != children.end (); ++it)
{
TestCylinder child = *it;
boost::shared_ptr<TestSegment> seg_ptr = boost::make_shared<TestSegment>(segment);
TestSegment childSegment (child, seg_ptr);
if (childSegment.getParentSegment() == rootSegment)
{
std::cout << "TestTreeCpp::addChildCylinders, rootSegment is parentSegment \n";
}
addChildCylinders(child,childSegment);
}
}
}
std::vector<TestCylinder>
TestTree::getChildCylinders(TestCylinder& currentCylinder)
{
std::vector<TestCylinder> children;
for (std::vector<TestCylinder>::iterator it = cylinders.begin (); it != cylinders.end (); ++it)
{
TestCylinder cylinder = *it;
if(currentCylinder.end == cylinder.start)
{
children.push_back(cylinder);
}
}
return children;
}
/*
* Getters and Setters
*/
TestCylinder&
TestTree::getRootCylinder ()
{
TestSegment root = *rootSegment;
return root.getCylinders().at(0);
}
boost::shared_ptr<TestSegment>&
TestTree::getRootSegment ()
{
return rootSegment;
}
//void
//TestTree::setRootSegment (SegmentModel rootSegmentNew)
//{
// rootSegment = rootSegmentNew;
//}
主要功能,只需创建6个连接的柱面并使用此列表调用树:
int
main (int argc,
char** argv)
{
// ------------------------------------
// -----Load Cherry 1 -----
// ------------------------------------
std::vector<TestCylinder> cylinders;
TestCylinder cyl(0,1);
cylinders.push_back(cyl);
TestCylinder cyl2(1,2);
cylinders.push_back(cyl2);
TestCylinder cyl3(2,3);
cylinders.push_back(cyl3);
TestCylinder cyl4(3,4);
cylinders.push_back(cyl4);
TestCylinder cyl5(3,14);
cylinders.push_back(cyl5);
TestCylinder cyl6(14,15);
cylinders.push_back(cyl6);
std::cout << cylinders.size() << "\n";
TestTree tree (cylinders);
std::cout << tree.getCylinderList().size() << "\n";
}
构建树可能有效,调用getCylinderList函数时会发生以下错误:
terminate called after throwing an instance of 'std::length_error'
what(): vector::_M_range_insert
Aborted (core dumped)
Possible dublicate对我没有帮助,因为我在迭代时不添加或删除项目。
答案 0 :(得分:6)
问题是TestSegment按值返回向量,例如在TestSegment :: getChildSegments中。这意味着,您制作了矢量的副本。
现在,在getCylinderlist中,您使用参数segment.getCylinders()。begin()和segment.getCylinders(调用std :: vector :: insert(在异常的错误消息中提到的函数)) )。结束()。但是这两个对getCylinders的调用并没有返回相同的向量,而是返回每个向量的单独副本。所以你基本上说的是
std::vector< TestCylinder > c1 = segment.getCylinders();
std::vector< TestCylinder > c2 = segment.getCylinders();
cylinders.insert( cylinders.end(), c1.begin(), c2.end() )
c1和c2不一样,这就是代码失败的原因。
TestSegment :: getChildSegments也出现了同样的问题。
要解决此问题,您应该通过const&amp;。
返回向量希望有所帮助。