HirstDots.java
1    /* 
2     * A program to paint an abstract gradient in the vertical direction. 
3     */
4    
5    package npw;
6    
7    import painter.SPainter;
8    import shapes.SCircle;
9    
10   import javax.swing.*;
11   import java.awt.*;
12   import java.util.Random;
13   import java.util.Scanner;
14   
15   public class HirstDots {
16   
17       public static void main(String[] args) {
18           SwingUtilities.invokeLater(HirstDots::new);
19       }
20   
21       public HirstDots() {
22           paintTheImage();
23       }
24   
25       private void paintTheImage(){
26           // Grab the input information
27           int width = getNumber("width");
28           int height = getNumber("height");
29           int dotSpace = getNumber("horizontal space between dots");
30           // Establish the painter
31           SPainter painter = new SPainter("Hirst Dots", width, height);
32           SCircle dot = new SCircle(5);
33   
34           // Move the painter to the upper left corner to get ready to paint the gradient
35           painter.mfd(height/2.0);
36           painter.tl();
37           painter.mfd(width/2.0);
38           painter.tl();
39   
40           // Paint it!
41           paintGradient(painter, dot, height, width, dotSpace);
42       }
43   
44       private static int getNumber(String prompt) {
45           String nss = JOptionPane.showInputDialog(null,prompt+"?");
46           Scanner scanner = new Scanner(nss);
47           return scanner.nextInt();
48       }
49   
50       private void paintGradient(SPainter painter, SCircle dot, int height, int width, int dotSpace){
51           // Calculate the number of columns. We want to fill the screen, but don't want any columns half on the canvas.
52           // A column takes up the horizontal space of a dot's diameter plus the space between it and a neighbor.
53           double colWidth = dot.diameter() + dotSpace;
54           // We don't want a column all the way on the edge on the right side, so subtract 1.
55           int nrOfCols = (int) Math.floor(( width / colWidth )) - 1;
56   
57           int cols = 0;
58           while (cols < nrOfCols){
59               nextCol(painter, dot, dotSpace);
60               paintColumn(painter, dot, height, dotSpace);
61               cols = cols + 1;
62           }
63       }
64   
65       private void paintOneDot(SPainter painter, SCircle dot){
66           painter.setColor(randomColor());
67           painter.paint(dot);
68       }
69   
70       private Color randomColor() {
71           int rv = (int)(Math.random()*256);
72           int gv = (int)(Math.random()*256);
73           int bv = (int)(Math.random()*256);
74           return new Color(rv,gv,bv);
75       }
76   
77       // Dots are spaced more tightly together near the bottom of the canvas.
78       private void paintColumn(SPainter painter, SCircle dot, int height, int dotSpace) {
79           int totalDistanceTraveled = 0;
80   
81           // Paint a column with decreasing distance between dots.
82           while(totalDistanceTraveled < height - (dot.radius() * 3)) {
83               int travel = dotSpace;
84               totalDistanceTraveled = totalDistanceTraveled + travel;
85               painter.mfd(travel);
86               paintOneDot(painter, dot);
87           }
88   
89           // Make the method invariant with respect to painter position.
90           painter.mbk(totalDistanceTraveled);
91       }
92   
93       // Moves the painter to the next column.
94       private void nextCol(SPainter painter, SCircle dot, int dotSpace){
95           painter.tl();
96           painter.mfd(dot.diameter() + dotSpace);
97           painter.tr();
98       }
99   
100  }
101