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 }