关于递归:C ++ / SFML:使用两个递归调用将凸形打印到屏幕上仅显示第一个递归调用中的形状,而不显示第二个

C++ / SFML: Printing convex shapes to the screen using two recursive calls only displays the shapes from the first recursive call and not the second

我正在使用SFML并在C ++中进行编码。我正在编写的程序必须是递归实现。

我的目标是创建一个函数,该函数根据先前绘制的正方形在屏幕上的不同位置和旋转位置上递归绘制正方形。

每个随后的正方形都应小于上一个函数调用,并向左(从前一个正方形的左角)旋转45度或向前一个正方形的右侧旋转45度。

每个新方块会再产生两个方块等。

我的想法是将一个正方形的左上角点和右上角点传递给两个不同的递归函数调用,并将这些点用作后续正方形的起点。

虽然生成的平方也将通过左上角和右上角传递给递归函数调用等。

我开发的代码没有显示应该由递归函数调用生成的两个平方。仅显示一侧。

我已经开发了以下代码(请原谅我的代码。.我用C ++编码已经很长时间了..)

程序驱动程序(main.cpp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include"PTree.hpp"

using namespace std;
using namespace sf;

int main( int argc, char* argv[ ] )
{
  double L = 0.0; // Length of square sides
  int N = 0; // Number of times to call recursive function          

  L = atol( argv[ 1 ] );
  N = atoi( argv[ 2 ] );
  Vector2f vPoint;
  vPoint.x = 0;
  vPoint.y = 0;

  // Create and Display Window
  PTree tree( L, N );
  return 0;
}

(PTree.hpp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef PTREE_H
#define PTREE_H

using namespace std;
using namespace sf;

class PTree /*:public sf::Drawable, public sf::Transformable*/{
public:
  // Constructor
  PTree( double L, int N );
  // Destructor
  ~PTree();

  // Recursive function to draw Pythagorias Tree
  void pTree( double L, int N, Vector2f vPoint, Vector2f vOrigin, float rotation );

private:
  float width = 0;
  float height = 0;
  int originX = 0;
  int originY = 0;
  float rotation = 0;
  RenderWindow window;
  int angle1 = 0;
  int angle2 = 0;

};

#endif // PTREE_H included

(PTree.cpp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <math.h>
#include"PTree.hpp"
#include <iostream>

using namespace std;
using namespace sf;

// Constructor
PTree::PTree( double L, int N )
{
  width = ( 6 * L );
  height = ( 4 * L );
  Vector2f vPoint = { width/2, height - 1 };
  Vector2f vOrigin;
  vOrigin.x = L/2;
  vOrigin.y = L;
  /* vPoint.x = width/2;
  vPoint.y = height - 1;
 */

  window.create( VideoMode( width, height ),"Pythagoras Fractal Tree" );
  pTree( L, N, vPoint, vOrigin, 0 );
}

// Destructor
PTree::~PTree(){}
/*###########################################################################*/

// Recursive function to draw Pythagorias Tree
void PTree::pTree( double L, int N, Vector2f vPoint, Vector2f vOrigin, float rotation  )
{
  Vector2f vPointR;

  if( N < 1 )
  {
    return;
  }

  // Define a convex shape called convexSquare
  ConvexShape convexSquare( 4 );
  convexSquare.setPoint( 0, Vector2f( 0, 0 ));
  convexSquare.setPoint( 1, Vector2f( 0, L ));
  convexSquare.setPoint( 2, Vector2f( L, L ));
  convexSquare.setPoint( 3, Vector2f( L, 0 ));

  convexSquare.setOutlineThickness( 1.f );
  convexSquare.setFillColor( Color::Black );
  convexSquare.setOutlineColor( Color::White );

  convexSquare.setPosition( vPoint );
  convexSquare.setOrigin( vOrigin );
  convexSquare.setRotation( rotation );

  while( window.isOpen( ))
  {
    Event event;
    while( window.pollEvent( event ))
    {
      if( event.type == Event::Closed )
      {
        window.close( );
      }
    }
    if( N >= 0 )
    {
    window.draw( convexSquare );
    window.display( );
    L = ( L * ( sqrt(2)/2 ));
    N = N - 1;
    rotation = rotation - 135;
    cout <<"LOOPS:" << N << endl;

//left
    vPoint = convexSquare.getTransform( ).transformPoint(   convexSquare.getPoint( 0 ));
    vOrigin = convexSquare.getPoint( (angle1) );
    pTree( L, N, vPoint, vOrigin, rotation );
    angle1 = (( angle1 + 1 ) % 4 );

//right
    vPointR = convexSquare.getTransform( ).transformPoint( convexSquare.getPoint( 3 ));
    vOrigin = convexSquare.getPoint( 2 );
    pTree( L, N, vPointR, vOrigin, rotation-90 );

    }
  }
cout <<"X value =" << vPoint.x <<"     Y value =" << vPoint.y << endl;

到目前为止,我已经尝试将凸形的各个点返回给函数pTree的第二次递归调用。这也没有显示任何内容。

最初,我只使用Vector2f vPoint并在每次递归调用之前对其进行修改,但是在用完解决方案的知识后,我专门为右侧正方形创建了一个新的变量,称为Vector2f vPointR。

SFML文档没有为像我这样的菜鸟提供足够的示例。该API本质上是一个选项列表,其中每个功能都包含最少的示例。我已尽我所能搜索互联网,以查看我是否传递了错误的观点,但找不到答案。

起作用的一件事(尽管并不完全正确)是当我切换递归调用时……这意味着我将对右侧正方形的调用移到了对左侧正方形的调用之前,但是这样做的问题是左侧s
quares没有显示。

在这一点上,我还试图为每个正方形计算出适当的旋转角度,但这是我最少的问题。

我尝试递归显示这些正方形的方式是否存在问题?

除了堆栈溢出以外,我不确定从这里可以得到的帮助。

感谢您的宝贵时间和专业知识。


不要递归调用整个while循环。 仅递归调用图形部分

1
2
3
4
5
6
7
8
9
10
11
12
13
// Initialize window...

while (window.isOpen())
{
    sf::Event event;
    // Handle events...

    window.clear();

    // call the recursive function here

    window.display();
}

另外,您可能希望使用sf::RectangleShape而不是sf::ConvexShape进行绘制

这是一个可行的"示例":

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <SFML/Graphics.hpp>
#include <cmath>

void drawPythagoreanTree(sf::RenderTarget&, const float, const int);

int main()
{
    const float L = 150;
    const int N = 14;

    const unsigned width = static_cast<unsigned>(6 * L);
    const unsigned height = static_cast<unsigned>(4 * L);
    sf::RenderWindow window{{width, height},"Pythagorean Tree"};
    while (window.isOpen())
    {
        for (sf::Event event; window.pollEvent(event);)
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }
        window.clear(sf::Color::White);
        drawPythagoreanTree(window, L, N);
        window.display();
    }
}

void drawPythagoreanTree(sf::RenderTarget& target, const int N,
                         const sf::RectangleShape& parent)
{
    static const float halfSqrt2 = sqrt(2.f) / 2;

    if (N < 1) return;
    target.draw(parent);
    auto const& sz = parent.getSize();
    auto const& tf = parent.getTransform();

    auto childL = parent;                    // copy parent's color and rotation
    childL.setSize(sz * halfSqrt2);          // resize
    childL.setOrigin(0, childL.getSize().y); // bottom left corner
    childL.setPosition(tf.transformPoint({0, 0})); // reposition
    childL.rotate(-45);
    drawPythagoreanTree(target, N - 1, childL);

    auto childR = parent;               // copy parent's color and rotation
    childR.setSize(sz * halfSqrt2);     // resize
    childR.setOrigin(childR.getSize()); // bottom right corner
    childR.setPosition(tf.transformPoint({sz.x, 0})); // reposition
    childR.rotate(45);
    drawPythagoreanTree(target, N - 1, childR);
}

void drawPythagoreanTree(sf::RenderTarget& target, const float L, const int N)
{
    sf::RectangleShape rect{{L, L}};
    // set origin to center of the rect, easier to center position on screen
    rect.setOrigin(rect.getSize() / 2.f);
    rect.setPosition(target.getSize().x / 2.f, target.getSize().y - L / 2.f);
    rect.setFillColor(sf::Color::Black);
    drawPythagoreanTree(target, N, rect);
}