# include # include using namespace std; int main ( ) // // DRAGON.CPP reads the data in the image file DRAGON.PGM // and uses the Monte Carlo method to estimate the area and // centroid of the dragon. // // To run the program: // // g++ dragon.cpp // mv a.out dragon // ./a.out < dragon.pgm // // The file dragon.pgm is a legitimate PGM image and can be viewed // by many image programs, including the program "eog": // // eog dragon.pgm // // The data in the file is an array of integers between 0 and 255, // arranged in an array that is 475 pixels wide and 460 pixels high. // // The background (the "non-dragon") is white, which is stored as 255. // The dragon is in shades of gray, which are numbers below 255. // (0 is black, and low numbers are dark.) // // We assume each pixel is 1 square unit, so the total picture is // 475 x 460 square units in area = AREA_BOX = 218,500. // // We wish to estimate the area of the dragon, and its center of mass. // // The area can be estimated by sampling the picture N times, and // counting M, the number of times we actually sampled the dragon. // Then the dragon's area is estimated as AREA_DRAGON = AREA_BOX * ( M / N ). // // We can also estimate the center of mass, ( X_AVERAGE, Y_AVERAGE ) // by averaging the (X,Y) coordinates of every pixel corresponding to // a hit. // // To calculate the exact values, we would have to consider all // 218,500 pixels. However, in this example, by considering just 1,000 // pixels, we get good estimates of both the area and the center of mass. // { double area_box; double area_dragon; int c; char c1; char c2; int columns; int *dragon; int h; int height; int i; int m; int n; int random_int ( int a, int b ); double x_average; double y_average; // // Scramble the random number generator. // srand ( time ( 0 ) ); // // Read the first two characters, which are a special code "P2", // meaning this is an ASCII PGM image file. // cin >> c1; cin >> c2; // // The next two numbers are the number of columns and rows. // cin >> columns; cin >> height; // // Set aside enough space to store the data. // dragon = new int[columns*height]; // // Read the data in. // for ( h = 0; h < height; h++ ) { for ( c = 0; c < columns; c++ ) { cin >> dragon[c+h*columns]; } } // // Sample the data N times. // n = 1000; area_box = columns * height; m = 0; x_average = 0.0; y_average = 0.0; // // Pick a random column between 0 and COLUMNS-1, // and a random row between 0 and HEIGHT-1. // for ( i = 1; i <= n; i++ ) { c = random_int ( 0, columns - 1 ); h = random_int ( 0, height - 1 ); // // If the value of the image at that row and column is not 255 (white) // then we've hit the dragon. Update the counters. // if ( dragon[c+h*columns] != 255 ) { m = m + 1; x_average = x_average + c; y_average = y_average + h; } } // // Average the data. // area_dragon = area_box * ( double ) m / ( double ) n; x_average = x_average / ( double ) m; y_average = y_average / ( double ) m; cout << "\n"; cout << "Monte Carlo Estimate:\n"; cout << " Based on " << n << " sample pixels\n"; cout << " Box area = " << area_box << "\n"; cout << " Dragon area = " << area_dragon << "\n"; cout << " Dragon center = ( " << x_average << "," << y_average << ")\n"; // // Do an "exact" calculation by going over every pixel. // n = height * columns; area_box = columns * height; m = 0; x_average = 0.0; y_average = 0.0; for ( h = 0; h < height; h++ ) { for ( c = 0; c < columns; c++ ) { if ( dragon[c+h*columns] != 255 ) { m = m + 1; x_average = x_average + c; y_average = y_average + h; } } } area_dragon = area_box * ( double ) m / ( double ) n; x_average = x_average / ( double ) m; y_average = y_average / ( double ) m; cout << "\n"; cout << "Exact Result:\n"; cout << " Computed using all " << n << " pixels.\n"; cout << " Box area = " << area_box << "\n"; cout << " Dragon area = " << area_dragon << "\n"; cout << " Dragon center = ( " << x_average << "," << y_average << ")\n"; return 0; } int random_int ( int a, int b ) // RANDOM_INT returns a random int between a and b. // // Since it calls RAND(), you must "# include ". // { int range; int value; range = b - a + 1; value = a + rand ( ) % range; return value; }