C++ vector loses data in recursive function

主宰稳场 提交于 2020-01-04 09:12:45

问题


I am very new to C++ and I am trying to implement a TriangleDynamic object that can recursively split itself using a function called splitTriangleProject. It splits itself into four smaller TriangleDynamic objects (and projects the vertices of the new triangles onto a sphere with a given radius and origin, but I believe this is beside the point), pushes the newly created triangles into a vector that is part of the member data of the original object. The vector member data is called subTriangles. Then each subTriangle recalls the splitTriangleProject function until a certain "level" of splits has occurred.

The issue I am having is that only the first level of splitting is actually properly pushing to the subTriangles vector. I am certain that the issue has to do with the vectors going out of scope, or maybe the TriangleDynamic going out of scope. I imagine there is some solution with pointers. If anyone could help, it would be much appreciated.

Here is my TriangleDynamic declaration:

class TriangleDynamic
{
public:
    TriangleDynamic(const Point &P1, const Point &P2, const Point &P3);
    TriangleDynamic();
    ~TriangleDynamic(){}
    void printTriangle();
    void splitTriangleProject( int currentLevel, int maxLevel, const Point &org, double radius);
    void init();
    bool operator<(const TriangleDynamic&);
    bool operator>(const TriangleDynamic&);
    Line edge1;
    Line edge2;
    Line edge3;

    Point p1;
    Point p2;
    Point p3;

    Vect normal;

    bool lowestLevel;

    vector<TriangleDynamic> subTriangles;
    static int numTriangles;
    int triangleId;
};

int TriangleDynamic::numTriangles = 0;

and the constructors:

// constructor for the TriangleDynamic object
TriangleDynamic::TriangleDynamic(const Point &P1, const Point &P2, const Point &P3)
{
    p1 = P1;
    p2 = P2;
    p3 = P3;
    init();
}

TriangleDynamic::TriangleDynamic()
{
    p1 = Point(0,0,0);
    p2 = Point(0,0,1);
    p3 = Point(0,1,0);
    init();
}

void TriangleDynamic::init()
{
    edge1 = Line(p1,p2);
    edge2 = Line(p2,p3);
    edge3 = Line(p3,p1);

    Vect U = p2.minus( p1);
    Vect V = p3.minus(p1);

    normal = U.cross(V);

    lowestLevel = true;
    triangleId = numTriangles + 1;
    numTriangles = triangleId;
}

Here is my splitTriangleProject function:

void TriangleDynamic::splitTriangleProject(int currentLevel, int maxLevel, const Point &org, double radius)
{
    if ( currentLevel < maxLevel)
    {
        lowestLevel = false;
        Point worldOrigin = Point(0,0,0);
        double edge1MidMag = (edge1.midpoint - org).distance(worldOrigin) ;
        double edge2MidMag = (edge2.midpoint - org).distance(worldOrigin) ;
        double edge3MidMag = (edge3.midpoint - org).distance(worldOrigin) ;

        Point newEdge1Mid = (((edge1.midpoint) * radius )/ edge1MidMag) + org;
        Point newEdge2Mid = (((edge2.midpoint) * radius )/ edge2MidMag) + org;
        Point newEdge3Mid = (((edge3.midpoint) * radius )/ edge3MidMag) + org;

        TriangleDynamic t1(p1 , newEdge1Mid , newEdge3Mid);
        subTriangles.push_back(t1);

        TriangleDynamic t2(newEdge1Mid, p2, newEdge2Mid);
        subTriangles.push_back(t2);

        TriangleDynamic t3(newEdge3Mid, newEdge2Mid, p3);
        subTriangles.push_back(t3);

        TriangleDynamic t4(newEdge1Mid, newEdge2Mid, newEdge3Mid);
        subTriangles.push_back(t4);

        t1.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
        t2.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
        t3.splitTriangleProject( currentLevel + 1, maxLevel, org, radius); 
        t4.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
    }
}

Here is a function for recursively printing the triangleDynamic when it's done:

void TriangleDynamic::printTriangle()
{
    cout<< "p1";
    p1.printPoint();
    cout << "\np2";
    p2.printPoint();
    cout << "\np3";
    p3.printPoint();
    cout << "\n\n";

    if(!lowestLevel)
    {
        int ctr;
        for (ctr=0; ctr<=subTriangles.size()-1; ctr++)
        {
            cout << "subTriangle\n";
            subTriangles[ctr].printTriangle();
        }
    }
}

Here is how I call it in my main:

int main()
{
    TriangleDynamic t = TriangleDynamic();
    t.splitTriangleProject(0,3,Point(), 1);
    t.printTriangle();
    cin.get();
    return 0;
}

I think I've posted too much at this point. Any help is appreciated, thanks in advance.


回答1:


The issue is right here

    TriangleDynamic t1(p1 , newEdge1Mid , newEdge3Mid);
    subTriangles.push_back(t1);

    TriangleDynamic t2(newEdge1Mid, p2, newEdge2Mid);
    subTriangles.push_back(t2);

    TriangleDynamic t3(newEdge3Mid, newEdge2Mid, p3);
    subTriangles.push_back(t3);

    TriangleDynamic t4(newEdge1Mid, newEdge2Mid, newEdge3Mid);
    subTriangles.push_back(t4);

    t1.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
    t2.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
    t3.splitTriangleProject( currentLevel + 1, maxLevel, org, radius); 
    t4.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);

Note how you push a copy of the triangle into the subTriangles vector before you call splitTrangleProject.

Thus the triangles in the vector did not have splitTriangleProject called on them.

Move the pushbacks to the end of the code and it should work.

    TriangleDynamic t1(p1 , newEdge1Mid , newEdge3Mid);


    TriangleDynamic t2(newEdge1Mid, p2, newEdge2Mid);


    TriangleDynamic t3(newEdge3Mid, newEdge2Mid, p3);


    TriangleDynamic t4(newEdge1Mid, newEdge2Mid, newEdge3Mid);


    t1.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
    t2.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
    t3.splitTriangleProject( currentLevel + 1, maxLevel, org, radius); 
    t4.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);

    subTriangles.push_back(t3);
    subTriangles.push_back(t2);
    subTriangles.push_back(t1);
    subTriangles.push_back(t4);

(Also, on another note, if this code starts getting slow it could be greatly sped up with a C++11 std::move. Don't go into pointers unless you have to.)




回答2:


After computing the subtriangles inside splitTriangleProject(), you need to retrieve them and add to the class'es own list (subTriangles). Like this:

void splitTriangleProject( int currentLevel, int maxLevel, const Point &org, double radius)
{
// your code above

subTriangles.insert(subTriangles.begin(), t1.subTriangles.begin(), t1.subTriangles.end());
subTriangles.insert(subTriangles.begin(), t2.subTriangles.begin(), t2.subTriangles.end());
subTriangles.insert(subTriangles.begin(), t3.subTriangles.begin(), t3.subTriangles.end());
subTriangles.insert(subTriangles.begin(), t4.subTriangles.begin(), t4.subTriangles.end());

}

Then you need to add an additional access method "const vector& getSubTriangles()". (Right now you seem to share all member variables as public which is not a good practise)




回答3:


When you push_back a triangle into the vector, it pushes a copy of the triangle. You then recurse on t1 to t4, but this recursion won't affect what has already been pushed into the vector, as it is a copy.



来源:https://stackoverflow.com/questions/9331404/c-vector-loses-data-in-recursive-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!