package org.nzdl.gsdl.GsdlCollageApplet; public class MyAffineTransform { public double scaleX = 0; public double scaleY = 0; public double translateX = 0; public double translateY = 0; public boolean overlap = false; public MyAffineTransform (int image_x_dim, int image_y_dim) { random_set_pos(image_x_dim, image_y_dim); } /** The amount to adjust the size of an image so that it fits into the applet screen * @param image_x_dim the width of the image to scale * @param image_y_dim the height of the image to scale * @return a value by which to scale the image to ensure it will fit in the applet */ private double scaleFactor (int image_x_dim, int image_y_dim) { double scale_factor = 1.0; // three quarters of the application width & height int tol_app_x_dim = 3*DisplayImages.app_x_dim_/4; int tol_app_y_dim = 3*DisplayImages.app_y_dim_/4; // if the image is too big, calculate a fraction // by which to reduce the image if (image_x_dim>tol_app_x_dim) { scale_factor = image_x_dim/tol_app_x_dim + 1; } if (image_y_dim>tol_app_y_dim) { int y_scale_factor = image_y_dim/tol_app_y_dim + 1; // take the biggest of the two as the same fraction must // be applied to both the x and y values to keep the image // in proportion if (y_scale_factor>scale_factor) { scale_factor = y_scale_factor; } } return scale_factor; } /** Determines the placement of new images on the applet screen
* First the image is scaled, then the function loops until a satisfactory * image position is found. This is done by randomly selecting an x and y * co-ordinate for the image, then determining how much whitespace will be * covered if the image were to be placed at this position in the collage. * The standards for loop termination are as follows:
* 1. On any occasion a whitespace coverage of greater than 70% will result * in the loop being terminated.
* 2. After three times through the loop, a whitespace coverage of 50% will * also allow the loop to terminate (a less stringent condition).
* 3. After seven times through, the loop will terminate and the best * position will be used by default.
* This function also updates the used space array after image position has been selected. * * @param image_x_dim the width of the image * @param image_y_dim the height of the image * @return a transform operation by which to move the image from the origin */ protected void random_set_pos(int image_x_dim, int image_y_dim) { double scale_factor = scaleFactor(image_x_dim, image_y_dim); // scale the image (will be 1 and therefore no change as a default) image_x_dim/=scale_factor; image_y_dim/=scale_factor; // initialise variables required to determine image placement int image_x_pos = 0; int image_y_pos = 0; int best_x = 0; int best_y = 0; double best_clear = 0; double clear = 100; int stoploop = 0; do { // increment the loop counter stoploop++; // the number of positions that the image could occupy on the x axis int safe_x_dim = DisplayImages.app_x_dim_ - image_x_dim; double rx = Math.random(); // randomly pick an x co-ordinate for the image image_x_pos= ((int)(rx*safe_x_dim)); // same process as for the x co-ordinate // ensuring the y co-ordinate will fit on the screen int safe_y_dim = DisplayImages.app_y_dim_ - image_y_dim; double ry = Math.random(); // randomly pick a y co-ordinate for the image image_y_pos= ((int)(ry*safe_y_dim)); double whitespace = 0; double space = 0; // determine how much whitespace the image will cover if placed in the // current position and how much overlap will occur for (int n = image_x_pos; n < (image_x_pos + image_x_dim); n++) { for (int m = image_y_pos; m < (image_y_pos + image_y_dim); m++) { if (DisplayImages.used_space[n][m] == 0) whitespace++; space++; } } // divide the amount of whitespace covered by the amount of overlap clear = whitespace/space; // if this value is better than previous calculations, save these co-ordinates if (clear > best_clear) { best_x = image_x_pos; best_y = image_y_pos; best_clear = clear; } if ((image_x_dim > (DisplayImages.app_x_dim_ / 2)) || (image_y_dim > (DisplayImages.app_y_dim_ / 2))) break; } while ((clear < 0.70 || (stoploop > 3 && clear < 0.50)) && stoploop < 7); // if we only terminated because we went through so many times, // then we set the position to the best value possible if (stoploop == 7) { image_x_pos = best_x; image_y_pos = best_y; } // indicate that the space where the image is to be placed is now used for (int n = image_x_pos; n < (image_x_pos + image_x_dim); n++) for (int m = image_y_pos; m < (image_y_pos + image_y_dim); m++) { DisplayImages.used_space[n][m]++; if (DisplayImages.used_space[n][m] > DisplayImages.NO_IMAGES_OF_OVERLAP) overlap = true; } translateX = image_x_pos; translateY = image_y_pos; // scale the image appropriately scaleX = 1.0/scale_factor; scaleY = 1.0/scale_factor; return; } }