001 /*
002 * SimuCS - Simulator to use with Classifier Systems
003 * MSc project - Oxford University
004 * by Benoit Isaac - Summer 2005
005 */
006
007 package simuLCS;
008 import java.awt.Color;
009 import java.awt.Graphics2D;
010 import java.awt.geom.Point2D;
011
012 /**
013 * Handles all the functions for 2D Vectors.
014 * @author Benoit
015 *
016 */
017 public class Vector2D {
018
019 private double x, y;
020
021 /**
022 * Creates a vector (0,0)
023 *
024 */
025 public Vector2D() {
026 x = 0.0;
027 y = 0.0;
028 }
029
030 /**
031 * Creates a vector (xp,yp)
032 * @param xp
033 * @param yp
034 */
035 public Vector2D(double xp, double yp) {
036 x = xp;
037 y = yp;
038 }
039
040 /**
041 * Creates a vector between (0,0) and the given point
042 * @param p
043 */
044 public Vector2D(Point2D p) {
045 x = p.getX();
046 y = p.getY();
047 }
048
049 /**
050 * Creates the vector between two given points
051 * @param p1
052 * @param p2
053 */
054 public Vector2D(Point2D p1, Point2D p2) {
055 x = p2.getX() - p1.getX();
056 y = p2.getY() - p1.getY();
057 }
058
059 /**
060 * Creates a clone of a given vector
061 * @param v
062 */
063 public Vector2D(Vector2D v) {
064 x = v.getX();
065 y = v.getY();
066 }
067
068 /**
069 * Add the given vector to this vector (it modifies the vector)
070 * @param v
071 */
072 public void add(Vector2D v) {
073 x = x + v.getX();
074 y = y + v.getY();
075 }
076
077 /**
078 * Change the vector into its opposite
079 *
080 */
081 public void opposite() {
082 x = -x;
083 y = -y;
084 }
085
086 /**
087 * Change the scale of the vector by multiplying its coordinates by a contant
088 * @param d
089 */
090 public void multiplyByConstant(double d) {
091 x = d * x;
092 y = d * y;
093 }
094
095 /**
096 * Set the Vector to the unit vector between the two points
097 * the previous values of the Vector are lost.
098 * @param p1
099 * @param p2
100 */
101 public void setUnitVector(Point2D p1, Point2D p2) {
102 double xv = p2.getX() - p1.getX();
103 double yv = p2.getY() - p1.getY();
104 double dist = Math.sqrt(xv * xv + yv * yv);
105 x = xv / dist;
106 y = yv / dist;
107 }
108
109 /**
110 * Get the norm of the Vector
111 * @return
112 */
113 public double getNorm(){
114 double norm = Math.sqrt((x*x) + (y*y));
115 return norm;
116 }
117
118 /**
119 * @return
120 */
121 public double getX() {
122 return x;
123 }
124
125 /**
126 * @return
127 */
128 public double getY() {
129 return y;
130 }
131
132 /**
133 * @param d
134 */
135 public void setX(double d) {
136 x = d;
137 }
138
139 /**
140 * @param d
141 */
142 public void setY(double d) {
143 y = d;
144 }
145
146 public String toString() {
147 return "Vector: x:" + getX() + " y:" + getY();
148 }
149
150 /**
151 * Paints the vector (useful for debugging)
152 * @param p
153 * @param g
154 * @param c
155 */
156 public void paint(Point2D p, Graphics2D g, Color c) {
157 Color oldc = g.getColor();
158 int x1 = (int) p.getX();
159 int y1 = (int) p.getY();
160 int x2 = x1 + (int) getX();
161 int y2 = y1 + (int) getY();
162 g.setColor(c);
163
164 g.drawLine(x1, y1, x2, y2);
165 g.setColor(oldc);
166 }
167
168 /**
169 * Get a perpendicular vector, on the left
170 * @return
171 */
172 public Vector2D getNormalLeft() {
173 return new Vector2D(this.getY(), -this.getX());
174 }
175
176 /**
177 * Correct the vector so that it doesn't bring the Entity outside the Arena.
178 * @param v
179 * @param a
180 * @param me
181 * @return
182 */
183 public static Vector2D getCorrectedVector(
184 Vector2D movVector,
185 Arena a,
186 Entity me,
187 Graphics2D g) {
188
189 double CLOSEST_DISTANCE_TO_WALL = 4;
190 double SCALE_MOVEMENT = 15;
191
192 Vector2D r = new Vector2D();
193 // movVector.paint(me.getCoord(), g, Color.RED);
194
195 double nextX = me.getCoord().getX() + movVector.getX();
196 double nextY = me.getCoord().getY() + movVector.getY();
197 Point2D nextPosition = new Point2D.Double(nextX, nextY);
198
199 // g.setColor(Color.RED);
200 // g.fillOval(
201 // (int) nextPosition.getX() - 2,
202 // (int) nextPosition.getY() - 2,
203 // 4,
204 // 4);
205
206 if ((a.isInside(nextX, nextY, me.getRadiusBody()))
207 && (a.distanceTo(nextPosition) > CLOSEST_DISTANCE_TO_WALL)) {
208 // next position inside arena, it's ok
209 r.add(movVector);
210 } else {
211 // next position outside, we need to correct
212 Vector2D vNotTooBig = new Vector2D(me.getCoord(), nextPosition);
213 vNotTooBig.add(vNotTooBig.getNormalLeft());
214
215 double withNormLeftX = me.getCoord().getX() + vNotTooBig.getX();
216 double withNormLeftY = me.getCoord().getY() + vNotTooBig.getY();
217
218 Point2D withNormLeft = new Point2D.Double(withNormLeftX,
219 withNormLeftY);
220
221 vNotTooBig.setUnitVector(me.getCoord(), withNormLeft);
222 vNotTooBig.multiplyByConstant(SCALE_MOVEMENT);
223
224 double nextXnotTooBig = me.getCoord().getX() + vNotTooBig.getX();
225 double nextYnotTooBig = me.getCoord().getY() + vNotTooBig.getY();
226
227 Point2D nextPosNotTooBig =
228 new Point2D.Double(nextXnotTooBig, nextYnotTooBig);
229
230 Point2D correctedNextPosition =
231 a.closestPointTo(
232 nextPosNotTooBig,
233 a.getRadius()
234 - me.getRadiusBody()
235 - CLOSEST_DISTANCE_TO_WALL);
236 // g.setColor(Color.GREEN);
237 // g.fillOval(
238 // (int) correctedNextPosition.getX() - 2,
239 // (int) correctedNextPosition.getY() - 2,
240 // 4,
241 // 4);
242 r.add(movVector);
243 Vector2D toRemove =
244 new Vector2D(nextPosition, correctedNextPosition);
245 r.add(toRemove);
246 // r.paint(me.getCoord(), g, Color.GREEN);
247
248 // try {
249 // Thread.sleep(5000);
250 // } catch (InterruptedException e) {
251 // }
252
253 }
254
255 return r;
256 }
257
258 }