// Mirror.java // /************************************************************************* * * * Copyright (c) 1998 Northwestern University * * * * This program is free software. You can copy, modify, or redistribute * * this software under the terms of the GNU General Public License * * as published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version, provided that both * * the above copyright notice appears in all copies and that this * * permission notice appear in any supporting documentation. * * * * This software is provided "as is" in the hope that it will be useful, * * but WITHOUT any expressed or implied warranty of merchantability or * * fitness for any particular purpose. Your milage may vary. * * See the GNU General Public License for more details. * * * *************************************************************************/ // Modification History // Date Initials Change /* @author Xiaowei Jiang, G. Anderson * @version 0.1, June 1999 */ import java.awt.*; import java.awt.event.*; import java.applet.*; import Banner; public class Mirror extends Applet{ private MirrorCanvas canvas; public Mirror(){ canvas = new MirrorCanvas(); setLayout(new BorderLayout()); add("North", new Banner("Mirrors")); add("South", new MirrorControl(canvas)); add("Center", canvas); } public void init(){ canvas.init(); } public void start(){} public String getAppletInfo(){ return "Copyrighted under the GNU GPL by Northwestern University"; } } class MirrorImage{ public int xx, yy; //Intersection of mirror with axis //origin = (xx,yy) & center = (xx-2*focus, yy) public int height; public double focus; public MirrorImage(double f, int h){ focus = f; height = h; xx = 200; yy = 150; } public double getF(){return focus;} public int getH(){return height;} public int getX(){return xx;} public int getY(){return yy;} public Point getTop(){return new Point(xx, yy+height);} public Point getBottom(){return new Point(xx, yy-height);} public Point getOrigin(){return new Point(xx, yy);} public Point getCenter(){return new Point( (int) (xx-2*focus), yy );} public Point getFocus(){return new Point((int)(xx-focus), yy);} public void setF(double f){focus = f;} public void setX(int x){xx = x;} public void setY(int y){yy = y;} public void setLocation(int x, int y){xx=x; yy = y;} public boolean inside(int x, int y){ if( Math.abs(x-xx)<3 && Math.abs(y-yy) < Math.abs(height) ) return true; else return false; } public void paint(Graphics g){ Point center = getCenter(); Point foc = getFocus(); int radius = (int) Math.abs(2*focus); double alpha1 = Math.atan2(-height, (int) (2*focus)); double alpha2 = Math.atan2(height, (int) (2*focus)); int degree1 = (int) (alpha1/Math.PI*180); int degree2 = (int) (alpha2/Math.PI*180); if(degree2 < degree1) degree2+=360; g.setColor(Color.black); g.drawLine(20, getY(), 520, getY()); g.drawArc(center.x-radius, center.y-radius, 2*radius, 2*radius, degree1, degree2-degree1); g.setColor(Color.black); g.drawLine(center.x, yy-5, center.x, yy+5); g.drawLine(foc.x, yy-5, foc.x, yy+5); } } class MirrorSystem{ private MirrorImage mirror; private MirrorArrow src, img; private int id; //id of the object been activated private boolean showParallelLine = false; private boolean showFocusLine = false; private boolean showCenterLine = false; public MirrorSystem(MirrorImage theMirror){ mirror = theMirror; src = new MirrorArrow(Color.blue, 6, 40); //color, width, height src.setLocation(60, mirror.getY()); //(x,y) img = new MirrorArrow(Color.blue, 6); //color, width, height img.setY(mirror.getY()); } public void setView(boolean a, boolean b, boolean c){ showCenterLine = a; showFocusLine = b; showParallelLine = c; } private void setImg(){ double f = mirror.getF(); int xMirror = mirror.getX(); int yMirror = mirror.getY(); int srcD = xMirror - src.getX(); int imgD = (int) (srcD*f/(srcD-f)); img.setX(xMirror-imgD); if(srcD!=0) img.setHeight(-src.getHeight()*imgD/srcD); if(img.getX() < mirror.getX()) img.setColor(Color.blue); //real image else img.setColor(Color.green); //virtual image } private int extractY(Point first, Point second, int x){ int x1 = first.x, y1 = first.y; int x2 = second.x, y2= second.y; if(x1!=x2) return (int) (y1 + (x-x1)*(y2-y1)/(x2-x1)); else { int LARGE = 10000; return LARGE; } } private void drawCenterLine(Graphics g){ Point srcTip = src.getTip(); Point imgTip = img.getTip(); Point center = mirror.getCenter(); int yOnMirror = extractY(srcTip, center, mirror.getX()); g.setColor(src.getColor()); g.drawLine(srcTip.x, srcTip.y, mirror.getX(), yOnMirror); g.setColor(img.getColor()); g.drawLine(mirror.getX(), yOnMirror, imgTip.x, imgTip.y); if(img.getX() > mirror.getX()){//virtual image if(src.getX() > center.x) {//source in the left of focus, concave case g.setColor(src.getColor()); g.drawLine(srcTip.x, srcTip.y, center.x, center.y); } else {//source in the right of focus, convex case g.setColor(img.getColor()); g.drawLine(imgTip.x, imgTip.y, center.x, center.y); } } } private void drawFocusLine(Graphics g){ int xLeft = 20; Point srcTip = src.getTip(); Point imgTip = img.getTip(); Point foc = mirror.getFocus(); int yOnMirror = extractY(srcTip, foc, mirror.getX()); g.setColor(src.getColor()); g.drawLine(srcTip.x, srcTip.y, mirror.getX(), yOnMirror); g.drawLine(mirror.getX(), yOnMirror, xLeft, yOnMirror); g.setColor(img.getColor()); g.drawLine(mirror.getX(), yOnMirror, imgTip.x, imgTip.y); if(img.getX() > mirror.getX()){//virtual image g.setColor(img.getColor()); if(src.getX() > foc.x) {//source in the left of focus, concave case g.drawLine(srcTip.x, srcTip.y, foc.x, foc.y); } else {//source in the right of focus, convex case g.drawLine(mirror.getX(), yOnMirror, foc.x, foc.y); } } } private void drawParallelLine(Graphics g){ int xLeft = 20; Point srcTip = src.getTip(); Point imgTip = img.getTip(); Point foc = mirror.getFocus(); g.setColor(src.getColor()); g.drawLine(srcTip.x, srcTip.y, mirror.getX(), srcTip.y); g.setColor(img.getColor()); g.drawLine(mirror.getX(), srcTip.y, imgTip.x, imgTip.y); if(img.getX() > mirror.getX()){//virtual image if(src.getX() > foc.x) {//source in the left of focus, concave case g.setColor(src.getColor()); g.drawLine(mirror.getX(), srcTip.y, foc.x, foc.y); } else {//source in the right of focus, convex case g.setColor(img.getColor()); g.drawLine(imgTip.x, imgTip.y, foc.x, foc.y); } } } public void paint(Graphics g){ setImg(); mirror.paint(g); src.paint(g); img.paint(g); if (showParallelLine) drawParallelLine(g); if (showCenterLine) drawCenterLine(g); if (showFocusLine) drawFocusLine(g); } public void move(int x, int y){ switch(id){ case 0://drag mirror moveMirror(x); break; case 1://drag source moveSrc(x); break; case 2://drag image moveImg(x); break; default: break; //do nothing } } private void moveMirror(int x){ if(x >= src.getX()) mirror.setX(x); else mirror.setX(src.getX()); } private void moveSrc(int x){ if(x < mirror.getX()) src.setX(x); else src.setX(mirror.getX()); } private void moveImg(int x){ //do nothing } MouseListener getFocusAssigner(){ return new FocusAssigner(); } class FocusAssigner extends MouseAdapter{ private int insideId(int x, int y){ if(mirror.inside(x,y)) return 0; //case: mirror been selected if(src.inside(x,y)) return 1; //case: source been selected if(img.inside(x,y)) return 2; //case: image been selected else return -1; } public void mousePressed(MouseEvent e){ id = insideId(e.getX(), e.getY()); } } } class MirrorControl extends Panel{ Choice mirrorType; Checkbox center, first, second; MirrorCanvas parent; public MirrorControl(MirrorCanvas theCanvas){ parent = theCanvas; setLayout(new GridLayout(1,4,5,5)); mirrorType = new Choice(); mirrorType.addItem("Convex Mirror"); mirrorType.addItem("Concave Mirror"); add(mirrorType); mirrorType.addItemListener(new ControlListener()); ItemListener view = new ViewListener(); center = new Checkbox("Center Line"); center.setState(false); add(center); center.addItemListener(view); first = new Checkbox("Focus Line"); first.setState(false); add(first); first.addItemListener(view); second = new Checkbox("Parallel Line"); second.setState(false); add(second); second.addItemListener(view); } private class ControlListener implements ItemListener{ public void itemStateChanged(ItemEvent e){ parent.item = mirrorType.getSelectedIndex(); parent.init(); setView(); parent.repaint(); } } private void setView(){ boolean a = center.getState(); boolean b = first.getState(); boolean c = second.getState(); parent.setView(a,b,c); } private class ViewListener implements ItemListener{ public void itemStateChanged(ItemEvent e){ setView(); parent.repaint(); } } } class MirrorCanvas extends Canvas{ public int item; //the item to be show, i.e, converge, or diverge private MirrorSystem mirrorSys; MirrorCanvas(){ item = 0; setBackground(Color.white); } public void init(){ if(item == 0) mirrorSys = new MirrorSystem(new MirrorConvex()); else mirrorSys = new MirrorSystem(new MirrorConcave()); addMouseListener(mirrorSys.getFocusAssigner()); addMouseMotionListener(new MirrorDragListener()); } public void paint(Graphics g){ mirrorSys.paint(g); } public void setView(boolean a, boolean b, boolean c){ mirrorSys.setView(a,b,c); } class MirrorDragListener extends MouseMotionAdapter{ public void mouseDragged(MouseEvent e){ int x = e.getX(); int y = e.getY(); mirrorSys.move(x, y); repaint(); } } } class MirrorConvex extends MirrorImage{ public MirrorConvex(){ super(-80., -80); setX(250); } public MirrorConvex(double f, int h){ super(f, h); setX(250); } } class MirrorConcave extends MirrorImage{ public MirrorConcave(){ super(80., 80); setX(250); } public MirrorConcave(double f, int h){ super(f,h); setX(250); } } class MirrorArrow{ private int xx, yy; private int width, height = 0; Color color; public MirrorArrow(Color theColor, int w){ color = theColor; width = w; } public MirrorArrow(Color theColor, int w, int h){ color = theColor; width = w; height = h; } public int getX(){return xx;} public int getY(){return yy;} public int getHeight(){return height;} public Color getColor(){return color;} public Point getTip(){return new Point(xx, yy-height);} public void setX(int x){xx = x;} public void setY(int y){yy = y;} public void setHeight(int h){height=h; if(width*h<0) width = -width;} public void setLocation(int x, int y){ xx = x; yy = y;} public void setColor(Color colo){color = colo;} public boolean inside(int x, int y){ if( Math.abs(x-xx) > (width/2) || (y-yy)*(y-(yy-height-2*width))>0) return false; else return true; } public void paint(Graphics g){ g.setColor(color); int w = (int) (width/2); int h = (int) (height-Math.sqrt(3)*width); if(height>0) g.fillRect(xx-w, yy-h, width+1, h); else g.fillRect(xx+w, yy, -width+1, -h); paintTriangle(g, xx, yy-h); } private void paintTriangle(Graphics g, int x, int y){ int[] xPoints = new int[3]; int[] yPoints = new int[3]; xPoints[0] = x - width; yPoints[0] = y; xPoints[1] = x + width; yPoints[1] = y; xPoints[2] = x; yPoints[2] = (int) (y - Math.sqrt(3)*width); g.fillPolygon(xPoints, yPoints, 3); } }