Introduction to Computer Graphics and Java Programming for Artists


School of the Museum of Fine Arts ::: Continuing Education

George Aroush, instructor


Lecture Five -- Array Variables; 2D Shapes & Transformations


 

Readings

  1. The handouts named:
  2. Sample Programs in Batch Five:
  3. "Java How to Program" by Paul J. Deitel, and Harvey M. Deitel

 

Exercises

    Do before our next lecture

This exercise will assist you in creating a closed-curve or outline form, storing it in arrays, displaying it, and transforming it.

  1. CREATE FORM:
    1. on a graph paper, draw an outline form (not too detailed!) draw without lifting the pencil from the paper;
    2. select key points on the drawing -- not too many and not too few. Make sure you can approximate curves with short line segments;
    3. write down the x & y coordinates for each point, in drawing order.
  2. DISPLAY FORM:
    1. enter the x & y coordinates into arrays in a Java program (see: ArrayTwo.java);
    2. get the program to draw it with drawPolygon().
  3. TRANSFORM FORM:
    1. edit the first program so that the form is transformed -- through movement, scaling, reflection etc.;
    2. you can show the results as an animation or as multiple images -- you could try them overlapping, randomly scattered, or in a grid.

Back to the top of this page. Back to main Index

 

Time Delay and Randomness in Java

Putting Java to sleep

Java offers a way to temporally stop while it is running. This feature is needed in several areas in programming. In our case we need it to slow down a fast moving object on the screen. This in effect will allow us to better control the animation at hand. The method that allows us to do this is:

Thread.sleep(long millis);

Here, millis is a millisecond value which represents the duration of the delay. To delay for one second we use the value 1000. For a delay of half a second, we use the value of 500.

Unfortunately, due to the design of Java, sleep() can't just be used as is. The sleep() method is part of a class belonging to the Thread family. A simple way to think about thread is to see it as a min-executable program within an executable program. Just like Windows 95, Unix, Mac OS, etc. offer us multi-tasking - the ability of running multiple application at once - threads allow us to run multiple executables at once controlled by the main Applet instead of the OS.

Because of this, and because it's difficult to explain more about thread right now, we will simply accept the fact for now that to enable us to use the sleep() method we will have to create a method like this:

public void Delay(int delayTime)
{
    try
    {
        Thread.sleep(delayTime); /* call Java's sleep method */
    }
    catch (InterruptedException e)
    {
        /* when the sleep() call above is over, Java will */
        /* be interrupted and we fall into this block of code */
        /* because our intention is simply slow down things */
        /* wed do nothing in our exception code and just get out */
    }
}

Here, we created a method that we called Delay(). This method will call the sleep() method and which is a Java method that will put the applet into sleep mode for the duration of delayTime.

Randomizing Java

Java has a randomness method that allows completely unpredictable numbers to be generated (will almost unpredictable!) These numbers can be used to position objects, control their size, determine the speed of their movement or their colors as we will see soon; all this in randomness. The method that Java offers to do this is located under the Math class and we access it like this:

Math.random();

This method will return to us a random number between 0.0 and 1.0 inclusive. To better utilize this method we will write our own random number generator that utilizes Java's random() method to give us random numbers that we can easily utilize. Here is our own version of the random() method:

public int Random(int range)
{
    return ((int) (Math.random() * range));
}

Calling this method is very much like rolling one of a pair of dice, except that we can specify how many numbers we want on the dice; (i.e. the range.) To use our Random() method we call it like this:

x = Random(9);

This will cause x to be assigned a random number between 0 and 9 which the method Random() will return. One way to see this statement is to think that Random() will be replaced by a number between 0 and 9. Once that happens the statement above will read as if it was assuming Random() returned 3:

x = 3;

Proper use of randomness can add surprise to a program, create certain kinds of textures and rhythms, and even imitate the human creative process.


Back to the top of this page. Back to main Index

 

New Operator; The for Loop & Arrays

New Operators: +=, -=, *= & /=

The compound assignment operators may be informally understood by taking the expression:

a op= b

to be equivalent to:

a = a op b

with the provision that the expression a is evaluated only once. The operation indicated by the operator op is then applied to the two operand values. The resulting value is then stored into the left operand. For the operators += and -=, the two operands may each be of any arithmetic type. Examples:

x += i; <=> x = x + i;
x += 1; <=> x++;       <=> x = x + 1;

x -= j; <=> x = x - j;
x -= 1; <=> x--;       <=> x = x - 1;

x /= 2; <=> x = x / 2;

x *= 2; <=> x = x * 2;

An expression is a combination of operands and operators that yields a single value when evaluated. An expression may occur wherever a value is allowed. An operand is a constant or variable value manipulated by an operator in an expression. An operator specifies how the operands in an expression are to be evaluated. Java contains a full set of operators covering everything form basic arithmetic operations to logical and bitwise operations. Operators can be combined with assignment operator (=) to form a compound assignment operator. Operators in Java also produce a result that can be nested within a large expression. Java operators have two properties, precedence and associatively. Parentheses around expressions force Java to evaluate them in specific order.

The for Loop

This is essentially a streamlined version of the while loop. Every loop has three sections to get it to work. The for statement lets us repeat a statement or compound statement a specified number of times. It consists of three expressions:

  • A loop-initialization expression (init-expr)
  • A conditional-expression (cond-expr) evaluated before each iteration
  • A loop-expression (loop-expr) executed at the end of each iteration of the loop

Each expression in the for statement can be any valid Java expression. The for statement operates in the following sequence:

  1. The init-expr is evaluated
  2. While the cond-expr evaluates to a true value, the statement is executed. When cond-expr becomes false, control passes to the statement following the body of the for loop.
  3. At the end of the loop, loop-expr is evaluated.

An example of the for statement is shown below:

int    i;

for (i = 0; i < 100; i++)
{
    x[i] = 0; /* zeros the elements of an array */
}

Here is a simple while loop that shows the three conditions:

int     c;
c = 0;           /* init-expr */
while (c < 100)  /* cond-expr */
{
    System.out.println(c);
    c = c + 1;   /* loop-expr */
}

The for loop condenses these three conditions in one set of parentheses:

for ( init-expr; cond-expr; loop-expr )
{
    . . .
    . . .
    . . .
    . . .
}

The while loop above would be written as the following for loop:

int     c;

for (c = 0; c < 100; c++)
{
    System.out.println(c);
}

Arrays

Arrays of variables are lists or sequences of memory locations which share the same name but have different indices (plural of index) or subscription. They are useful for describing more complex graphics objects such as outline figures or 3D objects, their shapes, positions, velocities, etc. An array variable might have a name such as X or Y (just like any other variable) followed by square brackets []:

int     x[];
int     y[];

x[0] would be the first element in the x array, x[1] would be the second element, x[2] the third, and so on. As usual in Java programming, we begin counting with 0. To create an array, declare it as:

int     x[] = new int[20];

This tells us that there will be an array of 20 elements ranging from x[0] to x[19] (note that there is NO x[20], the last element is x[19].) The array can be given values with a series of statements such as:

x[0] = 100;  /* 1st element */
x[1] = 110;  /* 2nd element */
x[2] = 90;   /* 3rd element */
. . .
. . .
x[19] = 205; /* 20th element -- the last element in the array */ 

This is shown in the demo program ArrayOne.java. An easier way to plug in values is shown in the demo program ArrayTwo.java. Here, the array is defined with all its elements when it is declared:

int     x[] = { 28, 45, 67, 89, 24 };

The values are listed inside curly braces, separated by commas. Notice that it is not necessary to put the number of elements inside the square brackets -- the Java compiler will count the elements inside the curly braces and make the array the correct size based on this count.

The number inside the brackets, called the subscript or the index, can be either a constant (a written out number, such as 1 or 32) or a variable (such as "point, i, count, X, etc.") Using variables inside the brackets makes it easy to treat the array as a single object. Changing the value of the index variable with a while loop allows a programmer to do the same thing to each member of the array: making movement, size change, etc., possible. A movement example can be seen in the demo program ArrayThree.java, and size change in the demo program ArrayFour.java.

A new Graphic method

To better utilize object drawing created using arrays we will need a new method provided by Java for drawing polygons. The new method is:

Java.Graphics.drawPolygon(int xPoints[], int yPoints[], int nPointsCount);

This method takes two arrays of x and y points and draws a polygon out of them. To draw a filled polygon, we use fillPolygon();


Back to the top of this page. Back to main Index.

 

Sample Programs -- Batch Five

ArrayOne.java

/*
 *  Program:    ArrayOne.java
 *  Purpose:    Array in Java
 *  Author:     George Aroush
 *  Date:       1/1/1998
 *  Change Log: None
 *
 *  Full description of Program:
 *      Demonstrtes array: uses cluster of dots to show use of arrays
 */

public class ArrayOne extends java.applet.Applet
{
    final int   NUM_PTS = 6;

    public void paint(java.awt.Graphics g)
    {
        int     x[] = new int[NUM_PTS];
        int     y[] = new int[NUM_PTS];
        int     point = 0;              /* this variable will "index" the arrays when */
                                        /* we plot the pixels stored in x[] and y[]. */
        
            /* These define a pentagonal cluster of five dots around a sixth, central dot */
        x[0] = 160;     /* First, we give values to x[] and y[]. 	*/
        y[0] = 98;      /* This is a tedious way to do this, so 	*/
                        /* don't try it with arrays with more than 	*/
        x[1] = 160;     /* 10 index values.  See 'array2.c' for a 	*/
        y[1] = 86;      /* better way to deal with larger arrays 	*/
        
        x[2] = 173;
        y[2] = 95;
        
        x[3] = 167;
        y[3] = 108;
        
        x[4] = 153;
        y[4] = 108;
        
        x[5] = 147;
        y[5] = 95;
        
        while (point < NUM_PTS)     /* plot points 0 through 5; NO x[6] & y[6] */
        {
            /* The variable "point" is plugged into the index position, so */
            /* we can use the same pixel() statement to plot all 6 points */
            g.drawLine(x[point], y[point], x[point], y[point]);

            point++;            /* point = point + 1 */
        }
    }
}

ArrayOne.htm

<html>
<head>
<title>ArrayOne</title>
</head>
<body>
    <hr>
    <applet code=ArrayOne width=640 height=480></applet>
    <hr>
</body>
</html>

ArrayTwo.java

/*
 *  Program:    ArrayTwo.java
 *  Purpose:    Array in Java
 *  Author:     George Aroush
 *  Date:       1/1/1998
 *  Change Log: None
 *
 *  Full description of Program:
 *      Demonstrtes array: uses cluster of dots to show use 
 *      of arrays with improved method of plugging values 
 *      into arrays.
 */

public class ArrayTwo extends java.applet.Applet
{
    final int   NUM_PTS = 6;

    public void paint(java.awt.Graphics g)
    {
        /* The values for ALL the x[]'s are listed after the declaration, enclosed in curly braces (),	*/
        /* separated by commas.  Note that it isn't necessary to say how many values are in the array:	*/
        /* the compiler will figure that out.  The declaration "int" has to be preceded by "static" to get	*/
        /* to get this to work, for reasons that will be explained later.					*/
        
        int     x[] = { 160, 160, 173, 167, 153, 147 };
        int     y[] = { 98,   86,   95,   108, 108, 95 };
        
        TheCluster(x, y, 6, g);    /* call our function */
    }

    /*
     *  void    TheCluster()
     *  
     *  Plots a cluster of points: x, y, pat are pointers to 
     *  arrays of integers; n is the number of points to plot.
     */
    public void TheCluster(int x[], int y[], int n, java.awt.Graphics g)
    {
        int     point = 0;
        
        while (point < n)   /* plot the 6 pooints */
        {
            g.drawLine(x[point], y[point], x[point], y[point]);
            point++;        /* notice the increment */
        }
    }
}

ArrayTwo.htm

<html>
<head>
<title>ArrayTwo</title>
</head>
<body>
    <hr>
    <applet code=ArrayTwo width=640 height=480></applet>
    <hr>
</body>
</html>

ArrayThree.java

/*
 *  Program:    ArrayThree.java
 *  Purpose:    Array in Java
 *  Author:     George Aroush
 *  Date:       1/1/1998
 *  Change Log: None
 *
 *  Full description of Program:
 *      Demonstrtes movement with arrays: plots 6 points 40 
 *      times, moving the cluster between plots 
 */

public class ArrayThree extends java.applet.Applet
{
    final int   ONE_SEC = 1000;
    final int   NUM_PTS = 6;
    final int   NUM_CLUST = 40;

    public void paint(java.awt.Graphics g)
    {
        int     x[] = { 160, 160, 173, 167, 153, 147 };
        int     y[] = { 98,   86,   95,   108, 108, 95 };
        int     pat[] = { 1, 2, 3, 4, 5, 6 };
        int     count = 0;
        
        while (count < NUM_CLUST)   /* plot 40 cliusters */
        {
            TheCluster(x, y, NUM_PTS, g);       /* plot one cluster */
            
            MoveCluster(x, y, NUM_PTS, 4, -2);  /* move the cluster */
            
            Delay(ONE_SEC);

            count++;
        }
    }
    
    
    /*
     *  void    TheCluster()
     *  
     *  Plots a cluster of points: x, y, pat are pointers to 
     *  arrays of integers; n is the number of points to plot.
     */
    public void TheCluster(int x[], int y[], int n, java.awt.Graphics g)
    {
        int     point = 0;
        
        while (point < n)   /* plot the 6 pooints */
        {
            g.drawLine(x[point], y[point], x[point], y[point]);
            point++;        /* notice the increment */
        }
    }
    
    
    /*
     *  void    MoveCluster()
     *
     *  Moves a cluster of dots by adding mx to each x in x 
     *  array  and my to each y in y array; all arguments 
     *  are integers.
     */
    public void MoveCluster(int x[], int y[], int n, int mx, int my)
    {
        int     point = 0;  /* reset "point" at start of move */
        
        while (point < n)       /* move the cluster */
        {
            x[point] += mx;         /* move mx horizontally */
            y[point] += my;         /* move my vertically */
            
            point++;
        }
    }
    
    
    /*
     *  void    Delay()
     *
     *  Simply pauses for some time
     */
    public void Delay(int delayTime)
    {
        try
        {
            Thread.sleep(delayTime);    /* call Java's sleep method */
        }
        catch (InterruptedException e)
        {
            /* when the sleep() call above is over, Java will */
            /* be interuppted and we fall into this block of code */
            /* because our intention is simply slow down things */
            /* wed do nothing in our exception code and just get out */
        }
    }
}

ArrayThree.htm

<html>
<head>
<title>ArrayThree</title>
</head>
<body>
    <hr>
    <applet code=ArrayThree width=640 height=480></applet>
    <hr>
</body>
</html>

ArrayFour.java

/*
 *  Program:    ArrayFour.java
 *  Purpose:    Scalling an objects
 *  Author:     George Aroush
 *  Date:       1/1/1998
 *  Change Log: None
 *
 *  Full description of Program:
 *      Scaling: changing the size of the cluster by 
 *      decreasing x and y to 90% -- notice that the cluster 
 *      moves to the left and up as well as getting smaller. 
 *      Makes a nice perspective effect.
 */

public class ArrayFour extends java.applet.Applet
{
    final int   ONE_SEC = 1000;
    final int   NUM_PTS = 6;
    final int   NUM_CLUST = 22;

    public void paint(java.awt.Graphics g)
    {
        int     x[] = { 160, 160, 173, 167, 153, 147 };
        int     y[] = { 98,   86, 95,  108, 108, 95 };
        int     count = 0;
        
        while (count < NUM_CLUST)   /* plot 22 cliusters */
        {
            TheCluster(x, y, NUM_PTS, g);       /* plot one cluster */
            
            MoveCluster(x, y, NUM_PTS, 4, -2);  /* move the cluster */
            ScaleCluster(x, y, NUM_PTS, 9, 10); /* scale the cluster */
            
            Delay(ONE_SEC / 2);

            count++;
        }
    }
    
    
    /*
     *  void    TheCluster()
     *  
     *  Plots a cluster of points: x, y, pat are pointers to 
     *  arrays of integers; n is the number of points to plot.
     */
    public void TheCluster(int x[], int y[], int n, java.awt.Graphics g)
    {
        int     point = 0;
        
        while (point < n)   /* plot the 6 pooints */
        {
            g.drawLine(x[point], y[point], x[point], y[point]);
            point++;        /* notice the increment */
        }
    }
    
    
    /*
     *  void    MoveCluster()
     *
     *  Moves a cluster of dots by adding mx to each x in x 
     *  array  and my to each y in y array; all arguments 
     *  are integers.
     */
    public void MoveCluster(int x[], int y[], int n, int mx, int my)
    {
        int     point = 0;  /* reset "point" at start of move */
        
        while (point < n)       /* move the cluster */
        {
            x[point] += mx;         /* move mx horizontally */
            y[point] += my;         /* move my vertically */
            
            point++;
        }
    }
    
    
    /*
     *  void	ScaleCluster()
     *
     *  Increases or decreases spatial size of cluster by a 
     *  fraction determined by num and denom; each x and y 
     *  in the two arrays is multiplied by numer and divided 
     *  by denom.
     */
    void    ScaleCluster(int x[], int y[], int size, int numer, int denom)
    {
        int	point = 0;
        
        while (point < size)    /* scale or resize the cluster */
        {
            /* each x & y is decreased by 90% when numer = 9 & denom = 10 */
            /* We have to multiply by "numer" and divide by "denom" because we */
            /* don't know how to use "floating point" or decimal numbers yet */
            x[point] = x[point] * numer / denom;
            y[point] = y[point] * numer / denom;
            
            point++;
        }
    }
    
    
    /*
     *  void    Delay()
     *
     *  Simply pauses for some time
     */
    public void Delay(int delayTime)
    {
        try
        {
            Thread.sleep(delayTime);    /* call Java's sleep method */
        }
        catch (InterruptedException e)
        {
            /* when the sleep() call above is over, Java will */
            /* be interuppted and we fall into this block of code */
            /* because our intention is simply slow down things */
            /* wed do nothing in our exception code and just get out */
        }
    }
}

ArrayFour.htm

<html>
<head>
<title>ArrayFour</title>
</head>
<body>
    <hr>
    <applet code=ArrayFour width=640 height=480></applet>
    <hr>
</body>
</html>

ArrayFive.java

/*
 *  Program:    ArrayFive.java
 *  Purpose:    Using for loop; drawPolygon() & random()
 *  Author:     George Aroush
 *  Date:       1/1/1998
 *  Change Log: None
 *
 *  Full description of Program:
 *      Mutation demo -- randomly displacing points in array 
 *      and demo of drawPolygon() method and demonstrates 
 *      "for ()" loop & the "+=" to move a shape on the 
 *      screen 
 */

public class ArrayFive extends java.applet.Applet
{
    final int   ONE_SEC = 1000;
    final int   HALF_SEC = ONE_SEC / 2;
    final int   NUM_PTS = 7;
    final int   NUM_MOVES = 20;
    
    public void paint(java.awt.Graphics g)
    {
        int     x[] = { 100, 110, 110, 150, 150, 100, 100 };
        int     y[] = { 50,  50,  110, 110, 130, 130, 50 };
        int     count = 0;

        g.drawPolygon(x, y, NUM_PTS);   /* draw polygon using x[] & y[] array for 7 vertices */
        Delay(ONE_SEC * 4);
        
        for (count = 0; count < NUM_MOVES; count++)		/* draw 20 times */
        {
            g.clearRect(0, 0, 640, 480);    /* clear screen before each display */
            
            g.drawPolygon(x, y, NUM_PTS);   /* draw polygon using x[] & y[] array for 7 vertices */
            
            Mutate(x, y, NUM_PTS, 7);
            
            Delay(HALF_SEC);
        }
    }
    
    
    /*
     *	void    Mutate()
     *
     *	Randomly moves each x and y in the two arrays by a random integer between 0 and range
     */
    public void Mutate(int x[], int y[], int n, int range)
    {
        int     p;  /* indexes the arrays */
        
        for (p = 0; p < n; p++)     /* mutate the locations of the 7 vertices */
        {	
            x[p] += Random(range);      /* each x[] moves from 0 to range pixel, right */
            y[p] += Random(range);      /* each y[] moves from 0 to range pixels, down */
        }
        
        x[n-1] = x[0];      /* make sure the last vertex is the same as	*/
        y[n-1] = y[0];      /* the first, so the outline will be closed */
    }
    
    
    /*
     *  int     Rand()
     *
     *  Generate a random number between 0 to range - 1
     */
    public int Random(int range)
    {
        return ((int) (Math.random() * range));
    }
    
    
    /*
     *  void    Delay()
     *
     *  Simply pauses for some time
     */
    public void Delay(int delayTime)
    {
        try
        {
            Thread.sleep(delayTime);    /* call Java's sleep method */
        }
        catch (InterruptedException e)
        {
            /* when the sleep() call above is over, Java will */
            /* be interuppted and we fall into this block of code */
            /* because our intention is simply slow down things */
            /* wed do nothing in our exception code and just get out */
        }
    }
}

ArrayFive.htm

<html>
<head>
<title>ArrayFive</title>
</head>
<body>
    <hr>
    <applet code=ArrayFive width=640 height=480></applet>
    <hr>
</body>
</html>

Back to the top of this page. Back to main Index.