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