分形树-未绘制分支

时间:2018-08-01 15:06:34

标签: c++ graphics iteration sfml fractals

当前,我正在尝试通过IFS(迭代功能系统)绘制对称的二叉树:

但是结果总是只有分支提示:

我无法弄清楚自己做错了什么或缺少了什么。

这是IFS:

here

这是我的代码:

RenderWindow window(VideoMode(480, 640), "fractals everywhere");
CircleShape point(1);
int chance;
float x, y, w, h, nx, ny, px, py;

void SymmetricBinaryTrees()
{
    float r = 0.57f;
    float o = 0.785f;

    chance = rand() % 3;

    switch (chance)
    {
    case 0:
        nx = r * cos(o) * x + (-1 * r * sin(o) * y);
        ny = r * sin(o) * x + r * cos(o) * y + 1;
        break;
    case 1:
        nx = r * cos(o) * x + r * sin(o) * y;
        ny = -1 * r * sin(o) * x + r * cos(o) * y + 1;
        break;
    case 2:
        nx = x;
        ny = y;
        break;
    }
}

void nextPoint()
{
    SymmetricBinaryTrees();

    x = nx; y = ny;
}

void drawPoint()
{
    px = _map(x, -1.078, 1.078f, 0, w); py = _map(y, 0.f, 2.078f, h, 0); // maps the position accordingly
    point.setPosition(px, py);

    window.draw(point);
}

int main()
{
    srand(time(NULL));

    w = window.getSize().x * 1.f;
    h = window.getSize().y * 1.f;

    x = 0.f; y = 0.f;

    window.setFramerateLimit(60);

    while (window.isOpen())
    {
        Event e;

        while (window.pollEvent(e))
            if (e.type == Event::Closed) window.close();

        for (int i = 1; i <= 500; i++)
        {
            drawPoint();
            nextPoint();
        }

        window.display();
    }
    return 0;
}

This是我用于代码的网站。

如果有人可以帮助我或有任何想法,我将非常感谢,谢谢。

3 个答案:

答案 0 :(得分:4)

我分享@令人惊讶的观点,我认为您使事情变得过于复杂。使用其他方法会更容易。让我们变得更容易。

使用递归函数,我们可以轻松地理解每个步骤应该执行的操作。 考虑我们从一个初始点开始,然后在给定长度的一个角度上跟踪一条线,因此我们需要像这样的功能:

void createTreeRecursive(sf::VertexArray &tree, sf::Vector2f point, float angle, float lenght)

tree将是我们的行集,它组成了树本身。

我们要做的第一件事就是设置第一个点,这已经是众所周知的:

// Add first point
tree.append(sf::Vertex(point, treeColor));

现在,我们需要计算下一点,以形成一条线。使用简单的三角函数,我们可以确定该点:

float newX = point.x + (cos((2.f * PI / 360.f) * angle) * lenght);
float newY = point.y - (sin((2.f * PI / 360.f) * angle) * lenght);  // Caution here! Minus(-) sign because we're drawing upwards

因此,我们添加第二个点,然后将树分成2个新分支,每个分支都旋转了一定程度:

// Add second point
tree.append(sf::Vertex(nextPoint, treeColor));

// Create sub-tree from 2nd point, rotating +45 degrees (i.e. counterclockwise), reducing lenght of the new branch by 0.6 factor
createTreeRecursive(tree, nextPoint, angle + O, lenght * R);

// Same with the other sub-tree, but rotating -45 (i.e. clockwise)
createTreeRecursive(tree, nextPoint, angle - O, lenght * R);

我们需要一个基本的递归函数,在这种情况下,我选择3作为最小长度:

if (lenght < 3)
    // End condition, can be modified
    return;

必须先检查一下。

因此,我们完成了,我们只需要初始调用:

sf::VertexArray createTree(){
    // Our tree will be made out of lines
    sf::VertexArray ret(sf::PrimitiveType::Lines);
    // Initial point at botton-center(250, 450), with a 90 degrees rotation, first branch lenght 200 
    createTreeRecursive(ret, sf::Vector2f(250, 450), 90, 200);
    return ret;
}

结果是:

enter image description here

完整代码

#include <SFML/Graphics.hpp>

const double PI = 3.141592;
const double R = 0.57;  // Reduction factor
const double O = 45;    // Degree rotation each time
sf::Color treeColor = sf::Color::Blue;

void createTreeRecursive(sf::VertexArray &tree, sf::Vector2f point, float angle, float lenght){
    if (lenght < 3)
        // End condition, can be modified
        return;

    // Add first point
    tree.append(sf::Vertex(point, treeColor));
    float newX = point.x + (cos((2.f * PI / 360.f) * angle) * lenght);
    float newY = point.y - (sin((2.f * PI / 360.f) * angle) * lenght);  // Caution here! Minus(-) sign because we're drawing upwards
    sf::Vector2f nextPoint(newX, newY);
    // Add second point
    tree.append(sf::Vertex(nextPoint, treeColor));

    // Create sub-tree from 2nd point, rotating +45 degrees (i.e. counterclockwise), reducing lenght of the new branch by 0.6 factor
    createTreeRecursive(tree, nextPoint, angle + O, lenght * R);

    // Same with the other sub-tree, but rotating -45 (i.e. clockwise)
    createTreeRecursive(tree, nextPoint, angle - O, lenght * R);
}

sf::VertexArray createTree(){
    // Our tree will be made out of lines
    sf::VertexArray ret(sf::PrimitiveType::Lines);
    // Initial point at botton-center(250, 450), with a 90 degrees rotation, first branch lenght 200 
    createTreeRecursive(ret, sf::Vector2f(250, 450), 90, 200);
    return ret;
}

int main()
{
    RenderWindow window({ 500, 500 }, "SFML Tree", Style::Close);

    auto tree = createTree();

    while (window.isOpen())
    {
        for (Event event; window.pollEvent(event);){
            if (event.type == Event::Closed)
                window.close();
        }

        window.clear();
        window.draw(tree);
        window.display();
    }
    return EXIT_SUCCESS;
}

答案 1 :(得分:0)

我建议您将递归与以下功能一起使用:1)绘制当前分支(作为一行),然后2)从当前分支创建两个新分支。使用全局变量也无济于事。看来您应该重新考虑自己的方法。

答案 2 :(得分:0)

对于 Linux 是:

<%= form.submit %>