001 /*
002 * BallRenderer.java
003 *
004 * Created on February 7, 2003, 4:44 PM
005 */
006
007 package ballworld;
008
009 import cs101.lang.Animate;
010 import cs101.lang.AnimatorThread;
011
012 import java.awt.Point;
013 import java.awt.Color;
014 import java.awt.Graphics2D;
015 import java.awt.geom.Ellipse2D;
016 import java.awt.geom.Ellipse2D.Double;
017
018
019 /** Holds and animates one ball which can be rendered upon requested. Also
020 * provides methods for transforming between world corrdinates (cartesian
021 * with 0,0 at center) and GUI coordinates (0,0 at upper left with inverted
022 * vertical scale as is the norm in Java GUI components)
023 *
024 * @author Patrick G. Heck, gus.heck@olin.edu
025 */
026 public class BallRenderer {
027
028 private Ball myBall;
029 private BallWorld myWorld;
030 private AnimatorThread at;
031 private boolean selected;
032
033 /** Creates a new instance of BallRenderer
034 * @param b The {@link Ball} we are responsible for rendering
035 * @param w The {@link BallWorld} that
036 */
037 public BallRenderer(Ball b, BallWorld w) {
038 this.myBall = b;
039 this.myWorld = w;
040 if (b instanceof Animate) {
041 at = new AnimatorThread((Animate)b,AnimatorThread.START_IMMEDIATELY,0,50);
042 }
043 }
044
045 /**
046 * Draw the ball on the given graphics context.
047 *
048 * @param G A graphics context for drawing
049 */
050 public void drawBall(Graphics2D G) {
051 double radius = myBall.getRadius();
052 double diam = radius*2;
053 Point worldPoint = new Point();
054 worldPoint.setLocation(myBall.getX(), myBall.getY());
055 Point guiPoint = BallRenderer.transformWorld2GUI(worldPoint, myWorld);
056 double x = guiPoint.getX();
057 double y = guiPoint.getY();
058 Ellipse2D.Double ball =
059 new Ellipse2D.Double(x-radius,y-radius,diam,diam);
060 if(selected) {
061 G.setPaint(Color.red);
062 } else {
063 G.setPaint(Color.black);
064 }
065 G.fill(ball);
066 }
067
068 /**
069 * Get the ball held by this renderer.
070 *
071 * @return the ball contained by this renderer.
072 */
073 public Ball getBall() {
074 return myBall;
075 }
076
077 /**
078 * Set the selection status for this ball;
079 *
080 * @param state the state to set (selected or not)
081 */
082 public void setSelected(boolean state) {
083 selected = state;
084 }
085
086 /** Check whether or not the given point resides within the radius of the
087 * ball.
088 *
089 * @param p The point to check
090 * @return <code>true</code> if our ball contains this point, <code>false</code> otherwise.
091 */
092 public boolean containsPoint(Point p) {
093 if (distanceTo(p) <= myBall.getRadius()) {
094 return true;
095 }
096 return false;
097 }
098
099 /** Find the distance from our ball to the given point.
100 *
101 * @param p The point to measure the distance to
102 * @return The distance between the given coordinate and our ball
103 */
104 public double distanceTo(Point p) {
105 double x0 = myBall.getX();
106 double y0 = myBall.getY();
107 double x1 = p.getX();
108 double y1 = p.getY();
109
110 return Math.pow(Math.pow(x0-x1,2) + Math.pow(y0-y1,2),0.5);
111
112 }
113
114 /**
115 * Stop the Animator thread.
116 */
117 public void stop() {
118 at.stopExecution();
119 }
120
121 /** Convert a point from world coordinates to GUI coordinates.
122 * World coordinates are 0,0 at the center of the window with Y
123 * increasing in the up direction (standard Cartesian coordinates).
124 * GUI Coordinates are 0,0 at the upper left with Y increasing downwards
125 *
126 * @return A point in GUI coordinates
127 * @param w The world we are converting from
128 * @param p A point in world coordinates
129 */
130 public static Point transformWorld2GUI(Point p, BallWorld w) {
131 Point newP = new Point();
132 double worldH = w.getGUIMaxY();
133 double worldW = w.getGUIMaxX();
134 newP.setLocation(p.getX() + worldW/2,
135 worldH/2 - p.getY());
136
137 return newP;
138 }
139
140 /** Convert a point from GUI coordinates to world coordinates.
141 * World coordinates 0,0 at the center of the window with Y
142 * increasing in the up direction (standard Cartesian coordinates).
143 * GUI Coordinates are 0,0 at the upper left with Y increasing downwards
144 *
145 * @return A point in world coordinates
146 * @param w The world we are converting to
147 * @param p A point in GUI coordinates
148 */
149 public static Point transformGUI2World(Point p, BallWorld w) {
150 Point newP = new Point();
151 double worldH = w.getGUIMaxY();
152 double worldW = w.getGUIMaxX();
153 newP.setLocation(p.getX() - worldW/2,
154 worldH/2 - p.getY());
155
156 return newP;
157 }
158 }