July 29, 2013

The flag homework

We saw monkey1.C and monkey2.C on June 10, 2013.

#include <iostream>
#include <cstdlib>
#include <cmath>	//for sin, cos, atan2
using namespace std;

struct color {
	unsigned char red;	//can hold integers in range 0 to 255 inclusive
	unsigned char green;
	unsigned char blue;
};

int main()
{
	const size_t width = 700;
	const size_t height = width;
	color a[width][height];

	const int xmax = width / 2;	//Place origin at center.
	const int ymax = height / 2;

	const int xmin = xmax - width;
	const int ymin = ymax - height;

	const color bg  = {60, 250, 200};
	const color bg1 = {30, 175, 125};
	const color bg2 = {5, 100, 50};
	const color grid = {0, 230, 170};
	const color grid1 = {0, 150, 80};
	const color grid2 = {0, 20, 5};
	const color axis = {255, 155, 0};
	const color line  = {  255, 255, 255 };


	for (int x = xmin; x < xmax; ++x) {
		for (int y = ymin; y < ymax; ++y) {
			if (x == 0 || y == 0)  { a[x - xmin][y - ymin] = axis; }
			else {
				if ( (x-xmin) > (width/2) && (y-ymin) > (height/2) ) {
					if ((x - xmin) % 10 == 0 || (y - ymin) % 10 == 0)
						{ a[x - xmin][y - ymin] = grid;}
					else { a[x - xmin][y - ymin] = bg;}
				}
				else if ( (x-xmin) < (width/2) && (y-ymin) < (height/2) ) {
					if ((x - xmin) % 10 == 0 || (y - ymin) % 10 == 0)
						{ a[x - xmin][y - ymin] = grid2;}
					else { a[x - xmin][y - ymin] = bg2;}
				}
				else {
					if ((x - xmin) % 10 == 0 || (y - ymin) % 10 == 0)
						{ a[x - xmin][y - ymin] = grid1;}
					else { a[x - xmin][y - ymin] = bg1;}
				}
			}
		}}


	const int n = 3 * width;	//number of points to plot
	const double pi = atan(1)*4;

	for (int i = 0; i < n; ++i) {
		//The fraction i/n goes from 0 to almost 1,
		//so theta goes from 0 to almost 2 * pi radians.

		const double theta = 2 * pi * i / n;
		const double r = sin(6 * theta);	//flower with 3 petals

		const int x = static_cast<int>(r * cos(theta) * xmax);
		const int y = static_cast<int>(r * sin(theta) * ymax);

		if (xmin <= (x +3) && (x +3) < xmax && ymin <= (y + 3) && (y +3) < ymax) {
			for (int i = -3; i < 4; i++) {
				int thickx = x + i - xmin;
				for (int i = -3; i < 4; i++) {
					int thicky = y + i - ymin;
					a[thickx][thicky] = line;
				}
			}
		}
	}

	cout << "P3\n"		//magic number of Netpbm .ppm file
		<< width << " " << height << "\n"
		<< 255 << "\n";	//maximum color value; 0 is minimum

	for (int y = ymax - 1; y >= ymin; --y) {
		for (int x = xmin; x < xmax; ++x) {
			const color c = a[x - xmin][y - ymin];

			//Cast makes the unsigned chars print in decimal.
			cout
				<< static_cast<int>(c.red) << "\t"
				<< static_cast<int>(c.green) << "\t"
				<< static_cast<int>(c.blue) << "\n";
		}
	}

	return EXIT_SUCCESS;
}

I fixed one bug: the grid lines should be anchored to the axes, not to the edges of the image. Since the width of half the image (350 pixels) was a multiple of the grid interval (10 pixels), the bug didn’t appear. We were lucky.

#include <iostream>
#include <cstdlib>
#include <cmath>	//for sin, cos, atan2
#include <cassert>	//for assert
using namespace std;

struct color {
	unsigned char red;	//can hold integers in range 0 to 255 inclusive
	unsigned char green;
	unsigned char blue;
};

struct quadrant {
	color background;
	color grid;
};

const size_t width = 700;
const size_t height = width;

const int xmax = width / 2;	//Place origin at center.
const int ymax = height / 2;

const int xmin = xmax - width;
const int ymin = ymax - height;

//Return a reference to the pixel at offset (x, y) from the origin.

inline color& a(int x, int y) {
	static color arr[width][height];
	assert(xmin <= x && x < xmax && ymin <= y && y < ymax);
	return arr[y - ymin][x - xmin];
}

int main()
{
	//There are four quadrants.
	const quadrant q[2][2] = {
		//              left                             right
		{{{ 30, 175, 125}, {0, 150, 80}},   {{60, 250, 200}, {0, 230, 170}}},	//upper
		{{{  5, 100,  50}, {0,  20,  5}},   {{30, 175, 125}, {0, 150,  80}}}	//lower
	};

	const color axis = {255, 155,  10};	//X and Y axes
	const color line = {255, 255, 255};	//the curved line

	for (int y = ymin; y < ymax; ++y) {
		for (int x = xmin; x < xmax; ++x) {
			if (x == 0 || y == 0) {
				a(x, y) = axis;	//Draw the X and Y axes.
				continue;
			}

			//lower is true if (x, y) is in lower half of image,
			//false if (x, y) is in upper half of image.
			const bool lower = y < 0;
			const bool right = x > 0;

			if (x % 10 == 0 || y % 10 == 0) {
				a(x, y) = q[lower][right].grid;
			} else {
				a(x, y) = q[lower][right].background;
			}
		}
	}

	const int n = 3 * width;	//number of points to plot
	const double pi = 4 * atan(1.0);

	for (int i = 0; i < n; ++i) {
		//The fraction i/n goes from 0 to almost 1,
		//so theta goes from 0 to almost 2 * pi radians.

		const double theta = 2 * pi * i / n;
		const double r = sin(6 * theta);	//flower with 3 petals

		const int x = static_cast<int>(r * cos(theta) * xmax);
		const int y = static_cast<int>(r * sin(theta) * ymax);

		//Print a 7 by 7 square centered at pixel (x, y).
		for (int y1 = y - 3; y1 <= y + 3; ++y1) {
			for (int x1 = x - 3; x1 <= x + 3; ++x1) {
				if (xmin <= x1 && x1 < xmax
					&& ymin <= y1 && y1 < ymax) {
					a(x1, y1) = line;
				}
			}
		}
	}

	cout << "P3\n"		//magic number of Netpbm .ppm file
		<< width << " " << height << "\n"
		<< 255 << "\n";	//maximum color value; 0 is minimum

	for (int y = ymax - 1; y >= ymin; --y) {
		for (int x = xmin; x < xmax; ++x) {
			const color& c = a(x, y);

			//Cast makes the unsigned chars print in decimal.
			cout
				<< static_cast<int>(c.red)   << "\t"
				<< static_cast<int>(c.green) << "\t"
				<< static_cast<int>(c.blue)  << "\n";
		}
	}

	return EXIT_SUCCESS;
}

The curved line would be smoother if we printed a circle of radius 3, instead of a 7 × 7 square, centered at each pixel (x, y).

Create a class

Chapter 2, p. 177, asked you to be on the lookout for a set of variables used by a series of function calls. See the above variable arr used by each call to the function a. The variables floating alongside the function (width, height, xmax, etc.) could become static data members (pp. 238–239).

#ifndef CANVASH
#define CANVASH
#include <cstddef>	//for size_t
#include <cassert>	//for assert
using namespace std;

struct color {
	unsigned char red;	//can hold integers in range 0 to 255 inclusive
	unsigned char green;
	unsigned char blue;
};

class canvas {
	static const size_t width = 700;
	static const size_t height = width;
public:
	static const int xmax = width / 2;	//Place origin at center.
	static const int ymax = height / 2;

	static const int xmin = xmax - width;
	static const int ymin = ymax - height;
private:
	color arr[width][height];
public:
	//Return a reference to the pixel at offset (x, y) from the origin.
	color& a(int x, int y) {
		assert(xmin <= x && x < xmax && ymin <= y && y < ymax);
		return arr[y - ymin][x - xmin];
	}

	void print() const;
};

#endif
#include <iostream>
#include "canvas.h"
using namespace std;

void canvas::print() const
{
	cout << "P3\n"		//magic number of Netpbm .ppm file
		<< width << " " << height << "\n"
		<< 255 << "\n";	//maximum color value; 0 is minimum

        for (int y = ymax - 1; y >= ymin; --y) {
                for (int x = xmin; x < xmax; ++x) {
                        const color& c = arr[y - ymin][x - xmin];

                        //Cast makes the unsigned chars print in decimal.
                        cout
                                << static_cast<int>(c.red)   << "\t"
                                << static_cast<int>(c.green) << "\t"
                                << static_cast<int>(c.blue)  << "\n";
                }
        }
}
#include <iostream>
#include <cstdlib>
#include <cmath>	//for sin, cos, atan2
#include "canvas.h"
using namespace std;

struct quadrant {
	color background;
	color grid;
};

int main()
{
	canvas c;

	//There are four quadrants.
	const quadrant q[2][2] = {
		//              left                             right
		{{{ 30, 175, 125}, {0, 150, 80}},   {{60, 250, 200}, {0, 230, 170}}},	//upper
		{{{  5, 100,  50}, {0,  20,  5}},   {{30, 175, 125}, {0, 150,  80}}}	//lower
	};

	const color axis = {255, 155,  10};	//X and Y axes
	const color line = {255, 255, 255};	//the curved line

	for (int y = canvas::ymin; y < canvas::ymax; ++y) {
		for (int x = canvas::xmin; x < canvas::xmax; ++x) {
			if (x == 0 || y == 0) {
				c.a(x, y) = axis;	//Draw the X and Y axes.
				continue;
			}

			//lower is true if (x, y) is in lower half of image,
			//false if (x, y) is in upper half of image.
			const bool lower = y < 0;
			const bool right = x > 0;

			if (x % 10 == 0 || y % 10 == 0) {
				c.a(x, y) = q[lower][right].grid;
			} else {
				c.a(x, y) = q[lower][right].background;
			}
		}
	}

	//number of points to plot
	const int n = 3 * (canvas::xmax - canvas::xmin);
	const double pi = 4 * atan(1.0);

	for (int i = 0; i < n; ++i) {
		//The fraction i/n goes from 0 to almost 1,
		//so theta goes from 0 to almost 2 * pi radians.

		const double theta = 2 * pi * i / n;
		const double r = sin(6 * theta);	//flower with 3 petals

		const int x = static_cast<int>(r * cos(theta) * canvas::xmax);
		const int y = static_cast<int>(r * sin(theta) * canvas::ymax);

		//Print a 7 by 7 square centered at pixel (x, y).
		for (int y1 = y - 3; y1 <= y + 3; ++y1) {
			for (int x1 = x - 3; x1 <= x + 3; ++x1) {
				if (canvas::xmin <= x1 && x1 < canvas::xmax
					&& canvas::ymin <= y1 && y1 < canvas::ymax) {
					c.a(x1, y1) = line;
				}
			}
		}
	}

	c.print();
	return EXIT_SUCCESS;
}

Processing.