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