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