1 /* File Point2D.java 2 * 3 * Project : Java Geometry Library 4 * 5 * =========================================== 6 * 7 * This library is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU Lesser General Public License as published by 9 * the Free Software Foundation, either version 2.1 of the License, or (at 10 * your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY 14 * or FITNESS FOR A PARTICULAR PURPOSE. 15 * 16 * See the GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with this library. if not, write to : 20 * The Free Software Foundation, Inc., 59 Temple Place, Suite 330, 21 * Boston, MA 02111-1307, USA. 22 */ 23 24 // package 25 26 package math.geom2d; 27 28 import java.io.Serializable; 29 30 // Imports 31 32 /** 33 * A vector in the 2D plane. Provides methods to compute cross product and dot 34 * product, addition and subtraction of vectors. 35 */ 36 public class Vector2D implements Cloneable, Serializable { 37 38 // =================================================================== 39 // constants 40 41 // =================================================================== 42 // class variables 43 44 protected double x = 1; 45 protected double y = 0; 46 47 // =================================================================== 48 // constructors 49 50 /** 51 * Constructs a new Vectors initialized with x=1 and y=0. 52 */ 53 public Vector2D() { 54 this(1, 0); 55 } 56 57 /** 58 * Constructs a new vector between the origin and the given point. 59 */ 60 public Vector2D(java.awt.geom.Point2D point) { 61 this(point.getX(), point.getY()); 62 } 63 64 /** 65 * Constructs a new vector between two points 66 */ 67 public Vector2D(java.awt.geom.Point2D point1, java.awt.geom.Point2D point2) { 68 this(point2.getX()-point1.getX(), point2.getY()-point1.getY()); 69 } 70 71 /** 72 * Constructs a new vector with the given coordinates. 73 * Consider creating a new Vector using static factory. 74 */ 75 public Vector2D(double x, double y) { 76 this.x = x; 77 this.y = y; 78 } 79 80 // =================================================================== 81 // static functions 82 83 /** 84 * Static factory for creating a new vector from the coordinate of a point. 85 * @since 0.8.1 86 */ 87 public static Vector2D create(Point2D point) { 88 return new Vector2D(point.getX(), point.getY()); 89 } 90 91 /** 92 * Static factory for creating a new point in cartesian coordinates. 93 * @since 0.8.1 94 */ 95 public static Vector2D create(double x, double y) { 96 return new Vector2D(x, y); 97 } 98 99 100 /** 101 * Creates a new vector by specifying the distance to the origin, and the 102 * angle with the horizontal. 103 */ 104 public final static Vector2D createPolar(double rho, double theta) { 105 return new Vector2D(rho*Math.cos(theta), rho*Math.sin(theta)); 106 } 107 108 /** 109 * Get the dot product of the two vectors, defined by : 110 * <p> 111 * <code> dx1*dy2 + dx2*dy1</code> 112 * <p> 113 * Dot product is zero if the vectors defined by the 2 vectors are 114 * orthogonal. It is positive if vectors are in the same direction, and 115 * negative if they are in opposite direction. 116 */ 117 public final static double dot(Vector2D v1, Vector2D v2) { 118 return v1.getX()*v2.getX()+v1.getY()*v2.getY(); 119 } 120 121 /** 122 * Get the cross product of the two vectors, defined by : 123 * <p> 124 * <code> dx1*dy2 - dx2*dy1</code> 125 * <p> 126 * cross product is zero for colinear vectors. It is positive if angle 127 * between vector 1 and vector 2 is comprised between 0 and PI, and negative 128 * otherwise. 129 */ 130 public final static double cross(Vector2D v1, Vector2D v2) { 131 return v1.getX()*v2.getY()-v2.getX()*v1.getY(); 132 } 133 134 /** 135 * Tests if the two vectors are colinear 136 * 137 * @return true if the vectors are colinear 138 */ 139 public final static boolean isColinear(Vector2D v1, Vector2D v2) { 140 v1 = v1.getNormalizedVector(); 141 v2 = v2.getNormalizedVector(); 142 return Math.abs(v1.getX()*v2.getY()-v1.getY()*v2.getX())<Shape2D.ACCURACY; 143 } 144 145 /** 146 * Tests if the two vectors are orthogonal 147 * 148 * @return true if the vectors are orthogonal 149 */ 150 public final static boolean isOrthogonal(Vector2D v1, Vector2D v2) { 151 v1 = v1.getNormalizedVector(); 152 v2 = v2.getNormalizedVector(); 153 return Math.abs(v1.getX()*v2.getX()+v1.getY()*v2.getY())<Shape2D.ACCURACY; 154 } 155 156 // =================================================================== 157 // accessors 158 159 public double getX() { 160 return this.x; 161 } 162 163 public double getY() { 164 return this.y; 165 } 166 167 // =================================================================== 168 // modifiers 169 170 /** 171 * @deprecated vectors will become imutable in a future release 172 */ 173 @Deprecated 174 public void setX(double x) { 175 this.x = x; 176 } 177 178 /** 179 * @deprecated vectors will become imutable in a future release 180 */ 181 @Deprecated 182 public void setY(double y) { 183 this.y = y; 184 } 185 186 /** 187 * @deprecated vectors will become imutable in a future release 188 */ 189 @Deprecated 190 public void setVector(double x, double y) { 191 this.x = x; 192 this.y = y; 193 } 194 195 /** 196 * Set location specified as polar coordinate : distance from origin + angle 197 * with horizontal. 198 * @deprecated vectors will become imutable in a future release 199 */ 200 @Deprecated 201 public void setAsPolar(double rho, double theta) { 202 this.x = rho*Math.cos(theta); 203 this.y = rho*Math.sin(theta); 204 } 205 206 /** 207 * Returns the opposite vector v2 of this, such that the sum of this and v2 208 * equals the null vector. 209 * 210 * @return the vector opposite to <code>this</code>. 211 */ 212 public Vector2D getOpposite() { 213 return new Vector2D(-this.x, -this.y); 214 } 215 216 /** 217 * Computes the norm of the vector 218 * 219 * @return the euclidean norm of the vector 220 */ 221 public double getNorm() { 222 return Math.hypot(x, y); 223 } 224 225 /** 226 * Returns the angle with the horizontal axis, in radians. 227 * 228 * @return the horizontal angle of the vector 229 */ 230 public double getAngle() { 231 return Angle2D.getHorizontalAngle(this); 232 } 233 234 /** 235 * Normalizes the vector, such that its norms becomes 1. 236 */ 237 public void normalize() { 238 double r = Math.hypot(this.x, this.y); 239 this.x = this.x/r; 240 this.y = this.y/r; 241 } 242 243 /** 244 * Returns the vector with same direction as this one, but with norm equal 245 * to 1. 246 */ 247 public Vector2D getNormalizedVector() { 248 double r = Math.hypot(this.x, this.y); 249 return new Vector2D(this.x/r, this.y/r); 250 } 251 252 // =================================================================== 253 // compare with other vectors 254 255 /** 256 * test if the two vectors are colinear 257 * 258 * @return true if the vectors are colinear 259 */ 260 public boolean isColinear(Vector2D v) { 261 return Vector2D.isColinear(this, v); 262 } 263 264 /** 265 * test if the two vectors are orthogonal 266 * 267 * @return true if the vectors are orthogonal 268 */ 269 public boolean isOrthogonal(Vector2D v) { 270 return Vector2D.isOrthogonal(this, v); 271 } 272 273 // =================================================================== 274 // operations between vectors 275 276 /** 277 * Get the dot product with point <code>p</code>. Dot product id defined 278 * by : 279 * <p> 280 * <code> x1*y2 + x2*y1</code> 281 * <p> 282 * Dot product is zero if the vectors defined by the 2 points are 283 * orthogonal. It is positive if vectors are in the same direction, and 284 * negative if they are in opposite direction. 285 */ 286 public double dot(Vector2D v) { 287 return x*v.getX()+y*v.getY(); 288 } 289 290 /** 291 * Get the cross product with point <code>p</code>. Cross product is 292 * defined by : 293 * <p> 294 * <code> x1*y2 - x2*y1</code> 295 * <p> 296 * cross product is zero for colinear vector. It is positive if angle 297 * between vector 1 and vector 2 is comprised between 0 and PI, and negative 298 * otherwise. 299 */ 300 public double cross(Vector2D v) { 301 return x*v.getY()-v.getX()*y; 302 } 303 304 /** 305 * Returns the sum of current vector with vector given as parameter. Inner 306 * fields are not modified. 307 */ 308 public Vector2D plus(Vector2D v) { 309 return new Vector2D(x+v.getX(), y+v.getY()); 310 } 311 312 /** 313 * Returns the subtraction of current vector with vector given as 314 * parameter. Inner fields are not modified. 315 */ 316 public Vector2D minus(Vector2D v) { 317 return new Vector2D(x-v.getX(), y-v.getY()); 318 } 319 320 /** 321 * Multiplies the vector by a scalar amount. Inner fields are not 322 * @param k the scale factor 323 * @return the scaled vector 324 * @since 0.7.0 325 */ 326 public Vector2D times(double k) { 327 return new Vector2D(this.x*k, this.y*k); 328 } 329 330 /** 331 * Transform the vector, by using only the first 4 parameters of the 332 * transform. Translation of a vector returns the same vector. 333 * 334 * @param trans an affine transform 335 * @return the transformed vector. 336 */ 337 public Vector2D transform(AffineTransform2D trans) { 338 double[] tab = trans.getCoefficients(); 339 return new Vector2D(x*tab[0]+y*tab[1], x*tab[3]+y*tab[4]); 340 } 341 342 /** 343 * Test whether this object is the same as another vector. 344 */ 345 @Override 346 public boolean equals(Object obj) { 347 if (!(obj instanceof Vector2D)) 348 return false; 349 Vector2D v = (Vector2D) obj; 350 return (Math.abs(v.getX()-x)<Shape2D.ACCURACY&&Math.abs(v.getY()-y)<Shape2D.ACCURACY); 351 } 352 353 @Override 354 public String toString() { 355 return new String("Vector2D(" + x + ", "+y+")"); 356 } 357 358 @Override 359 public Vector2D clone() { 360 return new Vector2D(x, y); 361 } 362 }