1 /*
2  * Copyright (c) 2016 Helmut Neemann
3  * Use of this source code is governed by the GPL v3 license
4  * that can be found in the LICENSE file.
5  */
6 package de.neemann.digital.draw.graphics;
7 
8 import java.util.ArrayList;
9 import java.util.List;
10 
11 /**
12  * Represents a 2D Vector
13  */
14 public class Vector implements VectorInterface {
15 
16     /**
17      * the x coordinate
18      */
19     public final int x;
20     /**
21      * the y coordinate
22      */
23     public final int y;
24 
25     /**
26      * Creates a new instance
27      *
28      * @param x x
29      * @param y y
30      */
Vector(int x, int y)31     public Vector(int x, int y) {
32         this.x = x;
33         this.y = y;
34     }
35 
36     /**
37      * Creates a copy of the given vector
38      *
39      * @param pos the vector to copy
40      */
Vector(VectorInterface pos)41     public Vector(VectorInterface pos) {
42         this(pos.getX(), pos.getY());
43     }
44 
45 
46     /**
47      * Returns a new vector
48      * shorthand for new Vector(x,y)
49      *
50      * @param x x
51      * @param y y
52      * @return the vector
53      */
vec(int x, int y)54     public static Vector vec(int x, int y) {
55         return new Vector(x, y);
56     }
57 
58 
59     /**
60      * returns the minimum vector from the given vectors.
61      *
62      * @param p the vectors to evaluate
63      * @return the minimum
64      */
min(VectorInterface... p)65     public static Vector min(VectorInterface... p) {
66         int x = p[0].getX();
67         int y = p[0].getY();
68         for (int i = 1; i < p.length; i++) {
69             if (p[i].getX() < x) x = p[i].getX();
70             if (p[i].getY() < y) y = p[i].getY();
71         }
72         return new Vector(x, y);
73     }
74 
75     /**
76      * returns the maximim vector from the given vectors.
77      *
78      * @param p the vectors to evaluate
79      * @return the maximum
80      */
max(VectorInterface... p)81     public static Vector max(VectorInterface... p) {
82         int x = p[0].getX();
83         int y = p[0].getY();
84         for (int i = 1; i < p.length; i++) {
85             if (p[i].getX() > x) x = p[i].getX();
86             if (p[i].getY() > y) y = p[i].getY();
87         }
88         return new Vector(x, y);
89     }
90 
91     /**
92      * returns the width of the given vectors.
93      *
94      * @param p the vectors
95      * @return max(p)-min(p)
96      */
width(VectorInterface... p)97     public static Vector width(VectorInterface... p) {
98         int x1 = p[0].getX();
99         int y1 = p[0].getY();
100         int x2 = x1;
101         int y2 = y1;
102         for (int i = 1; i < p.length; i++) {
103             if (p[i].getX() < x1) x1 = p[i].getX();
104             if (p[i].getY() < y1) y1 = p[i].getY();
105             if (p[i].getX() > x2) x2 = p[i].getX();
106             if (p[i].getY() > y2) y2 = p[i].getY();
107         }
108         return new Vector(x2 - x1, y2 - y1);
109     }
110 
111     @Override
add(VectorInterface a)112     public Vector add(VectorInterface a) {
113         return new Vector(x + a.getX(), y + a.getY());
114     }
115 
116     /**
117      * Creates a new vector which has the value this+(x,y)
118      *
119      * @param x x
120      * @param y y
121      * @return this+(x,y)
122      */
add(int x, int y)123     public Vector add(int x, int y) {
124         return new Vector(this.x + x, this.y + y);
125     }
126 
127     /**
128      * Adds an offset to every vector in the given list
129      *
130      * @param vectors the original vectors
131      * @param offs    the offset
132      * @return the new list
133      */
add(List<Vector> vectors, Vector offs)134     public static List<Vector> add(List<Vector> vectors, Vector offs) {
135         ArrayList<Vector> newVec = new ArrayList<>();
136         for (Vector v : vectors)
137             newVec.add(v.add(offs));
138         return newVec;
139     }
140 
141     @Override
sub(VectorInterface a)142     public Vector sub(VectorInterface a) {
143         return new Vector(x - a.getX(), y - a.getY());
144     }
145 
146     /**
147      * Creates a new vector which has the value this*a
148      *
149      * @param a a
150      * @return this*a
151      */
mul(int a)152     public Vector mul(int a) {
153         return new Vector(x * a, y * a);
154     }
155 
156     /**
157      * Creates a new vector which has the value this*a
158      *
159      * @param a a
160      * @return this*a
161      */
mul(float a)162     public VectorFloat mul(float a) {
163         return new VectorFloat(x * a, y * a);
164     }
165 
166     @Override
div(int d)167     public Vector div(int d) {
168         return new Vector(x / d, y / d);
169     }
170 
171     @Override
toString()172     public String toString() {
173         return "(x=" + x
174                 + ", y=" + y
175                 + ')';
176     }
177 
178     /**
179      * Checks if this vector is inside the given bounding box
180      *
181      * @param min upper left corner
182      * @param max lower right corner
183      * @return true is inside
184      */
inside(Vector min, Vector max)185     public boolean inside(Vector min, Vector max) {
186         return min.x <= x && x <= max.x && min.y <= y && y <= max.y;
187     }
188 
189     @Override
equals(Object o)190     public boolean equals(Object o) {
191         if (this == o) return true;
192         if (o == null || getClass() != o.getClass()) return false;
193 
194         Vector vector = (Vector) o;
195 
196         return x == vector.x && y == vector.y;
197 
198     }
199 
200     @Override
hashCode()201     public int hashCode() {
202         int result = x;
203         result = 31 * result + y;
204         return result;
205     }
206 
207     /**
208      * @return true if this vector is (0,0)
209      */
isZero()210     public boolean isZero() {
211         return x == 0 && y == 0;
212     }
213 
214     @Override
norm()215     public VectorFloat norm() {
216         float l = (float) Math.sqrt(x * x + y * y);
217         return new VectorFloat(x / l, y / l);
218     }
219 
220     @Override
getX()221     public int getX() {
222         return x;
223     }
224 
225     @Override
getY()226     public int getY() {
227         return y;
228     }
229 
230     @Override
getXFloat()231     public float getXFloat() {
232         return x;
233     }
234 
235     @Override
getYFloat()236     public float getYFloat() {
237         return y;
238     }
239 
240     @Override
transform(Transform tr)241     public VectorInterface transform(Transform tr) {
242         return tr.transform(this);
243     }
244 
245     @Override
round()246     public Vector round() {
247         return this;
248     }
249 
250     @Override
len()251     public float len() {
252         return (float) Math.sqrt(x * x + y * y);
253     }
254 
255     @Override
toFloat()256     public VectorFloat toFloat() {
257         return new VectorFloat(x, y);
258     }
259 
260     @Override
getOrthogonal()261     public Vector getOrthogonal() {
262         return new Vector(y, -x);
263     }
264 
265 }
266