Graphical user interface – Fast Light Toolkit [FLTK]

What is FLTK? As described on fltk.org:

“FLTK (pronounced “fulltick”) is a cross-platform C++ GUI toolkit for UNIX®/Linux® (X11), Microsoft® Windows®, and MacOS® X. FLTK provides modern GUI functionality without the bloat and supports 3D graphics via OpenGL® and its built-in GLUT emulation.
FLTK is designed to be small and modular enough to be statically linked, but works fine as a shared library. FLTK also includes an excellent UI builder called FLUID that can be used to create applications in minutes.”

Download FLTK here.

How to install FLTK under Visual Stduio 2017 Community
How to compile FLTK – [following the instruction of fltk.org] This approach apparently prevents cross-contamination. Instead of copying files and folders from fltk-1.3.4 to the Visual Studio Community 2017 folder structure, the include and library paths are propperly (I hope so!) added to the project.
How to compile FLTK – [following the instruction of Principles and Practice using C++]

FLTK Examples:
Chapter 12 – A Display Model [using FLTK]
Chapter 13 – Graphics Classes [using FLTK]
Chapter 14 – Graphics Class Design [using FLTK]
Chapter 15 – Graphing Functions and Data [using FLTK]
Chapter 16 – Graphical User Interface [using FLTK]

Average temperature data of Cambridge, England and Cambridge, Massachusetts graphing [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 15 Exercise 11
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 15 Exercise 11

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>

ostream& operator<<(ostream& out, Point& a) {
	out << "(" << a.x << "," << a.y << ")";
	return out;
}

// layout
constexpr int xmax = 600;
constexpr int ymax = 600;

constexpr int x_orig = xmax / 2;
constexpr int y_orig = ymax / 2;
Point orig(x_orig, y_orig);

constexpr int r_min = -10;
constexpr int r_max = 10;

constexpr int n_points = 400;

constexpr int x_scale = 2;
constexpr int y_scale = 2;

constexpr int xoffset = 100;
constexpr int yoffset = 100;

constexpr int xspace = 100;
constexpr int yspace = 100;

constexpr int xlength = xmax - xoffset - xspace;
constexpr int ylength = ymax - yoffset - yspace;


int main()
try
{
	Point tl(100, 100);
	Simple_window win(tl, xmax, ymax, "Function graphs");

	// x axis
	Axis x(Axis::x, Point(xoffset, ymax - yoffset), xlength, 12,
		"month    Jan  Feb   Mar  Apr  May  Jun   Jul    Aug  Sep  Oct  Nov   Dec");
	x.set_color(Color::black);
	x.label.move(-100, 0);
	win.attach(x);

	// y axis
	Axis y(Axis::y, Point(yoffset, ymax - yoffset), ylength, 20, "temperature in 0 - 20 C");
	y.set_color(Color::black);
	win.attach(y);

	// data
	// Cambridge, England monthly normal weather 2016
	vector<double> camb_eng_temp = { 
		3.7,
		3.8,
		6.1,
		8.0,
		11.4,
		14.3,
		16.8,
		16.9,
		14.1,
		10.5,
		6.5,
		4.7
	};

	// Cambridge, Massachusetts monthly normal weather 2016
	vector<double> camb_mas_temp = {
		-1.9,
		-0.9,
		3.7,
		8.9,
		14.6,
		19.8,
		23.1,
		22.2,
		18.2,
		12.7,
		7.4,
		0.9
	};

	// graph
	Open_polyline cet; // Cambridge, England
	Open_polyline cmt; // Cambridge, Massachusetts

	for (int i = 0; i < 12; i++) {
		cet.add(Point(xoffset + i * (xlength / 12), (yspace + ylength) - camb_eng_temp[i] * 20));
		cmt.add(Point(xoffset + i * (xlength / 12), (yspace + ylength) - camb_mas_temp[i] * 20));
	}

	cet.set_color(Color::red);
	win.attach(cet);

	cmt.set_color(Color::blue);
	win.attach(cmt);

	win.wait_for_button();
	keep_window_open();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

labeled points data graphing [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 15 Exercise 10
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 15 Exercise 10

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>

ostream& operator<<(ostream& out, Point& a) {
	out << "(" << a.x << "," << a.y << ")";
	return out;
}

// layout
constexpr int xmax = 600;
constexpr int ymax = 600;

constexpr int x_orig = xmax / 2;
constexpr int y_orig = ymax / 2;
Point orig(x_orig, y_orig);

constexpr int r_min = -10;
constexpr int r_max = 10;

constexpr int n_points = 400;

constexpr int x_scale = 2;
constexpr int y_scale = 2;

constexpr int xoffset = 100;
constexpr int yoffset = 100;

constexpr int xspace = 100;
constexpr int yspace = 100;

constexpr int xlength = xmax - xoffset - xspace;
constexpr int ylength = ymax - yoffset - yspace;

class bar_graph : public Shape
{
public:
	bar_graph(Point origin, vector<Point>& data, int x_scale, int r1_min, int r1_max, int y_scale, int r2_min, int r2_max, Color col, string label);

	void draw_lines() const;

	vector<Point>& get_data() { return data; }

private:
	Point origin;
	vector<Point>& data;

	int x_scale;
	int r1_min;
	int r1_max;

	int y_scale;
	int r2_min;
	int r2_max;

	int bar_width;

	Color col;
	string label;
};

bar_graph::bar_graph(Point origin, vector<Point>& data, int x_scale, int r1_min, int r1_max, int y_scale, int r2_min, int r2_max, Color col, string label)
	: origin(origin),
	data(data),
	x_scale(x_scale),
	r1_min(r1_min),
	r1_max(r1_max),
	y_scale(y_scale),
	r2_min(r2_min),
	r2_max(r2_max),
	bar_width(bar_width),
	col(col),
	label(label)
{

}

void bar_graph::draw_lines() const
{
	int ds = data.size();
	cout << ds << endl;


	for (int i = 0; i < data.size(); i++) {

		int h = data[i].x;
		int c = data[i].y;

		// scale factor
		double sx = (xlength / 2.0) / (r1_max - r1_min);
		double sy = (ylength / 2.0) / (r2_max - r2_min);

		// draw point
		Point p(origin.x + (h - r1_min) * sx, origin.y - (c - r2_min) * sy);
		cout << p << endl;

		Graph_lib::Circle crcl(p, 3);
		crcl.set_color(col);
		crcl.set_fill_color(col);
		crcl.draw();

		// draw label
		string point_label = "(" + to_string(data[i].x) + "," + to_string(data[i].y) + ")";
		Text l(p, point_label);
		l.set_color(Color::red);

		l.draw();

	}

	// graph label
	Text gl(Point(origin.x - 90, origin.y + 15), label);
	gl.set_color(col);

	gl.draw();
}

int main()
try
{
	Point tl(100, 100);
	Simple_window win(tl, xmax, ymax, "Function graphs.");

	int r1_min = 170;
	int r1_max = 180;

	int r2_min = 7;
	int r2_max = 23;

	// notch label x
	string x_notch = "1 == " + to_string((r1_max - r1_min) / 10);

	// notch label y
	ostringstream strs;
	strs << setprecision(2) << (r2_max - r2_min) / 10.0;
	string y_notch = "1 == " + strs.str();

	// x axis
	Axis x(Axis::x, Point(orig.x - 200, orig.y), 400, 20, x_notch);
	x.set_color(Color::black);
	win.attach(x);

	// y axis
	Axis y(Axis::y, Point(orig.x, orig.y + 200), 400, 20, y_notch);
	y.set_color(Color::black);
	win.attach(y);

	// people height data
	vector<Point> d = {
		Point(170, 7),
		Point(175, 9),
		Point(180, 23),
		Point(173, 8),
		Point(178, 20),
		Point(177, 15),
		Point(171, 10),
		Point(174, 19)
	};

	// bar graph
	bar_graph bg(orig, d, x_scale, r1_min, r1_max, y_scale, r2_min, r2_max, Color::blue, "labeled points");
	win.attach(bg);

	win.wait_for_button();
	keep_window_open();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

bar graph – group of people height data graphing [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 15 Exercise 8
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 15 Exercise 8

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>

ostream& operator<<(ostream& out, Point& a) {
	out << "(" << a.x << "," << a.y << ")";
	return out;
}

// layout
constexpr int xmax = 600;
constexpr int ymax = 600;

constexpr int x_orig = xmax / 2;
constexpr int y_orig = ymax / 2;
Point orig(x_orig, y_orig);

constexpr int r_min = -10;
constexpr int r_max = 10;

constexpr int n_points = 400;

constexpr int x_scale = 2;
constexpr int y_scale = 2;

constexpr int xoffset = 100;
constexpr int yoffset = 100;

constexpr int xspace = 100;
constexpr int yspace = 100;

constexpr int xlength = xmax - xoffset - xspace;
constexpr int ylength = ymax - yoffset - yspace;

struct ppl_height
{
	ppl_height(double height, int count)
		:height(height), count(count) {	}
	double height;
	int count;
};

void read_data(string location, vector<ppl_height>& v)
{
	ifstream ist(location);
	if (!ist) { error("no such file exists", location); }

	char comma;
	double height;
	int count;

	while (ist >> height >> comma >> count)
	{
		if (ist.eof()) {
			break;
		}
		v.push_back(ppl_height(height, count));
	}

}

class bar_graph : public Shape
{
public:
	bar_graph(Point origin, vector<ppl_height>& data, int x_scale, int r1_min, int r1_max, int y_scale, int r2_min, int r2_max, int bar_width, Color col, string label);

	void draw_lines() const;

	vector<ppl_height>& get_data() { return data; }

private:
	Point origin;
	vector<ppl_height>& data;

	int x_scale;
	int r1_min;
	int r1_max;

	int y_scale;
	int r2_min;
	int r2_max;

	int bar_width;

	Color col;
	string label;
};

bar_graph::bar_graph(Point origin, vector<ppl_height>& data, int x_scale, int r1_min, int r1_max, int y_scale, int r2_min, int r2_max, int bar_width, Color col, string label)
	:	origin(origin),
		data(data),
		x_scale(x_scale),
		r1_min(r1_min),
		r1_max(r1_max),
		y_scale(y_scale),
		r2_min(r2_min),
		r2_max(r2_max),
		bar_width(bar_width),
		col(col),
		label(label)
{

}

void bar_graph::draw_lines() const
{
	int ds = data.size();


	for (int i = 0; i < data.size(); i++) {

		double w = double(bar_width / 2);
		int h = data[i].height;
		int c = data[i].count;

		// scale factor
		double sx = (xlength / 2.0) / (r1_max - r1_min);
		double sy = (ylength / 2.0) / (r2_max - r2_min);
		
		Point p0(origin.x + (h - r1_min) * sx - w, origin.y - c * sy);
		Point p1(origin.x + (h - r1_min) * sx + w, origin.y);

		Graph_lib::Rectangle r(p0, p1);

		r.set_color(col);
		r.set_fill_color(col);

		r.draw();

		// bar labels
		string hl = to_string((int)data[i].height);
		Text height_label(Point(p1.x - bar_width, p1.y + 15), hl);
		height_label.set_color(col);
		height_label.draw();
		
		string cl = to_string((int)data[i].count);
		Text count_label(Point(p0.x, p0.y - 10), cl);
		count_label.set_color(col);
		count_label.draw();

	}

	// graph label
	Text gl(Point(origin.x - 70, origin.y + 15), label);
	gl.set_color(col);

	gl.draw();
}

int main()
try
{
	Point tl(100, 100);
	Simple_window win(tl, xmax, ymax, "Function graphs.");

	int r1_min = 160;
	int r1_max = 200;

	int r2_min = 5;
	int r2_max = 30;

	int bar_width = 15;
	
	// notch label x
	string x_notch = "1 == " + to_string((r1_max - r1_min) / 10);

	// notch label y
	ostringstream strs;
	strs << setprecision(2) << (r2_max - r2_min) / 10.0;
	string y_notch = "1 == " + strs.str();

	// x axis
	Axis x(Axis::x, Point(orig.x - 200, orig.y), 400, 20, x_notch);
	x.set_color(Color::black);
	win.attach(x);

	// y axis
	Axis y(Axis::y, Point(orig.x, orig.y + 200), 400, 20, y_notch);
	y.set_color(Color::black);
	win.attach(y);

	// people height data
	vector<ppl_height> d = {	ppl_height(170, 7),
								ppl_height(175, 9),
								ppl_height(180, 23),
								ppl_height(185, 17),
								ppl_height(190, 6),
								ppl_height(195, 1)
	};

	// stream data from file
	vector<ppl_height> dff;
	string location = "input/height_data.txt";
	read_data(location, dff);

	// bar graph
	bar_graph bg(orig, dff, x_scale, r1_min, r1_max, y_scale, r2_min, r2_max, bar_width, Color::blue, "bar graph");
	win.attach(bg);

	win.wait_for_button();
	keep_window_open();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

elaborated bar graph class [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 15 Exercise 7
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 15 Exercise 7

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>

ostream& operator<<(ostream& out, Point& a) {
	out << "(" << a.x << "," << a.y << ")";
	return out;
}

// layout
constexpr int xmax = 600;
constexpr int ymax = 600;

constexpr int x_orig = xmax / 2;
constexpr int y_orig = ymax / 2;
Point orig(x_orig, y_orig);

constexpr int r_min = -10;
constexpr int r_max = 10;

constexpr int n_points = 400;

constexpr int x_scale = 20;
constexpr int y_scale = 20;

constexpr int xoffset = 100;
constexpr int yoffset = 100;

constexpr int xspace = 100;
constexpr int yspace = 100;

constexpr int xlength = xmax - xoffset - xspace;
constexpr int ylength = ymax - yoffset - yspace;

// bar graph class

class bar_graph : public Shape
{
public:
	bar_graph(Point origin, vector<double> data, int bar_width, int gap_width, Color col, string label);

	void draw_lines() const;

	vector<double> get_data() { return data; }

private:
	Point origin;
	vector<double> data;

	int bar_width;
	int gap_width;

	Color col;

	string label;
};

bar_graph::bar_graph(Point origin, vector<double> data, int bar_width, int gap_width, Color col, string label)
	: origin(origin), data(data), bar_width(bar_width), gap_width(gap_width), col(col), label(label)
{

}

void bar_graph::draw_lines() const
{
	int ds = data.size();


	for (int i = 0; i < data.size(); i++) {
		Point p0(origin.x + i * (bar_width + gap_width), origin.y);
		Point p1(origin.x + i * (bar_width + gap_width) + bar_width, origin.y);
		Point p2(origin.x + i * (bar_width + gap_width) + bar_width, origin.y - data[i]);
		Point p3(origin.x + i * (bar_width + gap_width), origin.y - data[i]);

		Closed_polyline cp;
		cp.add(p0);
		cp.add(p1);
		cp.add(p2);
		cp.add(p3);

		cp.set_color(col);
		cp.set_fill_color(col);

		cp.draw();

		// bar label
		ostringstream strs;
		strs << data[i];
		string d = strs.str();

		Text bl(Point(p3.x, p3.y - 5), d);
		bl.set_color(col);

		bl.draw();

	}

	// graph label
	Text gl(Point(origin.x, origin.y + 15), label);
	gl.set_color(col);

	gl.draw();

}

int main()
try
{
	Point tl(100, 100);
	Simple_window win(tl, xmax, ymax, "Function graphs.");

	Axis x(Axis::x, Point(orig.x - 200, orig.y), 400, 20, "1 == 20");
	x.set_color(Color::black);
	win.attach(x);

	Axis y(Axis::y, Point(orig.x, orig.y + 200), 400, 20, "1 == 20");
	y.set_color(Color::black);
	win.attach(y);

	vector<double> d = { 120, 123, 115, 110, 55 };

	bar_graph bg(orig, d, 10, 20, Color::blue, "bar graph");

	win.attach(bg);

	win.wait_for_button();
	keep_window_open();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

bar graph class [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 15 Exercise 6
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 15 Exercise 6

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>

ostream& operator<<(ostream& out, Point& a) {
	out << "(" << a.x << "," << a.y << ")";
	return out;
}

// layout
constexpr int xmax = 600;
constexpr int ymax = 600;

constexpr int x_orig = xmax / 2;
constexpr int y_orig = ymax / 2;
Point orig(x_orig, y_orig);

constexpr int r_min = -10;
constexpr int r_max = 10;

constexpr int n_points = 400;

constexpr int x_scale = 20;
constexpr int y_scale = 20;

constexpr int xoffset = 100;
constexpr int yoffset = 100;

constexpr int xspace = 100;
constexpr int yspace = 100;

constexpr int xlength = xmax - xoffset - xspace;
constexpr int ylength = ymax - yoffset - yspace;

// bar graph class

class bar_graph : public Shape
{
public:
	bar_graph(Point origin, vector<double> data, int bar_width, int gap_width, Color col);
		
	void draw_lines() const;

	vector<double> get_data() { return data; }

private:
	Point origin;
	vector<double> data;

	int bar_width;
	int gap_width;

	Color col;
};

bar_graph::bar_graph(Point origin, vector<double> data, int bar_width, int gap_width, Color col)
	: origin(origin), data(data), bar_width(bar_width), gap_width(gap_width), col(col)
{

}

void bar_graph::draw_lines() const
{
	int ds = data.size();

	
	for (int i = 0; i < data.size(); i++) {
		Point p0(origin.x + i * (bar_width + gap_width), origin.y);
		Point p1(origin.x + i * (bar_width + gap_width) + bar_width, origin.y);
		Point p2(origin.x + i * (bar_width + gap_width) + bar_width, origin.y - data[i]);
		Point p3(origin.x + i * (bar_width + gap_width), origin.y - data[i]);

		Closed_polyline cp;
		cp.add(p0);
		cp.add(p1);
		cp.add(p2);
		cp.add(p3);
		
		cp.set_color(col);
		cp.set_fill_color(col);

		cp.draw();
	}
	
}

int main()
try
{
	Point tl(100, 100);
	Simple_window win(tl, xmax, ymax, "Function graphs.");

	Axis x(Axis::x, Point(orig.x - 200, orig.y), 400, 20, "1 == 20");
	x.set_color(Color::black);
	win.attach(x);

	Axis y(Axis::y, Point(orig.x, orig.y + 200), 400, 20, "1 == 20");
	y.set_color(Color::black);
	win.attach(y);

	vector<double> d = { 120, 123, 115, 110, 55};
	
	bar_graph bg(orig, d, 10, 20, Color::red);

	win.attach(bg);

	win.wait_for_button();
	keep_window_open();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

animating leipniz’s series [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 15 Exercise 5
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 15 Exercise 5

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>

int fac_recursive(int n) { return n > 1 ? n * fac_recursive(n - 1) : 1; } // factorial n!

// layout
constexpr int xmax = 600;
constexpr int ymax = 600;

constexpr int x_orig = xmax / 2;
constexpr int y_orig = ymax / 2;
Point orig(x_orig, y_orig);

constexpr int r_min = -10;
constexpr int r_max = 10;

constexpr int n_points = 400;

constexpr int x_scale = 20;
constexpr int y_scale = 20;

constexpr int xoffset = 100;
constexpr int yoffset = 100;

constexpr int xspace = 100;
constexpr int yspace = 100;

constexpr int xlength = xmax - xoffset - xspace;
constexpr int ylength = ymax - yoffset - yspace;

// Leibniz Series graphing functions

/*
double exp0(double x) { return 1; }
double exp1(double x) { return 1 - 1/3 + 1/5; }
double exp2(double x) { return 1 - 1/3 + 1/5 - 1/7 + 1/9; }
*/

double expe(double n)
{
	double sum = 0;
	int denom = 1;
	int sign = 1;
	for (int i = 1; i <= n; i++)
	{
		sum += sign * 4.0 / denom;
		denom += 2;
		sign *= -1;
	}
	return sum;
}

int main()
try
{
	Point tl(100, 100);
	Simple_window win(tl, xmax, ymax, "Function graphs.");

	Axis x(Axis::x, Point(orig.x - 200, orig.y), 400, 20, "1 == 20");
	x.set_color(Color::black);
	win.attach(x);

	Axis y(Axis::y, Point(orig.x, orig.y + 200), 400, 20, "1 == 20");
	y.set_color(Color::black);
	win.attach(y);

	Function real_exp(exp, r_min, r_max, orig, 200, x_scale, y_scale);
	real_exp.set_color(Color::blue);

	Open_polyline poly;
	poly.add(orig);
	win.attach(poly);

	
	for (int n = 1; n < 50; ++n)
	{
		ostringstream ss;
		ss << "exp approximation, n == " << n;
		win.set_label(ss.str());
		//get next approximation:
		Function e(expe, r_min, r_max, orig, n, x_scale, y_scale);
		e.set_color(Color::red);
		win.attach(e);
		win.wait_for_button();
		win.detach(e);
	}
	
	keep_window_open();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

animating an exponential function approximation [fltk]

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 15 – 15.5
Using GUI library called FLTK (Fast Light Tool Kit, “full tick”).

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 15 15.5

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>

int fac_recursive(int n) { return n > 1 ? n * fac_recursive(n - 1) : 1; } // factorial n!

// layout
constexpr int xmax = 600;
constexpr int ymax = 600;

constexpr int x_orig = xmax / 2;
constexpr int y_orig = ymax / 2;
Point orig(x_orig, y_orig);

constexpr int r_min = -10;
constexpr int r_max = 10;

constexpr int n_points = 400;

constexpr int x_scale = 20;
constexpr int y_scale = 20;

constexpr int xoffset = 100;
constexpr int yoffset = 100;

constexpr int xspace = 100;
constexpr int yspace = 100;

constexpr int xlength = xmax - xoffset - xspace;
constexpr int ylength = ymax - yoffset - yspace;

// graphing functions

/*
double exp0(double x) { return 0; }
double exp1(double x) { return 1; }
double exp2(double x) { return 1 + x; }
double exp3(double x) { return 1 + x + pow(x, 2) / fac_recursive(2); }
double exp4(double x) { return 1 + x + pow(x, 2) / fac_recursive(2) + pow(x,3) / fac_recursive(3); }
double exp5(double x) { return 1 + x + pow(x, 2) / fac_recursive(2) + pow(x, 3) / fac_recursive(3) + pow(x, 4) / fac_recursive(4); }
*/

double term(double x, int n) { return pow(x, n) / fac_recursive(n); }

double expe(double x, int n)
{
	double sum = 0;
	for (int i = 0; i < n; ++i) { sum += term(x, i); }
	return sum;
}

int expN_number_of_terms = 10;

double expN(double x)
{
	return expe(x, expN_number_of_terms);
}

int main()
try
{
	Point tl(100, 100);
	Simple_window win(tl, xmax, ymax, "Function graphs.");

	Axis x(Axis::x, Point(orig.x - 200, orig.y), 400, 20, "1 == 20");
	x.set_color(Color::black);
	win.attach(x);

	Axis y(Axis::y, Point(orig.x, orig.y + 200), 400, 20, "1 == 20");
	y.set_color(Color::black);
	win.attach(y);

	Function real_exp(exp, r_min, r_max, orig, 200, x_scale, y_scale);
	real_exp.set_color(Color::blue);

	for (int n = 0; n < 50; ++n)
	{
		ostringstream ss;
		ss << "exp approximation, n == " << n;
		win.set_label(ss.str());
		//get next approximation:
		expN_number_of_terms = n;
		Function e(expN, r_min, r_max, orig, 200, x_scale, y_scale);
		e.set_color(Color::red);
		win.attach(e);
		win.wait_for_button();
		win.detach(e);
	}
	keep_window_open();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

graphing sine, cosine, their sum and the sum of their squares

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 15 Exercise 4

Output:

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 15 Exercise 4

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>


// layout
constexpr int xmax = 600;
constexpr int ymax = 600;

constexpr int x_orig = xmax / 2;
constexpr int y_orig = ymax / 2;
Point orig(x_orig, y_orig);

constexpr int r_min = -10;
constexpr int r_max = 10;

constexpr int n_points = 400;

constexpr int x_scale = 20;
constexpr int y_scale = 20;

constexpr int xoffset = 100;
constexpr int yoffset = 100;

constexpr int xspace = 100;
constexpr int yspace = 100;

constexpr int xlength = xmax - xoffset - xspace;
constexpr int ylength = ymax - yoffset - yspace;

// graphing functions
typedef double Fct(double);

double one(double x) { return 1; }
double slope(double x) { return x / 2; }
double square(double x) { return x * x; }
double sloping_sin(double x) { return sin(x) + slope(x); }
double sloping_cos(double x) { return cos(x) + slope(x); }
double sum_sin_cos(double x) { return sin(x) + cos(x); }
double sum_sin_cos_sq(double x) { return sin(x) * sin(x) + cos(x) * cos(x); }

template <class T> class myFct : public Shape {
public:
	myFct(Fct* f, double r1, double r2, Point orig, int count = 100, double xscale = 25, double yscale = 25, T precision = 1.0);
	~myFct() {}

	void set_f(Fct* p) { f = p; }
	void set_r1(double r) { r1 = r; }
	void set_r2(double r) { r2 = r; }
	void set_orig(Point o) { orig = o; }
	void set_count(int c) { count = c; }
	void set_xscale(double x) { xscale = x; }
	void set_yscale(double y) { yscale = y; }
	void set_precision(T p) { precision = p; }

	double get_r1() { return r1; }
	double get_r2() { return r2; }
	Point get_orig() { return orig; }
	int get_count() { return count; }
	double get_xscale() { return xscale; }
	double get_yscale() { return yscale; }
	T get_precision() { return precision; }

	void calc();
	void reset(Fct* f, double r1, double r2, Point orig, int count = 100, double xscale = 25, double yscale = 25, T precision = 1.0);

private:
	Fct* f;
	double r1;
	double r2;
	Point orig;
	int count;
	double xscale;
	double yscale;
	T precision;
};

template <class T> myFct<T>::myFct(Fct* f, double r1, double r2, Point orig, int count, double xscale, double yscale, T precision)
	:f(f), r1(r1), r2(r2), orig(orig), count(count), xscale(xscale), yscale(yscale), precision(precision)
{
	calc();
}

template <class T> void myFct<T>::calc()
{
	if (r2 - r1 <= 0) error("bad graphing range");
	if (count <= 0) error("non-positive graphing count");
	double dist = (r2 - r1) / count;
	double r = r1;
	for (int i = 0; i < count; ++i) {		
		int x = orig.x + int(int(r * xscale) / precision) * precision;
		int y = orig.y - int(int(f(r) * yscale) / precision) * precision;
		add(Point(x, y));
		r += dist;
	}
}

template <class T> void myFct<T>::reset(Fct* f, double r1, double r2, Point orig, int count, double xscale, double yscale, T precision)
{
	set_f(f);
	set_r1(r1);
	set_r2(r2);
	set_orig(orig);
	set_count(count);
	set_xscale(xscale);
	set_yscale(yscale);
	set_precision(precision);
	calc();
}

int main()
try
{
	Point tl(100, 100);
	Simple_window win(tl, xmax, ymax, "Function graphs.");

	Axis x(Axis::x, Point(orig.x - 200, orig.y), 400, 20, "1 == 20");
	x.set_color(Color::black);
	win.attach(x);	

	Axis y(Axis::y, Point(orig.x, orig.y + 200), 400, 20, "1 == 20");
	y.set_color(Color::black);
	win.attach(y);

	myFct<double> sin_graph(sin, r_min, r_max, orig, n_points, x_scale, y_scale);
	sin_graph.set_color(Color::blue);
	Text sg_label(Point(xoffset, orig.y + 60), "sin(x)");
	sg_label.set_color(Color::blue);
	win.attach(sin_graph);
	win.attach(sg_label);

	myFct<double> cos_graph(cos, r_min, r_max, orig, n_points, x_scale, y_scale);
	cos_graph.set_color(Color::green);
	Text cg_label(Point(xoffset, orig.y + 80), "cos(x)");
	cg_label.set_color(Color::green);
	win.attach(cos_graph);
	win.attach(cg_label);
	
	myFct<double> sin_cos_graph(sum_sin_cos, r_min, r_max, orig, n_points, x_scale, y_scale);
	sin_cos_graph.set_color(Color::cyan);
	Text scg_label(Point(xoffset, orig.y + 100), "sin(x) + cos(x)");
	scg_label.set_color(Color::cyan);
	win.attach(sin_cos_graph);
	win.attach(scg_label);

	myFct<double> sin_cos_sq_graph(sum_sin_cos_sq, r_min, r_max, orig, n_points, x_scale, y_scale);
	sin_cos_sq_graph.set_color(Color::magenta);
	Text scsq_label(Point(xoffset, orig.y - 40), "sin(x) * sin(x) + cos(x) * cos(x)");
	scsq_label.set_color(Color::magenta);
	win.attach(sin_cos_sq_graph);
	win.attach(scsq_label);
	
	win.wait_for_button();	
	keep_window_open();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}

function class object with reset and precision parameter

Bjarne Stroustrup “Programming Principles and Practice Using C++”
Chapter 15 Exercise 3

//  Philipp Siedler
//  Bjarne Stroustrup's PP
//  Chapter 15 Exercise 3

#define _USE_MATH_DEFINES
#include "Simple_window.h"
#include "Graph.h"
#include <cmath>

typedef double Fct(double);

double one(double x) { return 1; }
double slope(double x) { return x / 2; }
double square(double x) { return x * x; }
double sloping_cos(double x) { return cos(x) + slope(x); }
double sum_sin_cos(double x) { return sin(x) + cos(x); }
double sum_sin_cos_sq(double x) { return sin(x) * sin(x) + cos(x) * cos(x); }

template <class T> class myFct : Shape {
public:
	myFct(Fct* f, double r1, double r2, Point orig, int count = 100, double xscale = 25, double yscale = 25, T precision = 1.0);
	~myFct() {}

	void set_f(Fct* p) { f = p; }
	void set_r1(double r) { r1 = r; }
	void set_r2(double r) { r2 = r; }
	void set_orig(Point o) { orig = o; }
	void set_count(int c) { count = c; }
	void set_xscale(double x) { xscale = x; }
	void set_yscale(double y) { yscale = y; }
	void set_precision(T p) { precision = p; }

	double get_r1() { return r1; }
	double get_r2() { return r2; }
	Point get_orig() { return orig; }
	int get_count() { return count; }
	double get_xscale() { return xscale; }
	double get_yscale() { return yscale; }
	T get_precision() { return precision; }

	void calc();
	void reset(Fct* f, double r1, double r2, Point orig, int count = 100, double xscale = 25, double yscale = 25, T precision = 1.0);

private:
	Fct* f;
	double r1;
	double r2;
	Point orig;
	int count;
	double xscale;
	double yscale;
	T precision;
};

template <class T> myFct<T>::myFct(Fct* f, double r1, double r2, Point orig, int count, double xscale, double yscale, T precision)
	:f(f), r1(r1), r2(r2), orig(orig), count(count), xscale(xscale), yscale(yscale), precision(precision)
{
	calc();
}

template <class T> void myFct<T>::calc()
{
	if (r2 - r1 <= 0) error("bad graphing range");
	if (count <= 0) error("non-positive graphing count");
	double dist = (r2 - r1) / count;
	double r = r1;
	for (int i = 0; i < count; ++i) {
		cout << f(r) << endl;
		int x = orig.x + int(int(r * xscale) / precision) * precision;
		int y = orig.y - int(int(f(r) * yscale) / precision) * precision;
		add(Point(x, y));
		r += dist;
	}
}

template <class T> void myFct<T>::reset(Fct* f, double r1, double r2, Point orig, int count, double xscale, double yscale, T precision)
{
	set_f(f);
	set_r1(r1);
	set_r2(r2);
	set_orig(orig);
	set_count(count);
	set_xscale(xscale);
	set_yscale(yscale);
	set_precision(precision);
	calc();
}

int main()
try
{
	int min = 0;
	int max = 5;
	Point origin(0, 0);
	int count = 5;
	double xscale, yscale = 25;

	myFct<double> MF(one, min, max, origin, count, xscale, yscale, 2.0);
	cout << "---" << endl;
	MF.reset(slope, min, max, origin, count, xscale, yscale, 3.0);

	keep_window_open();
}
catch (exception& e) {
	cerr << "error: " << e.what() << '\n';
	keep_window_open();
	return 1;
}

catch (...) {
	cerr << "Unknown exception!\n";
	keep_window_open();
	return 2;
}
Output:
1
1
1
1
1
---
0
0.5
1
1.5
2
Please enter a character to exit