import java.awt.*; public class MandelCanvas extends Canvas implements Runnable { private Mandel master; private double xMin, xMax; private double yMin, yMax; private int iter; private int pixel; private int width; private int height; private boolean newImage; private Thread thread = null; private Image offImage = null; private Graphics offGraph = null; private Color c = new Color(255,0,0); private Rectangle currentRect; private Dimension currentSize; public MandelCanvas(Mandel _master, Image _offImage, int _width, int _height, double _xMin, double _xMax, double _yMin, double _yMax, int _iter, int _pixel) { super(); master = _master; offImage = _offImage; setParams(_xMin,_xMax, _yMin, _yMax, _iter, _pixel); width = _width; height = _height; resize(width,height); offGraph = offImage.getGraphics(); start(); } public void start() { if (thread == null) { offGraph.setColor(Color.white); offGraph.fillRect(0,0,width,height); thread = new Thread(this); thread.setPriority(2); thread.start(); } } public void stop() { if (thread != null) { thread.stop(); thread = null; } } public void setParams(double _xMin, double _xMax, double _yMin, double _yMax, int _iter, int _pixel) { xMin = _xMin; xMax = _xMax; yMin = _yMin; yMax = _yMax; iter = _iter; pixel = _pixel; } static double toWorld(int i, int iMax, double min, double max) { return (max - min) / iMax * ((double)i - iMax) + max; } static int toScreen(double x, int iMax, double min, double max) { return (int)Math.round( iMax / (max - min) * (x - max) + iMax); } public void iterate(double a, double b, int n) { int iter = 0; double x = 0; double y = 0; double tmp = 0; for (iter = 0; iter < n; iter ++) { tmp = x*x - y*y + a; y = 2*x*y + b; x = tmp; if (Math.abs(x) + Math.abs(y) >= 5.0) { c = new Color((20*iter) % 255, 0, 0); break; } else c = Color.blue; } } public void run() { for (int ix = 0; ix < width; ix += pixel) { for (int iy = 0; iy < height; iy +=pixel) { double a = toWorld(ix, width,xMin,xMax); double b = toWorld(iy, height, yMax, yMin); iterate(a,b,iter); offGraph.setColor(c); offGraph.fillRect(ix,iy,pixel,pixel); } repaint(); thread.yield(); } stop(); } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { g.drawImage(offImage,0,0,null); if (currentRect != null) { Rectangle box = getDrawableRect(currentRect, new Dimension(width, height)); g.setColor(Color.green); g.drawRect(box.x, box.y, box.width - 1, box.height - 1); } } public boolean mouseDown(Event event, int x, int y) { if (x > width) x = width; if (y > height) y = height; currentRect = new Rectangle(x, y, 0, 0); repaint(); return false; } public boolean mouseDrag(Event event, int x, int y) { if (x > width) x = width; if (y > height) y = height; double x1 = toWorld(x, width, xMin, xMax); double x2 = toWorld(currentRect.x, width, xMin, xMax); double y1 = toWorld(y, height, yMax, yMin); double y2 = toWorld(currentRect.y, height, yMax, yMin); String msg = "(" + x2 + "," + y2 + ") - (" + x1 + "," + y1 + ")"; master.showMsg(msg); currentRect.resize(x - currentRect.x, y - currentRect.y); repaint(); return false; } public boolean mouseUp(Event event, int x, int y) { if (x > width) x = width; if (y > height) y = height; currentRect.resize(x - currentRect.x, y - currentRect.y); if ((Math.abs(x - currentRect.x) > 8) && (Math.abs(y - currentRect.y) > 8)) { double x1 = toWorld(x, width, xMin, xMax); double x2 = toWorld(currentRect.x, width, xMin, xMax); if (x1 > x2) { double tmp = x1; x1 = x2; x2 = tmp; } double y1 = toWorld(y, height, yMax, yMin); double y2 = toWorld(currentRect.y, height, yMax, yMin); if (y1 > y2) { double tmp = y1; y1 = y2; y2 = tmp; } stop(); setParams(x1,x2,y1,y2,iter,pixel); master.setControlParams(x1,x2,y1,y2,iter,pixel); start(); } currentRect = null; return false; } public boolean mouseMove(Event e, int x, int y) { if (x > width) x = width; if (y > height) y = height; double xx = toWorld(x, width, xMin, xMax); double yy = toWorld(y, height, yMax, yMin); String msg = "(" + String.valueOf(xx) + " , " + String.valueOf(yy) + ")"; master.showMsg(msg); return true; } Rectangle getDrawableRect(Rectangle originalRect, Dimension drawingArea) { int x = originalRect.x; int y = originalRect.y; int width = originalRect.width; int height = originalRect.height; if (width < 0) { width = 0 - width; x = x - width + 1; if (x < 0) { width += x; x = 0; } } if (height < 0) { height = 0 - height; y = y - height + 1; if (y < 0) { height += y; y = 0; } } if ((x + width) > drawingArea.width) { width = drawingArea.width - x; } if ((y + height) > drawingArea.height) { height = drawingArea.height - y; } return new Rectangle(x, y, width, height); } }