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