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