1 /**
2  * Represents a 2D vector with integral-precision.
3  *
4  * @author RGreenlees
5  * @author Kai Burjack
6  * @author Hans Uhlig
7  */
8 module doml.vector_2i;
9 
10 import Math = doml.math;
11 
12 import doml.vector_2d;
13 
14 
15 /*
16  * The MIT License
17  *
18  * Copyright (c) 2015-2021 Richard Greenlees
19  @#$@#!$ Translated by jordan4ibanez
20  *
21  * Permission is hereby granted, free of charge, to any person obtaining a copy
22  * of this software and associated documentation files (the "Software"), to deal
23  * in the Software without restriction, including without limitation the rights
24  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25  * copies of the Software, and to permit persons to whom the Software is
26  * furnished to do so, subject to the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be included in
29  * all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37  * THE SOFTWARE.
38  */
39 
40 /**
41  * Represents a 2D vector with integer-precision.
42  *
43  * @author RGreenlees
44  * @author Kai Burjack
45  * @author Hans Uhlig
46  */
47 struct Vector2i {
48 
49     /**
50      * The x component of the vector.
51      */
52     public int x;
53     /**
54      * The y component of the vector.
55      */
56     public int y;
57 
58     /**
59      * Create a new {@link Vector2i} and initialize both of its components with
60      * the given value.
61      *
62      * @param s
63      *          the value of both components
64      */
65     this(int s) {
66         this.x = s;
67         this.y = s;
68     }
69 
70     /**
71      * Create a new {@link Vector2i} and initialize its components to the given values.
72      *
73      * @param x
74      *          the x component
75      * @param y
76      *          the y component
77      */
78     this(int x, int y) {
79         this.x = x;
80         this.y = y;
81     }
82 
83     /**
84      * Create a new {@link Vector2i} and initialize its component values and
85      * round using the given {@link RoundingMode}.
86      * @param x
87      *          the x component
88      * @param y
89      *          the y component
90      * @param mode
91      *          the {@link RoundingMode} to use
92      */
93     this(double x, double y, int mode) {
94         this.x = Math.roundUsing(x, mode);
95         this.y = Math.roundUsing(y, mode);
96     }
97 
98     /**
99      * Create a new {@link Vector2i} and initialize its components to the one of
100      * the given vector.
101      *
102      * @param v
103      *          the {@link Vector2i} to copy the values from
104      */
105     this(Vector2i v) {
106         x = v.x;
107         y = v.y;
108     }
109 
110     /**
111      * Create a new {@link Vector2i} and initialize its components to the rounded value of
112      * the given vector.
113      *
114      * @param v
115      *          the {@link Vector2d} to round and copy the values from
116      * @param mode
117      *          the {@link RoundingMode} to use
118      */
119     this(Vector2d v, int mode) {
120         x = Math.roundUsing(v.x, mode);
121         y = Math.roundUsing(v.y, mode);
122     }
123 
124     /**
125      * Create a new {@link Vector2i} and initialize its two components from the first
126      * two elements of the given array.
127      * 
128      * @param xy
129      *          the array containing at least three elements
130      */
131     this(int[] xy) {
132         this.x = xy[0];
133         this.y = xy[1];
134     }
135 
136     /**
137      * Set the x and y components to the supplied value.
138      *
139      * @param s
140      *          scalar value of both components
141      * @return this
142      */
143     ref public Vector2i set(int s) return {
144         this.x = s;
145         this.y = s;
146         return this;
147     }
148 
149     /**
150      * Set the x and y components to the supplied values.
151      *
152      * @param x
153      *          the x component
154      * @param y
155      *          the y component
156      * @return this
157      */
158     ref public Vector2i set(int x, int y) return {
159         this.x = x;
160         this.y = y;
161         return this;
162     }
163 
164     /**
165      * Set this {@link Vector2i} to the values of v.
166      *
167      * @param v
168      *          the vector to copy from
169      * @return this
170      */
171     ref public Vector2i set(Vector2i v) return {
172         this.x = v.x;
173         this.y = v.y;
174         return this;
175     }
176 
177     /**
178      * Set this {@link Vector2i} to the values of v using {@link RoundingMode#TRUNCATE} rounding.
179      * <p>
180      * Note that due to the given vector <code>v</code> storing the components
181      * in double-precision, there is the possibility to lose precision.
182      *
183      * @param v
184      *          the vector to copy from
185      * @return this
186      */
187     ref public Vector2i set(Vector2d v) return {
188         this.x = cast(int) v.x;
189         this.y = cast(int) v.y;
190         return this;
191     }
192 
193     /**
194      * Set this {@link Vector2i} to the values of v using the given {@link RoundingMode}.
195      * <p>
196      * Note that due to the given vector <code>v</code> storing the components
197      * in double-precision, there is the possibility to lose precision.
198      *
199      * @param v
200      *          the vector to copy from
201      * @param mode
202      *          the {@link RoundingMode} to use
203      * @return this
204      */
205     ref public Vector2i set(Vector2d v, int mode) return {
206         this.x = Math.roundUsing(v.x, mode);
207         this.y = Math.roundUsing(v.y, mode);
208         return this;
209     }
210 
211     /**
212      * Set the two components of this vector to the first two elements of the given array.
213      * 
214      * @param xy
215      *          the array containing at least two elements
216      * @return this
217      */
218     ref public Vector2i set(int[] xy) return {
219         this.x = xy[0];
220         this.y = xy[1];
221         return this;
222     }
223 
224     public int get(int component) {
225         switch (component) {
226         case 0:
227             return x;
228         case 1:
229             return y;
230         default:
231             return 0; // do nothing
232         }
233     }
234 
235     /**
236      * Set the value of the specified component of this vector.
237      *
238      * @param component
239      *          the component whose value to set, within <code>[0..1]</code>
240      * @param value
241      *          the value to set
242      * @return this
243      * @throws IllegalArgumentException if <code>component</code> is not within <code>[0..1]</code>
244      */
245     ref public Vector2i setComponent(int component, int value) return {
246         switch (component) {
247             case 0:
248                 x = value;
249                 break;
250             case 1:
251                 y = value;
252                 break;
253             default:{}
254         }
255         return this;
256     }
257 
258     /**
259      * Subtract the supplied vector from this one and store the result in
260      * <code>this</code>.
261      *
262      * @param v
263      *          the vector to subtract
264      * @return this
265      */
266     ref public Vector2i sub(Vector2i v) return {
267         this.x = x - v.x;
268         this.y = y - v.y;
269         return this;
270     }
271 
272     public Vector2i sub(Vector2i v, ref Vector2i dest) {
273         dest.x = x - v.x;
274         dest.y = y - v.y;
275         return dest;
276     }
277 
278     /**
279      * Decrement the components of this vector by the given values.
280      *
281      * @param x
282      *          the x component to subtract
283      * @param y
284      *          the y component to subtract
285      * @return this
286      */
287     ref public Vector2i sub(int x, int y) return {
288         this.x = this.x - x;
289         this.y = this.y - y;
290         return this;
291     }
292 
293     public Vector2i sub(int x, int y, ref Vector2i dest) {
294         dest.x = this.x - x;
295         dest.y = this.y - y;
296         return dest;
297     }
298 
299     public long lengthSquared() {
300         return x * x + y * y;
301     }
302 
303     /**
304      * Get the length squared of a 2-dimensional single-precision vector.
305      *
306      * @param x The vector's x component
307      * @param y The vector's y component
308      *
309      * @return the length squared of the given vector
310      */
311     public static long lengthSquared(int x, int y) {
312         return x * x + y * y;
313     }
314 
315     public double length() {
316         return Math.sqrt(x * x + y * y);
317     }
318 
319     /**
320      * Get the length of a 2-dimensional single-precision vector.
321      *
322      * @param x The vector's x component
323      * @param y The vector's y component
324      *
325      * @return the length squared of the given vector
326      */
327     public static double length(int x, int y) {
328         return Math.sqrt(x * x + y * y);
329     }
330 
331     public double distance(Vector2i v) {
332         int dx = this.x - v.x;
333         int dy = this.y - v.y;
334         return Math.sqrt(dx * dx + dy * dy);
335     }
336 
337     public double distance(int x, int y) {
338         int dx = this.x - x;
339         int dy = this.y - y;
340         return Math.sqrt(dx * dx + dy * dy);
341     }
342 
343     public long distanceSquared(Vector2i v) {
344         int dx = this.x - v.x;
345         int dy = this.y - v.y;
346         return dx * dx + dy * dy;
347     }
348 
349     public long distanceSquared(int x, int y) {
350         int dx = this.x - x;
351         int dy = this.y - y;
352         return dx * dx + dy * dy;
353     }
354 
355     public long gridDistance(Vector2i v) {
356         return Math.abs(v.x - x) + Math.abs(v.y - y);
357     }
358 
359     public long gridDistance(int x, int y) {
360         return Math.abs(x - this.x) + Math.abs(y - this.y);
361     }
362 
363     /**
364      * Return the distance between <code>(x1, y1)</code> and <code>(x2, y2)</code>.
365      *
366      * @param x1
367      *          the x component of the first vector
368      * @param y1
369      *          the y component of the first vector
370      * @param x2
371      *          the x component of the second vector
372      * @param y2
373      *          the y component of the second vector
374      * @return the euclidean distance
375      */
376     public static double distance(int x1, int y1, int x2, int y2) {
377         int dx = x1 - x2;
378         int dy = y1 - y2;
379         return Math.sqrt(dx * dx + dy * dy);
380     }
381 
382     /**
383      * Return the squared distance between <code>(x1, y1)</code> and <code>(x2, y2)</code>.
384      *
385      * @param x1
386      *          the x component of the first vector
387      * @param y1
388      *          the y component of the first vector
389      * @param x2
390      *          the x component of the second vector
391      * @param y2
392      *          the y component of the second vector
393      * @return the euclidean distance squared
394      */
395     public static long distanceSquared(int x1, int y1, int x2, int y2) {
396         int dx = x1 - x2;
397         int dy = y1 - y2;
398         return dx * dx + dy * dy;
399     }
400     
401     /**
402      * Add <code>v</code> to this vector.
403      *
404      * @param v
405      *          the vector to add
406      * @return this
407      */
408     ref public Vector2i add(Vector2i v) return {
409         this.x = x + v.x;
410         this.y = y + v.y;
411         return this;
412     }
413 
414     public Vector2i add(Vector2i v, ref Vector2i dest) {
415         dest.x = x + v.x;
416         dest.y = y + v.y;
417         return dest;
418     }
419 
420     /**
421      * Increment the components of this vector by the given values.
422      *
423      * @param x
424      *          the x component to add
425      * @param y
426      *          the y component to add
427      * @return this
428      */
429     ref public Vector2i add(int x, int y) return {
430         this.x = this.x + x;
431         this.y = this.y + y;
432         return this;
433     }
434 
435     public Vector2i add(int x, int y, ref Vector2i dest) {
436         dest.x = this.x + x;
437         dest.y = this.y + y;
438         return dest;
439     }
440 
441     /**
442      * Multiply all components of this {@link Vector2i} by the given scalar
443      * value.
444      * 
445      * @param scalar
446      *          the scalar to multiply this vector by
447      * @return this
448      */
449     ref public Vector2i mul(int scalar) return {
450         this.x = x * scalar;
451         this.y = y * scalar;
452         return this;
453     }
454 
455     public Vector2i mul(int scalar, ref Vector2i dest) {
456         dest.x = x * scalar;
457         dest.y = y * scalar;
458         return dest;
459     }
460 
461     /**
462      * Add the supplied vector by this one.
463      *
464      * @param v
465      *          the vector to multiply
466      * @return this
467      */
468     ref public Vector2i mul(Vector2i v) return {
469         this.x = x * v.x;
470         this.y = y * v.y;
471         return this;
472     }
473 
474     public Vector2i mul(Vector2i v, ref Vector2i dest) {
475         dest.x = x * v.x;
476         dest.y = y * v.y;
477         return dest;
478     }
479 
480     /**
481      * Multiply the components of this vector by the given values.
482      *
483      * @param x
484      *          the x component to multiply
485      * @param y
486      *          the y component to multiply
487      * @return this
488      */
489     ref public Vector2i mul(int x, int y) return {
490         this.x = this.x * x;
491         this.y = this.y * y;
492         return this;
493     }
494 
495     public Vector2i mul(int x, int y, ref Vector2i dest) {
496         dest.x = this.x * x;
497         dest.y = this.y * y;
498         return dest;
499     }
500 
501     /**
502      * Divide all components of this {@link Vector2i} by the given scalar value.
503      *
504      * @param scalar
505      *          the scalar to divide by
506      * @return a vector holding the result
507      */
508     public Vector2i div(double scalar) {
509         double invscalar = 1.0f / scalar;
510         this.x = cast(int) (x * invscalar);
511         this.y = cast(int) (y * invscalar);
512         return this;
513     }
514 
515     public Vector2i div(double scalar, ref Vector2i dest) {
516         double invscalar = 1.0f / scalar;
517         dest.x = cast(int) (x * invscalar);
518         dest.y = cast(int) (y * invscalar);
519         return dest;
520     }
521 
522     /**
523      * Divide all components of this {@link Vector2i} by the given scalar value.
524      *
525      * @param scalar
526      *          the scalar to divide by
527      * @return a vector holding the result
528      */
529     public Vector2i div(int scalar) {
530         this.x = x / scalar;
531         this.y = y / scalar;
532         return this;
533     }
534 
535     public Vector2i div(int scalar, ref Vector2i dest) {
536         dest.x = x / scalar;
537         dest.y = y / scalar;
538         return dest;
539     }
540     
541     /**
542      * Set all components to zero.
543      *
544      * @return this
545      */
546     ref public Vector2i zero() return {
547         this.x = 0;
548         this.y = 0;
549         return this;
550     }
551 
552 
553     /**
554      * Negate this vector.
555      *
556      * @return this
557      */
558     ref public Vector2i negate() return {
559         this.x = -x;
560         this.y = -y;
561         return this;
562     }
563 
564     public Vector2i negate(ref Vector2i dest) {
565         dest.x = -x;
566         dest.y = -y;
567         return dest;
568     }
569 
570     /**
571      * Set the components of this vector to be the component-wise minimum of this and the other vector.
572      *
573      * @param v
574      *          the other vector
575      * @return this
576      */
577     ref public Vector2i min(Vector2i v) return {
578         this.x = x < v.x ? x : v.x;
579         this.y = y < v.y ? y : v.y;
580         return this;
581     }
582 
583     public Vector2i min(Vector2i v, ref Vector2i dest) {
584         dest.x = x < v.x ? x : v.x;
585         dest.y = y < v.y ? y : v.y;
586         return dest;
587     }
588 
589     /**
590      * Set the components of this vector to be the component-wise maximum of this and the other vector.
591      *
592      * @param v
593      *          the other vector
594      * @return this
595      */
596     ref public Vector2i max(Vector2i v) return {
597         this.x = x > v.x ? x : v.x;
598         this.y = y > v.y ? y : v.y;
599         return this;
600     }
601 
602     public Vector2i max(Vector2i v, ref Vector2i dest) {
603         dest.x = x > v.x ? x : v.x;
604         dest.y = y > v.y ? y : v.y;
605         return dest;
606     }
607 
608     public int maxComponent() {
609         int absX = Math.abs(x);
610         int absY = Math.abs(y);
611         if (absX >= absY)
612             return 0;
613         return 1;
614     }
615 
616     public int minComponent() {
617         int absX = Math.abs(x);
618         int absY = Math.abs(y);
619         if (absX < absY)
620             return 0;
621         return 1;
622     }
623 
624     /**
625      * Set <code>this</code> vector's components to their respective absolute values.
626      * 
627      * @return this
628      */
629     ref public Vector2i absolute() return {
630         this.x = Math.abs(this.x);
631         this.y = Math.abs(this.y);
632         return this;
633     }
634 
635     public Vector2i absolute(ref Vector2i dest) {
636         dest.x = Math.abs(this.x);
637         dest.y = Math.abs(this.y);
638         return dest;
639     }
640 
641     public int hashCode() {
642         immutable int prime = 31;
643         int result = 1;
644         result = prime * result + x;
645         result = prime * result + y;
646         return result;
647     }
648 
649 
650     public bool equals(int x, int y) {
651         if (this.x != x)
652             return false;
653         if (this.y != y)
654             return false;
655         return true;
656     }
657 
658     public bool equals(Vector2i other) {
659         if (this.x != other.x)
660             return false;
661         if (this.y != other.y)
662             return false;
663         return true;
664     }
665 
666 }