Draw an Equilateral Triangle using FLTK (indirectly)

Pages: 12
Mar 25, 2017 at 9:19pm
I'm doing an exercise in my C++ intro book where I have to draw a series of regular polygons, one inside another, starting with an equilateral triangle. I drew the triangle the same way as shown in an example in the book. I don't really get what point of the triangle goes where (like, which one's the top point, the bottom-left, and the bottom-right). I intend to move the triangle to the middle of the window as it's currently a bit to left and up-top.

The book I'm reading is PPP2, of course, and it's Chapter 12 Exercise 11.
Specifications:

Draw a series of regular polygons, one inside the other. The innermost
should be an equilateral triangle, enclosed by a square, enclosed by a
pentagon, etc. For the mathematically adept only: let all the points of
each N -polygon touch sides of the (N+1) -polygon. Hint: The trigonomet-
ric functions are found in <cmath> (§24.8, §B.9.2).


I'm not that mathematically adept, but I still want to give that last part of the exercise a try. I'll do that later, though.

Here's the code I have now:
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
// Osman Zakir
// 3 / 22 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 12 Exercise 11
// File chapter12ex11.cpp
// Exercise Specifications:
/**
* Draw a series of regular polygons, one inside the other. The innermost
* should be an equilateral triangle, enclosed by a square, enclosed by a
* pentagon, etc. For the mathematically adept only: let all the points of
* each N-polygon touch sides of the (N+1) -polygon. Hint: The trigonometric
* functions are found in <cmath> (§24.8, §B.9.2).
*/

#include "../../Simple_window.h"
#include "../../Graph.h"

int main()
{
	using namespace Graph_lib;

	Point top_left{ 200, 200 };

	Simple_window win{ top_left, 600, 400, "Polygons" };

	try
	{
		Graph_lib::Polygon poly;

		poly.add(Point{ 300, 200 });
		poly.add(Point{ 350, 100 });
		poly.add(Point{ 400, 200 });

		poly.set_color(Color::black);

		win.attach(poly);
		win.wait_for_button();
	}
	catch (const runtime_error &rte)
	{
		Text err_msg_start{ Point{ 150, 200 }, "Runtime_error: " };
		Text err_msg{ Point{ 250, 200 }, rte.what() };

		err_msg_start.set_color(Color::black);
		err_msg.set_color(Color::black);

		win.attach(err_msg_start);
		win.attach(err_msg);

		win.wait_for_button();
		return 1;
	}
}


I uploaded the output image to Photobucket this time. Here's the link: http://i197.photobucket.com/albums/aa143/Osman456/IMG_2464_zpsngvz5oga.jpg (taken with my iPhone).
Last edited on Mar 25, 2017 at 9:20pm
Mar 25, 2017 at 10:42pm
1
2
x = r * cosθ
y = r * sinθ

This is the parametric equation of a circle but it can be generalised to any regular N-sided polygon. For each θ you input, the above formula will output a point that lies on a circle with radius r. For example, if you wanted a circle with radius 100,
1
2
3
4
5
6
7
8
9
10
constexpr int radius{ 100 };

Graph_lib::Polygon poly;
for( int deg{}; deg < 360; deg++ ) {
    Point pt{
        radius * cos( deg * M_PI/180 ),
        radius * sin( deg * M_PI/180 )
    };
    poly.add( pt );
}


Now say we wanted a triangle. Each iteration, we would need θ to increase by 120° as 360°/3 = 120°.
1
2
3
4
5
6
7
for( int deg{}; deg < 360; deg += 120 ) {
    Point pt{
        radius * cos( deg * M_PI/180 ),
        radius * sin( deg * M_PI/180 )
    };
    poly.add( pt );
}


In general, we increase θ by 360/N to get each corner of a regular N-sided polygon. Note that the polygon's origin is at (0, 0). Simply add win_width/2 and win_height/2 to each x and y ordinate, respectively, to get the polygon centered in your window.
Last edited on Mar 25, 2017 at 10:44pm
Mar 25, 2017 at 11:38pm
The loop is good and all, but I think the exercise is asking for me to hard-code the values. The GUI code mixed with algorithms comes later in the book. It mentions that in Chapter 12 itself.

So for each polygon, I add points with x-axis being win_width/2 and win_height/2 if I want it centered in the window? No matter what polygon it is? Or does that only apply to triangles? For the triangle I have now, if I do (600,400), (650, 300), (700,400), and it'll by centered in my window? Or does it not mean the current x- and y-coordinates?
Last edited on Mar 25, 2017 at 11:39pm
Mar 25, 2017 at 11:48pm
The loop is good and all, but I think the exercise is asking for me to hard-code the values.

I don't think it is a good practice to hard code values, especially when you can let the computer do it for you.

So for each polygon, I add points with x-axis being win_width/2 and win_height/2 if I want it centered in the window?

I meant it like so:
1
2
3
4
5
6
7
8
for( int deg{}; deg < 360; deg += 120 ) {
    Point pt{
        radius * cos( deg * M_PI/180 ) + win_width/2.0,
        // note the -; y-values grow down, not up
        radius * sin( deg * M_PI/180 ) - win_height/2.0
    };
    poly.add( pt );
}

This will center the polygon in the middle of your window.
Mar 26, 2017 at 12:05am
That's not what I mean. I really mean that the algorithmic and logical stuff is later in the book for the GUI stuff. I don't want to get ahead of myself. I like algorithms and logic more, too, but I'm trying to follow the book here.

This is from Chapter 12 in the book:

From the primitive graphics elements you see in this window, you can build dis-
plays of just about any complexity and subtlety. For now, just note a peculiarity
of the code in this chapter: there are no loops, no selection statements, and all
data was “hardwired” in. The output was just composed of primitives in the
simplest possible way. Once we start composing these primitives using data and
algorithms, things will start to get interesting.


I'm inferring from this that I have to wait for the book to get to the real juicy stuff with the GUI programming. That's why I this this program's values are probably meant to be hard-coded. I hope I'm wrong, though.

But if I use those loops, do I use a separate one for each polygon I draw? How do I determine the number of points in the loop and make it stop where I intend it to?
Last edited on Mar 26, 2017 at 12:06am
Mar 26, 2017 at 12:52am
But if I use those loops, do I use a separate one for each polygon I draw?

Yes.

How do I determine the number of points in the loop and make it stop where I intend it to?
1
2
3
4
5
6
7
8
9
constexpr int revolution{ 360 } sides{ 3 };
for( int deg{}; deg < revolution; deg += revolution/sides ) {
    Point pt{
        radius * cos( deg * M_PI/180 ) + win_width/2.0,
        // note the -; y-values grow down, not up
        radius * sin( deg * M_PI/180 ) - win_height/2.0
    };
    poly.add( pt );
}

The terminating condition for the loop will always be the same. How much you increment deg (θ) depends on the number of sides of the polygon (360/N).
Mar 26, 2017 at 1:23am
Okay, thanks. I'll try it like that.

Also, you have suggestions for math stuff I should read up on for GUI programming? From Khan Academy if you know where the stuff is in there, since I've signed up there. I was thinking of doing some Linear Algebra, Trig and Differential Calculus since I read somewhere that I might need that for programming, especially GUI and other stuff. I just need to know what I should do to understand how to plot points for drawing text and polygon objects better.

I know up to High School Algebra and Geometry, with some basic Trig stuff (but I'll have to review it all since I don't remember much, as it was some years ago that I last did that stuff (in the US, around before 2009(in terms of years) I believe)).

Edit:
But if I make the sides variable constexpr, I won't be able to change it, right? And you're saying I have to write all that more than once in the same program for each polygon I have to make?
Last edited on Mar 26, 2017 at 1:26am
Mar 26, 2017 at 1:56am
But if I make the sides variable constexpr, I won't be able to change it, right? And you're saying I have to write all that more than once in the same program for each polygon I have to make?

Yes, and no. You can have a loop to control the number of sides.
For example,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
constexpr int revolution{ 360 }, max_sides{ 10 };
Vector_ref<Polygon> polys;
for( int i{ 3 }; i <= max_sides; i++ ) {
    Polygon poly{ new Polygon };
    for( int deg{}; deg < revolution; deg += revolution/i ) {
        Point pt{
            radius * cos( deg * M_PI/180 ) + win_width/2.0,
            // note the -; y-values grow down, not up
            radius * sin( deg * M_PI/180 ) - win_height/2.0
        };
        poly.add( pt );
    }
    polys.push_back( poly );
}

for( Polygon& p : polys )
    win.attach( p );


As for graphics programming, I'm not too sure.
Last edited on Mar 26, 2017 at 1:58am
Mar 26, 2017 at 12:12pm
The constructor for Point requires the coordinates as ints, so using a double is flagging a "conversion from 'double' to 'int' requires a narrowing conversion" error on both the x- and y-coordinates. And trying to use a copy constructor has the same thing happen. How do I fix this?

This is my code right now:
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
// Osman Zakir
// 3 / 22 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 12 Exercise 11
// File chapter12ex11.cpp
// Exercise Specifications:
/**
* Draw a series of regular polygons, one inside the other. The innermost
* should be an equilateral triangle, enclosed by a square, enclosed by a
* pentagon, etc. For the mathematically adept only: let all the points of
* each N-polygon touch sides of the (N+1) -polygon. Hint: The trigonometric
* functions are found in <cmath> (§24.8, §B.9.2).
*/

#include "../../Simple_window.h"
#include "../../Graph.h"
#include <cmath>

int main()
{
	using namespace Graph_lib;

	Point top_left{ 200, 200 };
	constexpr int win_width = 600;
	constexpr int win_height = 400;
	Simple_window win{ top_left, win_width, win_height, "Polygons" };

	try
	{
		Graph_lib::Polygon poly;

		constexpr int revolution{ 360 };
		constexpr int max_sides{ 8 };
		Vector_ref<Graph_lib::Polygon> polys;
		for (int i = 3; i <= max_sides; ++i)
		{
			Graph_lib::Polygon *poly = new Graph_lib::Polygon;
			double radius = 6.0;
			constexpr double pi = 3.14159265359;
			for (int deg = 0; deg < revolution; deg += revolution / i)
			{
				Point point
				{ 
					radius * cos(deg * pi / 180.0) + win_width / 2.0,
					radius * sin(deg * pi / 180.0) - win_height / 2.0 
				};
				poly->add(point);
			}
			polys.push_back(poly);
		}

		for (int i = 0; i < polys.size(); ++i)
		{
			win.attach(polys[i]);
		}
		win.wait_for_button();
	}
	catch (const runtime_error &rte)
	{
		Text err_msg_start{ Point{ 150, 200 }, "Runtime_error: " };
		Text err_msg{ Point{ 250, 200 }, rte.what() };

		err_msg_start.set_color(Color::black);
		err_msg.set_color(Color::black);

		win.attach(err_msg_start);
		win.attach(err_msg);

		win.wait_for_button();
		return 1;
	}
}


And these are the two errors (there are some warnings, too, but I'm not going to post those):

1>c:\users\osman\programming\visual studio 2017\projects\programming_principles_practice_using_c++\chapter12ex11\chapter12ex11\chapter12ex11.cpp(46): error C2398: Element '1': conversion from 'double' to 'int' requires a narrowing conversion
1>c:\users\osman\programming\visual studio 2017\projects\programming_principles_practice_using_c++\chapter12ex11\chapter12ex11\chapter12ex11.cpp(46): error C2398: Element '2': conversion from 'double' to 'int' requires a narrowing conversion


And by the way, a Vector_ref has no begin() or end() function, so a range-based for loop won't work for it.
Last edited on Mar 26, 2017 at 12:33pm
Mar 26, 2017 at 12:53pm
1
2
  radius * cos(deg * pi / 180.0) + win_width / 2.0,
  radius * sin(deg * pi / 180.0) - win_height / 2.0

You need to cast these values into an int before you pass them to the Point ctor.
Mar 26, 2017 at 1:24pm
I used a static_cast<int> and it worked. But now the polygons aren't showing up in the window. What happened? Did I use the wrong value for the radius variable or is there some other mistake?

Edit: Update.
I got something to happen, at least, but it's not something good. The runtime_error exception got triggered because "two polygons lie in a straight line". Now what do I do?

Here's the code:
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
// Osman Zakir
// 3 / 22 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 12 Exercise 11
// File chapter12ex11.cpp
// Exercise Specifications:
/**
* Draw a series of regular polygons, one inside the other. The innermost
* should be an equilateral triangle, enclosed by a square, enclosed by a
* pentagon, etc. For the mathematically adept only: let all the points of
* each N-polygon touch sides of the (N+1) -polygon. Hint: The trigonometric
* functions are found in <cmath> (§24.8, §B.9.2).
*/

#include "../../Simple_window.h"
#include "../../Graph.h"
#include <cmath>

int main()
{
	using namespace Graph_lib;

	Point top_left{ 100, 100 };
	constexpr int win_width = 600;
	constexpr int win_height = 400;
	Simple_window win{ top_left, win_width, win_height, "Polygons" };

	try
	{
		constexpr int revolution{ 360 };
		constexpr int max_sides{ 10 };
		Vector_ref<Graph_lib::Polygon> polys;
		for (int i = 3; i <= max_sides; ++i)
		{
			Graph_lib::Polygon *poly = new Graph_lib::Polygon;
			double radius = 4.0;
			constexpr double pi = 3.14159265359;
			for (int deg = 0; deg < revolution; deg += revolution / i)
			{
				Point point
				{ 
					static_cast<int>(radius * cos(deg * pi / 180.0) + win_width / 2.0),
					static_cast<int>(radius * sin(deg * pi / 180.0) - win_height / 2.0) 
				};
				poly->add(point);
				poly->set_color(Color::black);
			}
		}
		for (int i = 0; i < polys.size(); ++i)
		{
			win.attach(polys[i]);
		}
		win.wait_for_button();
	}
	catch (const runtime_error &rte)
	{
		Text err_msg_start{ Point{ 150, 200 }, "Runtime_error: " };
		Text err_msg{ Point{ 250, 200 }, rte.what() };

		err_msg_start.set_color(Color::black);
		err_msg.set_color(Color::black);

		win.attach(err_msg_start);
		win.attach(err_msg);

		win.wait_for_button();
		return 1;
	}
}
Last edited on Mar 26, 2017 at 3:48pm
Mar 26, 2017 at 8:41pm
I have no idea what this runtime_error means.
for (int i = 0; i < polys.size(); ++i) I guess this vector is empty since you don't add anything to it.
I did a little Win32 app with most of your code and it show that your y coordinates are outside the visible area. No wonder that nothing is visible.

Point X=304, Y=-200
Point X=297, Y=-196
Point X=298, Y=-203
Point X=304, Y=-200
Point X=299, Y=-196
Point X=296, Y=-200
Point X=300, Y=-204
Point X=304, Y=-200
Point X=301, Y=-196
Point X=296, Y=-197
Point X=296, Y=-202
Point X=301, Y=-203
Point X=304, Y=-200
Point X=301, Y=-196
Point X=297, Y=-196
Point X=296, Y=-200
Point X=298, Y=-203
Point X=302, Y=-203
Point X=304, Y=-200
Point X=302, Y=-196
Point X=299, Y=-196
Point X=296, Y=-198
Point X=296, Y=-201
Point X=298, Y=-203
Point X=302, Y=-203
Point X=303, Y=-200
Point X=304, Y=-200
Point X=302, Y=-197
Point X=299, Y=-196
Point X=297, Y=-197
Point X=296, Y=-200
Point X=297, Y=-202
Point X=300, Y=-204
Point X=302, Y=-202
Point X=304, Y=-200
Point X=303, Y=-197
Point X=300, Y=-196
Point X=297, Y=-196
Point X=296, Y=-198
Point X=296, Y=-201
Point X=298, Y=-203
Point X=300, Y=-203
Point X=303, Y=-202
Point X=304, Y=-200
Point X=303, Y=-197
Point X=301, Y=-196
Point X=298, Y=-196
Point X=296, Y=-197
Point X=296, Y=-200
Point X=296, Y=-202
Point X=298, Y=-203
Point X=301, Y=-203
Point X=303, Y=-202
** Size of polygons = 8


Hope this helps to find the problem.
Mar 26, 2017 at 10:20pm
Nothing was visible at first, but then that runtime error came up. I'm worried about it and I hope I can find a way to fix it.

I added the polygons to the vector, but now the program has a white, blank window and stops working. It freezes and then it either crashes or I have to kill it.

You think there might be a problem in my calculation?

Edit: Updated code:
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
// Osman Zakir
// 3 / 22 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 12 Exercise 11
// File chapter12ex11.cpp
// Exercise Specifications:
/**
* Draw a series of regular polygons, one inside the other. The innermost
* should be an equilateral triangle, enclosed by a square, enclosed by a
* pentagon, etc. For the mathematically adept only: let all the points of
* each N-polygon touch sides of the (N+1) -polygon. Hint: The trigonometric
* functions are found in <cmath> (§24.8, §B.9.2).
*/

#include "../../Simple_window.h"
#include "../../Graph.h"
#include <cmath>

int main()
{
	using namespace Graph_lib;

	Point top_left{ 100, 100 };
	constexpr int win_width = 600;
	constexpr int win_height = 400;
	Simple_window win{ top_left, win_width, win_height, "Polygons" };

	try
	{
		constexpr int revolution{ 360 };
		constexpr int max_sides{ 10 };
		Vector_ref<Graph_lib::Polygon> polys;
		Graph_lib::Polygon *poly = new Graph_lib::Polygon;
		for (int i = 3; i <= max_sides; ++i)
		{
			double radius = 4.0;
			constexpr double pi = 3.14159265359;
			for (int deg = 0; deg < revolution; deg += revolution / i)
			{
				Point point
				{ 
					static_cast<int>(radius * cos(deg * pi / 180.0) + win_width / 2.0),
					static_cast<int>(radius * sin(deg * pi / 180.0) - win_height / 2.0) 
				};
				poly->add(point);
				poly->set_color(Color::black);
				polys.push_back(poly);
			}
		}
		for (int i = 0; i < polys.size(); ++i)
		{
			win.attach(polys[i]);
		}
		delete[] poly;
		win.wait_for_button();
	}
	catch (const runtime_error &rte)
	{
		Text err_msg_start{ Point{ 150, 200 }, "Runtime_error: " };
		Text err_msg{ Point{ 250, 200 }, rte.what() };

		err_msg_start.set_color(Color::black);
		err_msg.set_color(Color::black);

		win.attach(err_msg_start);
		win.attach(err_msg);

		win.wait_for_button();
		return 1;
	}
	catch (const exception &e)
	{
		Text err_msg_start{ Point{ 150, 200 }, "Runtime_error: " };
		Text err_msg{ Point{ 250, 200 }, e.what() };

		err_msg_start.set_color(Color::black);
		err_msg.set_color(Color::black);

		win.attach(err_msg_start);
		win.attach(err_msg);

		win.wait_for_button();
		return 2;
	}
	catch (...)
	{
		Text err_msg{ Point{ 150, 200 }, "An unknown exception occurred." };

		err_msg.set_color(Color::black);

		win.attach(err_msg);

		return 3;
	}
}


I felt that maybe the problem is that I'm freeing my allocating memory with delete, but I guess that's not it either.

Edit2: Okay, the reason for it freezing up was the use of pointers in here, so I took out pointers and new and delete, which took care of that problem. But now there's that same runtime error again.

Why is my Y value outside the window, though? Help me with debugging that first, please.
Last edited on Mar 26, 2017 at 11:10pm
Mar 27, 2017 at 4:45am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
		Graph_lib::Polygon *poly = new Graph_lib::Polygon;
		for (int i = 3; i <= max_sides; ++i)
		{
			double radius = 4.0;
			constexpr double pi = 3.14159265359;
			for (int deg = 0; deg < revolution; deg += revolution / i)
			{
				Point point
				{ 
					static_cast<int>(radius * cos(deg * pi / 180.0) + win_width / 2.0),
					static_cast<int>(radius * sin(deg * pi / 180.0) - win_height / 2.0) 
				};
				poly->add(point);
				poly->set_color(Color::black);
				polys.push_back(poly);
			}
		}

You don't create a fresh poly every iteration of the outer for-loop. Thus, you will end up adding points for a triangle, square, pentagon, etc... to the same polygon. With a polygon, the lines can not intersect, which is probably why you're getting a runtime error.

1
2
3
4
5
Point point
{ 
    static_cast<int>(radius * cos(deg * pi / 180.0) + win_width / 2.0),
    static_cast<int>(radius * sin(deg * pi / 180.0) - win_height / 2.0) 
}

Also, the reason you were getting a narrowing conversion without the static_cast, is because uniform initialisation braces ({}) don't allow you to "down cast" and lose information. Instead of the ugly and verbose static_cast, use the function call brackets.
1
2
3
4
5
Point point
(
    radius * cos(deg * pi / 180.0) + win_width / 2.0),
    radius * sin(deg * pi / 180.0) - win_height / 2.0) 
)


delete[] poly;
No need to do this. Vector_ref cleans up in its destructor.
Mar 27, 2017 at 9:06am
With positive y values and a radius of 100 and the hints from interalfx it looks like this in my Win32 App. http://pasteboard.co/52u4vB9XZ.jpg
Mar 27, 2017 at 11:02am
That's not what I intended. I wanted them to be in the middle of the window and for the triangle's top point to be facing the top of the window. How do I make sure of that (I don't know how to correctly plot points, so you'll have to help me out there as well)?

Anyway, should I use dynamic memory allocation at all, or should I just let Vector_ref do it on its own and just fix my placement of polygon initialization?

Edit:
Update: The runtime error is taken care of and I'm using abs() now to make sure that both values are positive. But I still get nothing showing up on the window.

Code:
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
// Osman Zakir
// 3 / 22 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 12 Exercise 11
// File chapter12ex11.cpp
// Exercise Specifications:
/**
* Draw a series of regular polygons, one inside the other. The innermost
* should be an equilateral triangle, enclosed by a square, enclosed by a
* pentagon, etc. For the mathematically adept only: let all the points of
* each N-polygon touch sides of the (N+1) -polygon. Hint: The trigonometric
* functions are found in <cmath> (§24.8, §B.9.2).
*/

#include "../../Simple_window.h"
#include "../../Graph.h"
#include <cmath>

int main()
{
	using namespace Graph_lib;

	Point top_left{ 100, 100 };
	constexpr int win_width = 600;
	constexpr int win_height = 400;
	Simple_window win{ top_left, win_width, win_height, "Polygons" };

	try
	{
		constexpr int revolution{ 360 };
		constexpr int max_sides{ 10 };
		Vector_ref<Graph_lib::Polygon> polys;
		for (int i = 3; i <= max_sides; ++i)
		{
			Graph_lib::Polygon poly;
			double radius = 100.0;
			constexpr double pi = 3.14159265359;
			for (int deg = 0; deg < revolution; deg += revolution / i)
			{
				Point point
				{ 
					int(radius * cos(deg * pi / 180.0) + win_width / 2.0),
					abs(int(radius * sin(deg * pi / 180.0) - win_height / 2.0))
				};
				poly.add(point);
				poly.set_color(Color::black);
				polys.push_back(poly);
			}
		}
		for (int i = 0; i < polys.size(); ++i)
		{
			win.attach(polys[i]);
		}
		win.wait_for_button();
	}
	catch (const runtime_error &rte)
	{
		Text err_msg_start{ Point{ 150, 200 }, "Runtime_error: " };
		Text err_msg{ Point{ 250, 200 }, rte.what() };

		err_msg_start.set_color(Color::black);
		err_msg.set_color(Color::black);

		win.attach(err_msg_start);
		win.attach(err_msg);

		win.wait_for_button();
		return 1;
	}
	catch (const exception &e)
	{
		Text err_msg_start{ Point{ 150, 200 }, "Exception: " };
		Text err_msg{ Point{ 250, 200 }, e.what() };

		err_msg_start.set_color(Color::black);
		err_msg.set_color(Color::black);

		win.attach(err_msg_start);
		win.attach(err_msg);

		win.wait_for_button();
		return 2;
	}
	catch (...)
	{
		Text err_msg{ Point{ 150, 200 }, "An unknown exception occurred." };

		err_msg.set_color(Color::black);

		win.attach(err_msg);

		return 3;
	}
}


Edit: I took out the abs from the x-axis value.
Last edited on Mar 27, 2017 at 12:12pm
Mar 27, 2017 at 12:26pm
I am not sure about your Graph_lib::Polygon but on my Win32 app the polygon needs to be closed, i.e. first point must be == last point.
It looks then like this: http://pasteboard.co/Osgl7J2La.jpg
Mar 27, 2017 at 1:58pm
Even if I manage to make the last point == the first (how do I even do that, though?), the polygon is still being drawn outside the window so I won't even see it.

Edit: Actually, I'll just try hard-coding the values for now. I'll see if I can find some way to programmatically get those same values later.

Edit: Making the first point == the last gives me the runtime error "two polygon points lie on the same line". So I guess I shouldn't do that.

Anyway, I hard-coded the polygon points for an equilateral triangle just now, and it looks like this: https://1drv.ms/i/s!As6LkLqTe7Ps7gT_zSp7STJzRaF-

Here's the code:
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
// Osman Zakir
// 3 / 22 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 12 Exercise 11
// File chapter12ex11.cpp
// Exercise Specifications:
/**
* Draw a series of regular polygons, one inside the other. The innermost
* should be an equilateral triangle, enclosed by a square, enclosed by a
* pentagon, etc. For the mathematically adept only: let all the points of
* each N-polygon touch sides of the (N+1) -polygon. Hint: The trigonometric
* functions are found in <cmath> (§24.8, §B.9.2).
*/

#include "../../Simple_window.h"
#include "../../Graph.h"
#include <cmath>

int main()
{
	using namespace Graph_lib;

	Point top_left{ 100, 100 };
	constexpr int win_width = 600;
	constexpr int win_height = 400;
	Simple_window win{ top_left, win_width, win_height, "Polygons" };

	try
	{
		Graph_lib::Polygon poly;

		poly.add(Point{ 240, 230 });
		poly.add(Point{ 290, 130 });
		poly.add(Point{ 340, 230 });

		poly.set_color(Color::black);
		win.attach(poly);
		win.wait_for_button();
	}
	catch (const runtime_error &rte)
	{
		Text err_msg_start{ Point{ 150, 200 }, "Runtime_error: " };
		Text err_msg{ Point{ 250, 200 }, rte.what() };

		err_msg_start.set_color(Color::black);
		err_msg.set_color(Color::black);

		win.attach(err_msg_start);
		win.attach(err_msg);

		win.wait_for_button();
		return 1;
	}
	catch (const exception &e)
	{
		Text err_msg_start{ Point{ 150, 200 }, "Exception: " };
		Text err_msg{ Point{ 250, 200 }, e.what() };

		err_msg_start.set_color(Color::black);
		err_msg.set_color(Color::black);

		win.attach(err_msg_start);
		win.attach(err_msg);

		win.wait_for_button();
		return 2;
	}
	catch (...)
	{
		Text err_msg{ Point{ 150, 200 }, "An unknown exception occurred." };

		err_msg.set_color(Color::black);

		win.attach(err_msg);

		return 3;
	}
}


Another thing I need to ask about: is there a way to get libs for FLTK targeting x64 platforms that don't use Xlibs? I found on Stack Overflow that Visual Studio doesn't support Xlibs. When I try to build a project in Visual Studio using FLTK x64 libs, I get linker errors about Xlibs not being found.

Edit: Okay, I made a square just now. I'll show the code later in another post if possible, but for now, here's a screenshot: https://1drv.ms/i/s!As6LkLqTe7Ps7gVPLr54VTFKkusS
Last edited on Mar 27, 2017 at 4:24pm
Mar 27, 2017 at 6:37pm
I tried to do it programmatically again, but it's not working. Trying to do just the triangle for now, though.

Code:
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
// Osman Zakir
// 3 / 22 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 12 Exercise 11
// File chapter12ex11.cpp
// Exercise Specifications:
/**
* Draw a series of regular polygons, one inside the other. The innermost
* should be an equilateral triangle, enclosed by a square, enclosed by a
* pentagon, etc. For the mathematically adept only: let all the points of
* each N-polygon touch sides of the (N+1) -polygon. Hint: The trigonometric
* functions are found in <cmath> (§24.8, §B.9.2).
*/

#include "../../Simple_window.h"
#include "../../Graph.h"
#include <cmath>

int main()
{
	using namespace Graph_lib;

	Point top_left{ 100, 100 };
	constexpr int win_width = 600;
	constexpr int win_height = 400;
	Simple_window win{ top_left, win_width, win_height, "Polygons" };

	try
	{
		constexpr double pi = 3.14159265359;
		constexpr int revolution = 360;
		constexpr int radius = 100;
		int sides = 3;
		Graph_lib::Polygon tri;
		for (int deg = 0; deg < revolution; deg += (revolution / sides))
		{
			Point pt
			{
				int(radius * cos(deg * pi / 180) + (win_width / 2.0)),
				int(radius * sin(deg * pi / 180) - (win_height / 2.0))
			};
			tri.add(pt);
			tri.set_color(Color::black);
		}
		win.attach(tri);
		win.wait_for_button();
	}
	catch (const runtime_error &rte)
	{
		Text err_msg_start{ Point{ 150, 200 }, "Runtime_error: " };
		Text err_msg{ Point{ 250, 200 }, rte.what() };

		err_msg_start.set_color(Color::black);
		err_msg.set_color(Color::black);

		win.attach(err_msg_start);
		win.attach(err_msg);

		win.wait_for_button();
		return 1;
	}
	catch (const exception &e)
	{
		Text err_msg_start{ Point{ 150, 200 }, "Exception: " };
		Text err_msg{ Point{ 250, 200 }, e.what() };

		err_msg_start.set_color(Color::black);
		err_msg.set_color(Color::black);

		win.attach(err_msg_start);
		win.attach(err_msg);

		win.wait_for_button();
		return 2;
	}
	catch (...)
	{
		Text err_msg{ Point{ 150, 200 }, "An unknown exception occurred." };

		err_msg.set_color(Color::black);

		win.attach(err_msg);

		return 3;
	}
}


All I get is a blank window.
Mar 27, 2017 at 7:57pm
Your y points are negative. If you use
1
2
3
4
5
POINT pt
{
   int(radius * cos(deg * pi / 180) + (win_width / 2.0)),
   abs(int(radius * sin(deg * pi / 180) - (win_height / 2.0)))
};

you should see sth. like this: http://pasteboard.co/vmhbA5Yi.jpg
Pages: 12