Fibonacci Word Fractal

I saw this topic: http://www.cplusplus.com/forum/general/254904/
And decided to make a fractal from it... You'll need to include "vector".
I'm not very good on c++, but you guys might like it.

So i made it using CImg (http://cimg.eu/):
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
// FIBONACCI WORD
string FiboWord(int Iter)
{
	string Last; Last.push_back('0');
	if (Iter < 1) { return (Last); }
	string Now; Now += Last; Now.push_back('1');
	if (Iter < 2 && Iter > 1) { return (Now); }
	string Next;
	for (int n = 3; n <= Iter; ++n)
	{
		Next = Now + Last;
		Last = Now;
		Now = Next;
	}
	return (Next);
}

// #######

// FIBONACCI WORD FRACTAL COORDINATES:
vector<vector<int>> FiboWordFrac(string Word)
{
	vector<vector<int>> Coord(2); Coord[0].push_back(0); Coord[1].push_back(0); Coord[0].push_back(0); Coord[1].push_back(1); // Makes a vertical bar, x0 = 0, y0 = 0, x1 = 0, y1 = 1;
	int x = 0, y = 1;
	short Dir = 0; // Dir = Direction; 0 = Up; 1 = Down; 2 = Left; 3 = Right;
	bool First = true;
	if (Word.size() < 1) { return (Coord); }
	for (int n = 1; n < Word.length(); ++n)
	{
		if (!First)
		{
			if (Dir == 0) { ++y; Coord[0].push_back(x); Coord[1].push_back(y); } else if (Dir == 3) { ++x; Coord[0].push_back(x); Coord[1].push_back(y); }
			else if (Dir == 1) { --y; Coord[0].push_back(x); Coord[1].push_back(y); } else if (Dir == 2) { --x;  Coord[0].push_back(x); Coord[1].push_back(y); }
		}
		if (First) { First = false; }
		if (Word.at(n) == '0')
		{
			if (n % 2 == 0)	{ if (Dir == 0) { Dir = 2; } else if (Dir == 3) { Dir = 0; } else if (Dir == 1) { Dir = 3; } else if (Dir == 2) { Dir = 1; } } // Change direction
			else { if (Dir == 0) { Dir = 3; } else if (Dir == 3) { Dir = 1; } else if (Dir == 1) { Dir = 2; } else if (Dir == 2) { Dir = 0; } } // Change direction
		}
	}
	return (Coord);
}


In another header i made:
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
// PLOT BRESENHAM LINES: <-- It can be any function that draws a line, i just had this one in hand
void Linexy(CImg<unsigned char>& Img, int Thisx1, int Thisy1, int Thisx2, int Thisy2, int R, int G, int B)
{
	int Thisx, Thisy, dx, dy, dx1, dy1, px, py, xe, ye, Thisi;
	dx = Thisx2 - Thisx1;
	dy = Thisy2 - Thisy1;
	dx1 = fabs(dx);
	dy1 = fabs(dy);
	px = 2 * dy1 - dx1;
	py = 2 * dx1 - dy1;
	unsigned char Color[] = { R, G, B };
	if (dy1 <= dx1)
	{
		if (dx >= 0) { Thisx = Thisx1; Thisy = Thisy1; xe = Thisx2; }
		else { Thisx = Thisx2; Thisy = Thisy2; xe = Thisx1; }
		Img.draw_point(Thisx, Thisy, Color);
		for (Thisi = 0; Thisx < xe; Thisi++)
		{
			Thisx = Thisx + 1;
			if (px < 0) { px = px + 2 * dy1; }
			else { if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0)) { Thisy = Thisy + 1; } else { Thisy = Thisy - 1; } px = px + 2 * (dy1 - dx1); }
			Img.draw_point(Thisx, Thisy, Color);
		}
	}
	else
	{
		if (dy >= 0) { Thisx = Thisx1; Thisy = Thisy1; ye = Thisy2; }
		else { Thisx = Thisx2; Thisy = Thisy2; ye = Thisy1; }
		Img.draw_point(Thisx, Thisy, Color);
		for (Thisi = 0; Thisy < ye; Thisi++)
		{
			Thisy = Thisy + 1;
			if (py <= 0) { py = py + 2 * dx1; }
			else { if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0)) { Thisx = Thisx + 1; } else { Thisx = Thisx - 1; }	py = py + 2 * (dx1 - dy1); }
			Img.draw_point(Thisx, Thisy, Color);
		}
	}
}

// PRINT IT:
CImg<unsigned char> PrintFiboWordFrac(vector<vector<int>> Coord, int SegmentSize)
{
	int maxx = Coord[0][0], minx = Coord[0][0], maxy = Coord[1][0], miny = Coord[1][0];
	for (int n = 0; n < Coord[0].size(); ++n)
	{
		if (Coord[0][n] > maxx) { maxx = Coord[0][n]; } if (Coord[0][n] < minx) { minx = Coord[0][n]; }
		if (Coord[1][n] > maxy) { maxy = Coord[1][n]; } if (Coord[1][n] < miny) { miny = Coord[1][n]; }
	}
	int sx = round((abs(maxx) + abs(minx) + 1) * SegmentSize), sy = round((abs(maxy) + abs(miny) + 2) * SegmentSize);
	CImg<unsigned char> Fractal(sx, sy, 1, 3, 0);

	for (int n = 1; n < Coord[0].size(); ++n)
	{
		int R = 0, G = 0, B = 0; // CHANGE IT!!!!!!!
		Linexy(Fractal, ((Coord[0][n - 1] + 1) * SegmentSize), ((Coord[1][n - 1] + 1) * SegmentSize), ((Coord[0][n] + 1) * SegmentSize), ((Coord[1][n] + 1) * SegmentSize), R, G, B);
	}
	return (Fractal);
}

And to choose parameters:
1
2
int Opa, Opl; cout << "Iterations: "; cin >> Opa; cout << "Lenght: "; cin >> Opl;
PrintFiboWordFrac(FiboWordFrac(FiboWord(Opa)), Opl).save_bmp("FiboWordFrac.bmp");


This is the resulting image with red color and black background:
https://i.imgur.com/vnrOZkU.png
Last edited on
Nice, pretty cool. I noticed that fractal too on the wikipedia page but didn't make it:)

Minor formatting complaint, I don't think it helps readability to put everything on one line like this
else { if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0)) { Thisy = Thisy + 1; } else { Thisy = Thisy - 1; } px = px + 2 * (dy1 - dx1); }
You seem to like doing this a lot. It's up to you, I just don't recommend t.
Last edited on
Cool program! Too bad it wasn't complete so we could run it easily.

BTW, as Iter is an int, this will be a rare event indeed:

 
if (Iter < 2 && Iter > 1) { return (Now); }

Last edited on
Also,
vector<vector<int>> Coord(2); Coord[0].push_back(0); Coord[1].push_back(0); Coord[0].push_back(0); Coord[1].push_back(1);
This can just become,
vector<vector<int>> Coord = { {0, 0}, {0, 1} };

And std::abs can be used instead of std::fabs because C++ has function overloading, but I suppose it doesn't really matter.
Last edited on
Here's a (untested and possibly not-quite-right) re-write of one of your functions. It uses a Point struct. You might want to rewrite your code to use a Point struct.

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
struct Point {
    int x, y;
};

enum {Up, Down, Left, Right};

vector<Point>
FiboWordFrac(string Word) {

    static int nextDir[2][4] = {
        { Left,  Up,   Right, Down },
        { Right, Down, Left,  Up }
    };

    vector<Point> Coord;
    Coord.push_back(Point(0,0));
    Coord.push_back(Point(0,1));

    if (Word.size() < 2) return Coord;

    int x = 0, y = 1;
    int Dir = Up;

    if (Word.at(1) == '0') Dir = nextDir[1][Dir];

    for (int n = 2; n < Word.length(); ++n) {
        if      (Dir == Up   ) ++y;
        else if (Dir == Right) ++x;
        else if (Dir == Down ) --y;
        else if (Dir == Left ) --x; 
        Coord.push_back(Point(x, y));
        if (Word.at(n) == '0') Dir = nextDir[n % 2][Dir];
    }

    return Coord;
}

Last edited on
I took another look at your program. My first rewrite above wasn't quite right. This one seems to work.

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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//For ubuntu:
//$ sudo apt-get install libx11-dev
//$ sudo apt-get install cimg-dev
//$ g++ -Wall prog.cpp -lpthread -lX11

#include <iostream>
#include <string>
#include <vector>
#include <CImg.h>

using Byte = unsigned char;
using Image = cimg_library::CImg<Byte>;

enum {Up, Down, Left, Right};

struct Point
{
    int x, y;
    Point(int x, int y) : x(x), y(y) {}
};

std::ostream& operator<<(std::ostream& os, const Point& p)
{
    return os << '(' << p.x << ',' << p.y << ')';
}

void DrawLine(Image& img,
              int x0, int y0, int x1, int y1,
              Byte r, Byte g, Byte b)
{
    Byte color[] = { r, g, b };
    img.draw_line(x0, y0, x1, y1, color);
}

std::vector<Point> FiboWordFrac(std::string word)
{
    static int nextDir[2][4] = {
        { Left,  Right, Down,  Up },
        { Right, Left,  Up,    Down }
    };
    std::vector<Point> coord { {0, 0} };
    int x = 0, y = 0;
    int dir = Up;

    for (size_t n = 1; n < word.size(); ++n)
    {
        if      (dir == Up   ) ++y;
        else if (dir == Right) ++x;
        else if (dir == Down ) --y;
        else if (dir == Left ) --x;

        coord.push_back({x, y});

        if (word.at(n) == '0') dir = nextDir[n % 2][dir];
    }

    return coord;
}

Image DrawFiboWordFrac(const std::vector<Point>& coord, int segmentSize)
{
    Point max(coord[0]), min(coord[0]);
    for (size_t n = 1; n < coord.size(); ++n) {
        if      (coord[n].x > max.x) max.x = coord[n].x;
        else if (coord[n].x < min.x) min.x = coord[n].x;
        if      (coord[n].y > max.y) max.y = coord[n].y;
        else if (coord[n].y < min.y) min.y = coord[n].y;
    }

    int sx = (max.x - min.x + 1) * segmentSize,
        sy = (max.y - min.y + 1) * segmentSize;

    std::cout << "max: " << max << "   min: " << min << '\n';
    std::cout << "sx: " << sx << "  sy: " << sy << '\n';

    Image fractal(sx, sy, 1, 3, 0);

    for (size_t n = 1; n < coord.size(); ++n)
        DrawLine(fractal,
                 (coord[n - 1].x - min.x) * segmentSize,
                 (coord[n - 1].y - min.y) * segmentSize,
                 (coord[n    ].x - min.x) * segmentSize,
                 (coord[n    ].y - min.y) * segmentSize,
                 255, 0, 0);

    return fractal;
}

std::string FiboWord(int iters)
{
    if (iters < 1) return "0";
    std::string prev {"0"}, now{"01"}, next;
    for (int n = 2; n < iters; ++n) {
        next = now + prev;
        prev = now;
        now = next;
    }
    return now;
}

int main()
{
    int iters = 20, len = 5;
    auto word = FiboWord(iters);
    auto frac = FiboWordFrac(word);
    std::cout << "frac.size: " << frac.size() << '\n';
    auto img = DrawFiboWordFrac(frac, len);
    img.save_bmp("fibowordfrac.bmp");
}

Last edited on
You guys are amazing, I'm very gladly, thanks! I couldn't imagine so much resuming...
Also, sorry taking long to answer, i was very occupied today...
Sorry for the formating mistakes, i'll from now on post on this forum the working program and not just mere functions, also, in a readable way :p...
Also, i forgot to say the bresenham lines, i used because i already had it, but people can simple use any function that draw lines...


@dutch Omg, i can't believe i made this formula "Iter < 2 && Iter > 1", it should have been "Iter < 3"...

@Ganado, hmm, i don't knew about this "fabs" thing, i'll be honest that i "stole" this function from somewhere in "Stackoverflow", can't find the link here, I'll check it out better...

@dutch, the program is working perfectly now, i'm thankful for your effort!
Sorry any "newbism" from me on this forum! I'll make more proper posts next time...
Last edited on
Topic archived. No new replies allowed.