// Strange pattern program import java.awt.*; import java.applet.*; import java.awt.event.*; import java.awt.image.*; // The Applet that does the work public class Roundrel extends Applet implements ActionListener , ColorChange, ValueChange { // variables for intitiating the drawing thread Drawer d; Thread cthread; // variables involved in communicating with the multiColorLevelPicker int numberOfControls = 12; Color[] levelColors = new Color [numberOfControls]; int[] values = new int [numberOfControls]; MultiColorLevelPicker mCLP; // the image to be drawn and its source from memory Image im; MemoryImageSource source; IndexColorModel icm; // the pixels of the drawing byte [] pixels; // canvas for drawing the image Canvas screen; // canvas for drawing the wave form Canvas waveCanvas; // variables controlling the image being drawn int nx, ny; // size of image being drawn currently int size = 9, size2 = 512, sym = 5; // overall character of image int tt = 1; // the "magnification factor" int piRange = 24; int basex = -1, basey = -1; // image shift int [] weight = new int[17]; // weight being applied to cosine components 0/1 int phase = 0; // static phase shift applied to component waves in degrees int repeats = 1; // extent of phase variation before return to normal int spread = 0; // magnitude of maximum variable phase shift double dPhase = 0.0; // radians version of phase shift double dSpread = 0.0; // radians version of phase spread // the double values of the drawing double [][] H = new double [512][512]; double hmin = -10, hmax= 10; // max and min values of last H calculated boolean fixMinMax = false; // controls whether to alter min and max bounds // wave sample double [] wave = new double [512]; // contour bounds double [] bound = new double [numberOfControls]; // need to initialise // overall controls Button calc = new Button ("CALC"), cont = new Button ("CONT"), recol = new Button ("COLR"), stopit = new Button ("STOP"), fix = new Button ("FLT"); TextField tSize = new TextField("9"), tSym = new TextField("05"), tXBase = new TextField("-1"), tYBase = new TextField("-1"), tPhase = new TextField("000"), tRepeats = new TextField("01"), tSpread = new TextField("000"), tPis = new TextField("024"); // Panel for controlling the weights Panel p ; Dimension D = new Dimension(); TextField [] W = new TextField [17]; // methods invoked by the MultiColorLevelPicker public void valueChangeAction(){ values = mCLP.getValues(); setBounds(); } public void setBounds () { for (int i = 0; i=0){ h = h + (weight[i])*Math.cos(xval + dSpread*Math.sin(xval/repeats) + dPhase); } else { h = h + (-weight[i])*Math.cos(-(xval + dSpread*Math.sin(xval/repeats)) + dPhase); }; }; // set maximum and minimum heights if (h < hmin) {hmin = h;}; if (h > hmax) {hmax = h;}; H[ix][iy] = h; }; // give controls a chance Thread.yield(); }; }; // reset contour bounds based on newly calculated hmin hmax if (! fixMinMax) {setBounds();}; // draw the contour intervals for (iy = 0; iy < ny; iy++) { // give controls a chance Thread.yield(); // find contours of row iy contour(iy,0,nx); }; // display the contoured pattern source.newPixels(0, 0, nx, ny); (screen.getGraphics()).drawImage(im,0,0,nx,ny,0,0,nx,ny,this); }; // Recalculate contours for one line of drawing public void contour(int iy, int ixmin, int ixmax){ double h; int ix,pix; pix = iy*512 + ixmin; for (ix = ixmin; ix < ixmax; ix++) { h = H[ix][iy]; pixels[pix] = (byte)1; for (int b = 1; b < numberOfControls+1; b++){ if (h >= bound[b-1]) { pixels[pix] = (byte) b ; }; }; pix = pix+1; }; }; public void drawWave(){ Graphics g = waveCanvas.getGraphics(); // draw outline of the wave at the bottom of the screen g.clearRect(0,0,512,100); if (weight[16] == 0) clearWave(); // initialise drawing size double mag, xmin, xmax; mag = (piRange) * Math.PI; xmin = mag*basex; xmax = xmin+2*mag; int nx = size2; double u, h; // initialise height max and min double hmin = 10; double hmax = -10; for (int ix = 0; ix < nx; ix++) { // calculate value ix of wave as h u = xmin + ix * (xmax - xmin) / nx; h = weight[16] * wave[ix]; // add to previous wave if (weight[0]>=0) h = h + (weight[0])*Math.cos(u + dSpread*Math.sin(u/repeats) + dPhase); else h = h + (-weight[0])*Math.cos(-(u + dSpread*Math.sin(u/repeats)) + dPhase); wave [ix] = h; if (h < hmin) hmin = h; if (h > hmax) hmax = h; }; // display the scaled wave g.setColor(Color.black); int nextiy = 50; int iy = (int)(100 - 100*(wave[0] - hmin)/(hmax-hmin)) ; int ix = 0; for (int nextix = 1; nextix < nx; nextix++){ nextiy = (int)(100 - 100*(wave[ix] - hmin)/(hmax-hmin)) ; g.drawLine(ix,iy,nextix,nextiy); ix = nextix; iy = nextiy; } // display middle line g.setColor(Color.blue); g.drawLine(nx/2+1,0,nx/2+1,100); }; public void clearWave(){ for (int i=0; i<512; i++) wave[i] = 0.0; } // introduce IndexColorModel public IndexColorModel changeColorModel(){ byte[] r = new byte[numberOfControls+1]; byte[] g = new byte[numberOfControls+1]; byte[] b = new byte[numberOfControls+1]; for (int i = 1; i < numberOfControls+1; i++){ r[i] = (byte)levelColors[i-1].getRed(); g[i] = (byte)levelColors[i-1].getGreen(); b[i] = (byte)levelColors[i-1].getBlue(); }; r[0] = (byte)0; g[0] = (byte)0; b[0] = (byte)0; return new IndexColorModel(4,numberOfControls+1,r,g,b); }; // initialise the whole shebang public void init(){ clearWave(); // initialise image and add screen to Applet int width = 512; int height = 512; int size = width * height; pixels = new byte[size]; byte blackByte = 0; // for (int i = 0; i < size; i++) { // pixels[i] = blackByte; // }; screen = new Canvas() { public void paint(Graphics g){ }; }; screen.setSize(512,512); add (screen); // initialise weights and add weight control panel for (int i = 0; i < 16; i++) { weight[i] = 1; }; weight[16] = 0; for (int ix = 0; ix<256; ix++) for (int iy = 0; iy<256; iy++) H[ix][iy] = 0.0; D.width = 55; D.height = 512; p = new Panel(){ public Dimension getPreferredSize(){ return D; }; }; for (int i = 0; i <16 ; i++){ W[i] = new TextField("01"); p.add(new Label(""+i)); p.add(W[i]);}; W[16] = new TextField("00"); p.add(new Label("P")); p.add(W[16]); add(p); // add MultiColorLevelPicker mCLP = new MultiColorLevelPicker(); add(mCLP); valueChangeAction(); colorChangeAction(); // add controls add (new Label("Size:"));add(tSize); add (new Label("Sym:"));add(tSym); add (new Label("Phs:"));add(tPhase); add (new Label("Rps:"));add(tRepeats); add (new Label("Spd:"));add(tSpread); add (new Label("PIs:"));add(tPis); add (new Label("X:"));add(tXBase); add (new Label("Y:"));add(tYBase); add(calc); add(cont); add(recol); add(stopit); add(fix); // initialise wave Canvas and add it to Applet waveCanvas = new Canvas() { public Dimension getPreferredSize(){ return new Dimension(512,100); }; public void paint(Graphics g){ }; }; waveCanvas.setSize(512,100); add (waveCanvas); // register listeners calc.addActionListener(this); cont.addActionListener(this); recol.addActionListener(this); stopit.addActionListener(this); tPis.addActionListener(this); fix.addActionListener(this); tPhase.addActionListener(this); tRepeats.addActionListener(this); tSpread.addActionListener(this); for (int i = 0; i <17 ; i++){ W[i].addActionListener(this);}; { (screen.getGraphics()).clearRect(0,0,512,512); drawWave(); if (d != null) {if (d.isAlive()) {d.stop();};}; d = new Drawer(this, true); cthread = d; d.start(); } }; public void actionPerformed(ActionEvent e){ basex = Integer.parseInt (tXBase.getText()); basey = Integer.parseInt (tYBase.getText()); size = Integer.parseInt (tSize.getText()); size2 = (int) Math.pow(2.0,size); sym = Integer.parseInt (tSym.getText()); phase = Integer.parseInt (tPhase.getText()); repeats = Integer.parseInt (tRepeats.getText()); spread = Integer.parseInt (tSpread.getText()); dPhase = phase*2*Math.PI/360; dSpread = spread*2*Math.PI/360; piRange = Integer.parseInt (tPis.getText()); for (int i=0; i<17; i++) { weight[i] = Integer.parseInt (W[i].getText()); }; if (e.getSource()==calc) { (screen.getGraphics()).clearRect(0,0,512,512); drawWave(); if (d != null) {if (d.isAlive()) {d.stop();};}; d = new Drawer(this, true); cthread = d; d.start(); } else if (e.getSource()==cont) { (screen.getGraphics()).clearRect(0,0,512,512); if (d != null) {if (d.isAlive()) {d.stop();};}; d = new Drawer(this, false); cthread = d; d.start(); } else if (e.getSource()==stopit) { if (d != null) {if (d.isAlive()) {d.stop();};}; } else if (e.getSource()==recol) { if (d != null) {if (d.isAlive()) {d.stop();};}; source.newPixels(0, 0, nx, 1); (screen.getGraphics()).drawImage(im,0,0,nx,ny,0,0,nx,ny,this); } else if (e.getSource()==fix) { fixMinMax = ! fixMinMax; if (fixMinMax) { fix.setLabel("FIX ");} else {fix.setLabel("FLT");}; }; }; public void update(){ }; };