drawing a diagram from 12.6 [fltk]

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

Output:

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

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

using namespace Graph_lib;

Point operator+(Point& a, Point& b)
{
	return Point(a.x + b.x, a.y + b.y);
}

Point operator-(Point& a, Point& b)
{
	return Point(a.x - b.x, a.y - b.y);
}

//ARROW CLASS-----------------------------------------START

double pointVecMag(Point vec) {
	return sqrt(pow(vec.x, 2) + pow(vec.y, 2));;
}

struct MyArrow : public Shape
{
	MyArrow(Point start, Point end, bool s, bool e, int size, Fl_Color arrowColor)
		:start(start), end(end), s(s), e(e), size(size), aColor(arrowColor)
	{
		if (s) {
			//end-start vector: c
			c = Point(end.x - start.x, end.y - start.y);
			cMag = pointVecMag(c);
			cUnit = Point(c.x / cMag * size, c.y / cMag * size);
			cTrans = Point(cUnit.x, cUnit.y);

			//Arrow Head Start
			cPerp = Point(-cTrans.y, cTrans.x);
			arrowhead01 = Point(start.x + cPerp.x + cTrans.x, start.y + cPerp.y + cTrans.y);
			arrowhead02 = Point(start.x - cPerp.x + cTrans.x, start.y - cPerp.y + cTrans.y);
		}
		if (e) {
			//start-end vector: d
			d = Point(start.x - end.x, start.y - end.y);
			dMag = pointVecMag(d);
			dUnit = Point(d.x / dMag * size, d.y / dMag * size);
			dTrans = Point(dUnit.x, dUnit.y);

			//Arrow Head End
			dPerp = Point(-dTrans.y, dTrans.x);
			arrowhead03 = Point(end.x + dPerp.x + dTrans.x, end.y + dPerp.y + dTrans.y);
			arrowhead04 = Point(end.x - dPerp.x + dTrans.x, end.y - dPerp.y + dTrans.y);
		}
	};

	void draw_lines() const;

private:
	Fl_Color aColor;
	//Line
	Point start;
	Point end;

	//Arrowhead at start
	Point c;
	Point cUnit;
	Point cTrans;
	Point cPerp;
	double cMag;

	Point arrowhead01;
	Point arrowhead02;

	//Arrowhead at end
	Point d;
	Point dUnit;
	Point dTrans;
	Point dPerp;
	double dMag;

	Point arrowhead03;
	Point arrowhead04;

	bool s;
	bool e;
	int size;
};

void MyArrow::draw_lines() const {

	if (color().visibility()) {
		fl_color(aColor);
		//Line
		fl_line(start.x, start.y, end.x, end.y);
		//Arrowhead at start
		if (s) {
			fl_line(start.x, start.y, arrowhead01.x, arrowhead01.y);
			fl_line(start.x, start.y, arrowhead02.x, arrowhead02.y);
		}
		//Arrowhead at end
		if (e) {
			fl_line(end.x, end.y, arrowhead03.x, arrowhead03.y);
			fl_line(end.x, end.y, arrowhead04.x, arrowhead04.y);
		}
	}
}

//ARROW CLASS-----------------------------------------END

//BOX ROUNDED CORNERS CLASS---------------------------START

struct boxRoundCorners : public Shape
{
	boxRoundCorners(Fl_Color boxColor, Point origin, int width, int height, int radius, Fl_Color textColor, string s)
	:
		bc(boxColor),		// box color
		o(origin),			// box origin
		w(width),			// box width
		h(height),			// box height
		r(radius),			// box corner radius
		tc(textColor),		// text color
		label(s)			// text
	{
		// defining points for box
		a1 = Point(o.x + r, o.y);
		a2 = Point(o.x, o.y + r);
		a3 = Point(o.x + r, o.y + r);
		
		b1 = Point(o.x + w - r, o.y);
		b2 = Point(o.x + w, o.y + r);
		b3 = Point(o.x + w - r, o.y + r);

		c1 = Point(o.x + w, o.y + h - r);
		c2 = Point(o.x + w - r, o.y + h);
		c3 = Point(o.x + w - r, o.y + h - r);

		d1 = Point(o.x + r, o.y + h);
		d2 = Point(o.x, o.y + h - r);
		d3 = Point(o.x + r, o.y + h - r);

		set_fill_color(Color::red);

		textPt = Point(o.x + r, o.y + h / 2 + r); // text point
		add(textPt);		// adding text point to shape
	};
		
	Point get_textPt() { return textPt; }
	Point get_north() { return Point(o.x + w / 2, o.y); }
	Point get_east() { return Point(o.x + w, o.y + h / 2); }
	Point get_south() { return Point(o.x + w / 2, o.y + h); }
	Point get_west() { return Point(o.x, o.y + h / 2); }

	int get_width() { return w; }
	int get_height() { return h; }

	void draw_lines() const {
		if (color().visibility()) {
			// DRAWING TEXT
			fl_color(tc);	// setting text color
			fl_draw(label.c_str(), point(0).x, point(0).y); // drawing text

			// DRAWING BOX
			fl_color(bc);	// setting box color

			/*
			// defining box lines
			fl_line(a1.x, a1.y, b1.x, b1.y);
			fl_line(b2.x, b2.y, c1.x, c1.y);
			fl_line(c2.x, c2.y, d1.x, d1.y);
			fl_line(d2.x, d2.y, a2.x, a2.y);
			// defining box arcs
			fl_arc(o.x, o.y, r + r, r + r, 90, 180);
			fl_arc(o.x + w - (r + r), o.y, r + r, r + r, 360, 90);
			fl_arc(o.x + w - (r + r), o.y + h - (r + r), r + r, r + r, 270, 360);
			fl_arc(o.x, o.y + h - (r + r), r + r, r + r, 180, 270);
			*/

			fl_begin_complex_polygon();
			fl_arc(o.x, o.y, r + r, r + r, 90, 180);
			fl_gap();
			fl_line(a1.x, a1.y, b1.x, b1.y);
			fl_gap();
			fl_arc(o.x + w - (r + r), o.y, r + r, r + r, 360, 90);
			fl_gap();
			fl_line(b2.x, b2.y, c1.x, c1.y);
			fl_gap();
			fl_arc(o.x + w - (r + r), o.y + h - (r + r), r + r, r + r, 270, 360);
			fl_gap();
			fl_line(c2.x, c2.y, d1.x, d1.y);
			fl_gap();
			fl_arc(o.x, o.y + h - (r + r), r + r, r + r, 180, 270);
			fl_gap();
			fl_line(d2.x, d2.y, a2.x, a2.y);
			fl_end_complex_polygon();
		}		
	}
	
private:
	// BOX
	Point o;
	Point a1, a2, b1, b2, c1, c2, d1, d2;
	Point a3, b3, c3, d3;
	Point north, east, south, west;	
	Fl_Color bc;
	int w, h, r;

	// LABEL
	Point textPt;
	string label; // label
	Fl_Color tc;	
};

//BOX ROUNDED CORNERS CLASS---------------------------END

int main()
try
{
	Point tl(100, 100);
	Simple_window win(tl, 600, 400, "Simple Window");

	Fl_Color boxColor = Color::black;
	Fl_Color textColor = Color::black;
	Fl_Color arrowColor = Color::black;
	
	boxRoundCorners box_Window(boxColor, Point(200, 100), 60, 20, 5, textColor, "Window");
	boxRoundCorners box_Line_style(boxColor, Point(300, 100), 80, 20, 5, textColor, "Line_style");
	boxRoundCorners box_Color(boxColor, Point(400, 100), 60, 20, 5, textColor, "Color");

	boxRoundCorners box_Simple_window(boxColor, Point(175, 200), 105, 20, 5, textColor, "Simple_window");
	boxRoundCorners box_Shape(boxColor, Point(310, 200), 60, 20, 5, textColor, "Shape");
	boxRoundCorners box_Point(boxColor, Point(400, 200), 60, 20, 5, textColor, "Point");

	boxRoundCorners box_Line(boxColor, Point(150, 300), 40, 20, 5, textColor, "Line");
	boxRoundCorners box_Lines(boxColor, Point(200, 300), 40, 20, 5, textColor, "Lines");
	boxRoundCorners box_Polygon(boxColor, Point(250, 300), 60, 20, 5, textColor, "Polygon");
	boxRoundCorners box_Axis(boxColor, Point(325, 300), 40, 20, 5, textColor, "Axis");
	boxRoundCorners box_Rectangle(boxColor, Point(375, 300), 70, 20, 5, textColor, "Rectangle");
	boxRoundCorners box_Text(boxColor, Point(450, 300), 40, 20, 5, textColor, "Text");
	boxRoundCorners box_Image(boxColor, Point(500, 300), 45, 20, 5, textColor, "Image");

	MyArrow arrow_Sw_W(box_Simple_window.get_north(), box_Window.get_south(), false, true, 5, arrowColor);
	MyArrow arrow_L_S(box_Line.get_north(), Point(box_Shape.get_south().x - box_Shape.get_width() / 2, box_Shape.get_south().y), false, true, 5, arrowColor);
	MyArrow arrow_Ls_S(box_Lines.get_north(), Point(box_Shape.get_south().x - box_Shape.get_width() / 4, box_Shape.get_south().y), false, true, 5, arrowColor);
	MyArrow arrow_P_S(box_Polygon.get_north(), Point(box_Shape.get_south().x - box_Shape.get_width() / 6, box_Shape.get_south().y), false, true, 5, arrowColor);
	MyArrow arrow_A_S(box_Axis.get_north(), box_Shape.get_south(), false, true, 5, arrowColor);
	MyArrow arrow_R_S(box_Rectangle.get_north(), Point(box_Shape.get_south().x + box_Shape.get_width() / 6, box_Shape.get_south().y), false, true, 5, arrowColor);
	MyArrow arrow_T_S(box_Text.get_north(), Point(box_Shape.get_south().x + box_Shape.get_width() / 4, box_Shape.get_south().y), false, true, 5, arrowColor);
	MyArrow arrow_I_S(box_Image.get_north(), Point(box_Shape.get_south().x + box_Shape.get_width() / 2, box_Shape.get_south().y), false, true, 5, arrowColor);

	//ATTACH BOXES
	win.attach(box_Window);
	win.attach(box_Line_style);
	win.attach(box_Color);

	win.attach(box_Simple_window);
	win.attach(box_Shape);
	win.attach(box_Point);

	win.attach(box_Line);
	win.attach(box_Lines);
	win.attach(box_Polygon);
	win.attach(box_Axis);
	win.attach(box_Rectangle);
	win.attach(box_Text);
	win.attach(box_Image);

	//ATTACH ARROWS
	win.attach(arrow_Sw_W);
	win.attach(arrow_L_S);
	win.attach(arrow_Ls_S);
	win.attach(arrow_P_S);
	win.attach(arrow_A_S);
	win.attach(arrow_R_S);
	win.attach(arrow_T_S);
	win.attach(arrow_I_S);

	win.wait_for_button();
}
catch (exception& e) {
	cout << e.what() << endl;
	return 1;
}
catch (...) {
	cout << "Exiting" << endl;
	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.