View Javadoc

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 }