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;
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.