import java.applet.*; import java.awt.*; import java.awt.image.BufferedImage; import java.awt.event.MouseMotionListener; import java.awt.event.MouseEvent; public class Spiral extends Applet implements Runnable, MouseMotionListener { int _radius; // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 int[] _fibonacci={0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657}; int _patterns=_fibonacci.length-8; int _index=0; int _drawn=0; double _phi=1.61803399; // Golden Ratio double _anglestep=2 * 3.141592654 * _phi; // (circle (Golden Ratio)) in Radians double _scale=1; Graphics2D _big; BufferedImage[] _bi=new BufferedImage[_patterns]; public void paint(Graphics g) {((Graphics2D)g).drawImage(_bi[_index],0,0,this);} public void init() { _radius=(getSize().width < getSize().height ? getSize().width : getSize().height)/2; new Thread(this).start(); addMouseMotionListener(this); } public void run() {for(_drawn=0; _drawn<_patterns; ++_drawn) drawSeedHeadImage(_drawn);} public void mouseDragged(MouseEvent e) {} public void mouseMoved(MouseEvent e) { int NewIndex=Math.max(0,(int)(_drawn-_drawn*Math.hypot(e.getX()-_radius,e.getY()-_radius)/_radius)); if(_index==NewIndex) return; _index=NewIndex; repaint(); } public void drawSeedHeadImage(int n) { _bi[n]=new BufferedImage(2*_radius,2*_radius, BufferedImage.TYPE_INT_RGB); _big=_bi[n].createGraphics(); // Use a back-buffer to paint on: _big.drawImage(_bi[n],0,0,this); _big.setColor(Color.white); _big.fillRect(0,0,getSize().width, getSize().height); _big.setStroke(new BasicStroke(2.0f)); // 2-pixel lines _big.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); _big.translate(_radius,_radius); float[] Split={0.f, 0.5f, 1.f}; // Background: Color[] Colours={new Color(0.f,0.f,1.f,.6f), new Color(1.f,0.f,0.f,.8f), new Color(0.f,0.f,1.f,.2f)}; _big.setPaint(new RadialGradientPaint(0,0, _radius, Split, Colours)); disk(0,0, _radius); drawSeedHead(n); } public void drawSeedHead(int n) { int Seeds=_fibonacci[n+=_fibonacci.length-_patterns]; int SpiralA=_fibonacci[n=(int)(n/_phi)]; // The most natural curves are here. int SpiralB=_fibonacci[n+1]; // one will be clockwise, its neighbour anticlockwise. _scale=_radius/(Math.sqrt(Seeds)+_phi/2); // Draw the seed head: for(int i=1; iSpiralA) _big.drawLine(x,y, X(i-SpiralA),Y(i-SpiralA)); if(i>SpiralB) _big.drawLine(x,y, X(i-SpiralB),Y(i-SpiralB)); circle(x,y,(int)(_scale*_phi/2)); } _big.setFont(new Font("Sans Serif",java.awt.Font.BOLD,18)); _big.setColor(Color.black); _big.drawString("SpiralA="+Integer.toString(SpiralA), 1-_radius, 18-_radius); _big.drawString("SpiralB="+Integer.toString(SpiralB), 1-_radius, 36-_radius); _big.drawString("Seeds="+Integer.toString(Seeds), 1-_radius, 54-_radius); } private int X(double n) {return (int)(_scale*Math.sqrt(n)*Math.sin(n*_anglestep));} private int Y(double n) {return (int)(_scale*Math.sqrt(n)*Math.cos(n*_anglestep));} public void circle(int x, int y, int r) {_big.drawOval(x-r,y-r, 2*r,2*r);} public void disk(int x, int y, int r) { int mx=x-r, my=y-r, d=2*r; _big.fillOval(mx,my,d,d); _big.drawOval(mx,my,d,d); } private Color getRainbowColour(double Ratio) {return new Color(GetGreen(Ratio + 1/3.), GetGreen(Ratio), GetGreen(Ratio - 1/3.), 0.5f);} private float GetGreen(double n) { // 1 __ Returns the amplitude of Green through the spectrum: if(n<0.) n=n+1; //GetGreen / \__ shift the X-Axis 1/3 backwards or forwards to get red and blue if(n>1.) n=n-1; // 0 n 1 if(n<1/6.) return new Float(n * 6.); if(n<1/2.) return 1.f; if(n<2/3.) return new Float((2/3. - n) * 6.); return 0.f; } }