- Draw 3 circles.
- Erase the left half of the upper circle and the right half of the lower circle.
- Add two "eyes".
- Fill regions with appropriate color.
Straight forward implementation
public void drawTaichi(BufferedImage image) { java.awt.Graphics2D gr = (java.awt.Graphics2D) image.getGraphics(); gr.setColor(java.awt.Color.WHITE); gr.fillRect(0,0,300,300); gr.setStroke(new java.awt.BasicStroke(2)); // pen width gr.setColor(java.awt.Color.BLACK); // draw a big circle with radius 100 with center at (150,150) int r=100; // radius int xc=150, yc=150; // center // the bounding rectangle (x,y,w,h) of the circle is defined by : // x=xc-r, y=yc-r, w=r*2, h=r*2; gr.drawArc(xc-r,yc-r,r*2,r*2,0,360); // (x,y,w,h,startDegree,arcDegree) // draw a small half circle with radius 50 with center at (150,100) xc=150; yc=100; r=50; gr.drawArc(xc-r,yc-r,r*2,r*2,270,180); // (x,y,w,h,startDegree,arcDegree) // draw another small half circle with radius 50 with center at (150,200) xc=150; yc=200; r=50; gr.drawArc(xc-r,yc-r,r*2,r*2,90,180); // (x,y,w,h,startDegree,arcDegree) // draw two more small circles ("eyes") xc=150; yc=100; r=12; gr.drawArc(xc-r,yc-r,r*2,r*2,0,360); // (x,y,w,h,startDegree,arcDegree) xc=150; yc=200; r=12; gr.drawArc(xc-r,yc-r,r*2,r*2,0,360); // (x,y,w,h,startDegree,arcDegree) // fill with appropriate color int black=packRgb(0,0,0); floodFill(image,150,100,black); floodFill(image,150,160,black); }
The above implementation uses the floodFill() method described in the previous article.
Improvement : removing the hard coded values
The above implementation is full of hard coded values such as 300,150,100...etc. A way to remove those hard coded values is to introduce magic constants such as :int BIG_RADIUS=100; int HARD_RADIUS=BIG_RADIUS/2; ...
Another approach is to redefine the drawing routine to accept parameters. Full runnable sample follows :
/****************************************************************************** * File : Taichi.java * Author : http://java.macteki.com/ * Description : * Draw a Taichi image in a graphics panel. * Tested with : JDK 1.6 ******************************************************************************/ import java.awt.image.BufferedImage; import java.awt.Point; class Taichi extends javax.swing.JPanel { private BufferedImage taichiImage; public static Taichi getInstance() { Taichi panel=new Taichi(); panel.setPreferredSize(new java.awt.Dimension(320,320)); panel.taichiImage = new BufferedImage(300,300,BufferedImage.TYPE_INT_RGB); panel.drawTaichi(panel.taichiImage,150,150,100); return panel; } // draw a taichi image public void drawTaichi(BufferedImage image,int xCenter,int yCenter, int radius) { java.awt.Graphics2D gr = (java.awt.Graphics2D) image.getGraphics(); gr.setColor(java.awt.Color.WHITE); gr.fillRect(0,0,image.getWidth(this),image.getWidth(this)); gr.setStroke(new java.awt.BasicStroke(2)); // pen width gr.setColor(java.awt.Color.BLACK); // draw the big circle int r=radius; // radius int xc=xCenter, yc=yCenter; // center // the bounding rectangle (x,y,w,h) of the circle is defined by : // x=xc-r, y=yc-r, w=r*2, h=r*2; gr.drawArc(xc-r,yc-r,r*2,r*2,0,360); // (x,y,w,h,startDegree,arcDegree) // draw a half circle inside the big circle xc=xCenter; yc=yCenter-radius/2; r=radius/2; gr.drawArc(xc-r,yc-r,r*2,r*2,270,180); // (x,y,w,h,startDegree,arcDegree) // draw another half circle inside the big circle xc=xCenter; yc=yCenter+radius/2; r=radius/2; gr.drawArc(xc-r,yc-r,r*2,r*2,90,180); // (x,y,w,h,startDegree,arcDegree) // draw two more small circles xc=xCenter; yc=yCenter-radius/2; r=radius/8; gr.drawArc(xc-r,yc-r,r*2,r*2,0,360); // (x,y,w,h,startDegree,arcDegree) xc=xCenter; yc=yCenter+radius/2; r=radius/8+1; gr.drawArc(xc-r,yc-r,r*2,r*2,0,360); // (x,y,w,h,startDegree,arcDegree) // fill with appropriate color int black=packRgb(0,0,0); floodFill(image,xCenter,yCenter-radius/2,black); floodFill(image,xCenter,yCenter+radius/16,black); } // override the paint method // just paint the taichi image here public void paintComponent(java.awt.Graphics graphics) { super.paintComponent(graphics); // Graphics2D is a better choice to the default Graphics object java.awt.Graphics2D gr=(java.awt.Graphics2D) graphics; gr.drawImage(taichiImage,10,10,this); } public static int packRgb(int r,int g,int b) { return (r*256+g)*256+b; } // implements the flood fill algorithm public static void floodFill(BufferedImage image, int x,int y, int fillColor) { java.util.ArrayList<Point> examList=new java.util.ArrayList<Point>(); int initialColor=image.getRGB(x,y); examList.add(new Point(x,y)); while (examList.size()>0) { Point p = examList.remove(0); // get and remove the first point in the list if (image.getRGB(p.x,p.y)==initialColor) { x = p.x; y = p.y; image.setRGB(x, y, fillColor); // fill current pixel if (image.getRGB(x-1,y)==initialColor) // check west neighbor { examList.add(new Point(x-1,y)); } if (image.getRGB(x+1,y)==initialColor) // check east neighbor { examList.add(new Point(x+1,y)); } if (image.getRGB(x,y-1)==initialColor) // check north neighbor { examList.add(new Point(x,y-1)); } if (image.getRGB(x,y+1)==initialColor) // check south neighbor { examList.add(new Point(x,y+1)); } } } } public static void main(String[] args) throws Exception { Taichi graphicPanel = Taichi.getInstance(); javax.swing.JFrame window=new javax.swing.JFrame(); window.add(graphicPanel); window.pack(); window.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); window.setTitle("Macteki Taichi Panel"); window.setVisible(true); } }
The next article will make a rotating Taichi animation.
Thanks for reading. Comments are welcome.
No comments:
Post a Comment