1 /*
2  * Copyright 2005 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.common.geometry;
17 
18 /**
19  * R2Vector represents a vector in the two-dimensional space. It defines the
20  * basic geometrical operations for 2D vectors, e.g. cross product, addition,
21  * norm, comparison etc.
22  *
23  */
24 public final strictfp class R2Vector {
25   private final double x;
26   private final double y;
27 
R2Vector()28   public R2Vector() {
29     this(0, 0);
30   }
31 
R2Vector(double x, double y)32   public R2Vector(double x, double y) {
33     this.x = x;
34     this.y = y;
35   }
36 
R2Vector(double[] coord)37   public R2Vector(double[] coord) {
38     if (coord.length != 2) {
39       throw new IllegalStateException("Points must have exactly 2 coordinates");
40     }
41     x = coord[0];
42     y = coord[1];
43   }
44 
x()45   public double x() {
46     return x;
47   }
48 
y()49   public double y() {
50     return y;
51   }
52 
get(int index)53   public double get(int index) {
54     if (index > 1) {
55       throw new ArrayIndexOutOfBoundsException(index);
56     }
57     return index == 0 ? this.x : this.y;
58   }
59 
add(final R2Vector p1, final R2Vector p2)60   public static R2Vector add(final R2Vector p1, final R2Vector p2) {
61     return new R2Vector(p1.x + p2.x, p1.y + p2.y);
62   }
63 
mul(final R2Vector p, double m)64   public static R2Vector mul(final R2Vector p, double m) {
65     return new R2Vector(m * p.x, m * p.y);
66   }
67 
norm2()68   public double norm2() {
69     return (x * x) + (y * y);
70   }
71 
dotProd(final R2Vector p1, final R2Vector p2)72   public static double dotProd(final R2Vector p1, final R2Vector p2) {
73     return (p1.x * p2.x) + (p1.y * p2.y);
74   }
75 
dotProd(R2Vector that)76   public double dotProd(R2Vector that) {
77     return dotProd(this, that);
78   }
79 
crossProd(final R2Vector that)80   public double crossProd(final R2Vector that) {
81     return this.x * that.y - this.y * that.x;
82   }
83 
lessThan(R2Vector vb)84   public boolean lessThan(R2Vector vb) {
85     if (x < vb.x) {
86       return true;
87     }
88     if (vb.x < x) {
89       return false;
90     }
91     if (y < vb.y) {
92       return true;
93     }
94     return false;
95   }
96 
97   @Override
equals(Object that)98   public boolean equals(Object that) {
99     if (!(that instanceof R2Vector)) {
100       return false;
101     }
102     R2Vector thatPoint = (R2Vector) that;
103     return this.x == thatPoint.x && this.y == thatPoint.y;
104   }
105 
106   /**
107    * Calcualates hashcode based on stored coordinates. Since we want +0.0 and
108    * -0.0 to be treated the same, we ignore the sign of the coordinates.
109    */
110   @Override
hashCode()111   public int hashCode() {
112     long value = 17;
113     value += 37 * value + Double.doubleToLongBits(Math.abs(x));
114     value += 37 * value + Double.doubleToLongBits(Math.abs(y));
115     return (int) (value ^ (value >>> 32));
116   }
117 
118   @Override
toString()119   public String toString() {
120     return "(" + x + ", " + y + ")";
121   }
122 }
123