Updated readability of the code.
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / geometry / Point3D.java
1 /*
2  * Sixth 3D engine. Author: Svjatoslav Agejenko. 
3  * This project is released under Creative Commons Zero (CC0) license.
4  */
5 package eu.svjatoslav.sixth.e3d.geometry;
6
7 import static java.lang.Math.*;
8
9 /**
10  * Used to represent point in a 3D space or vector.
11  */
12
13 public class Point3D implements Cloneable {
14
15     // coordinates
16     public double x, y, z;
17
18     public Point3D() {
19     }
20
21     public Point3D(final double x, final double y, final double z) {
22         this.x = x;
23         this.y = y;
24         this.z = z;
25     }
26
27     public Point3D(final float x, final float y, final float z) {
28         this.x = x;
29         this.y = y;
30         this.z = z;
31     }
32
33     public Point3D(final int x, final int y, final int z) {
34         this.x = x;
35         this.y = y;
36         this.z = z;
37     }
38
39     /**
40      * Creates new current point by cloning coordinates from parent point.
41      */
42     public Point3D(final Point3D parent) {
43         x = parent.x;
44         y = parent.y;
45         z = parent.z;
46     }
47
48     /**
49      * Add other point to current point. Value of other point will not be changed.
50      *
51      * @param otherPoint point to add.
52      * @return current point.
53      */
54     public Point3D add(final Point3D otherPoint) {
55         x += otherPoint.x;
56         y += otherPoint.y;
57         z += otherPoint.z;
58         return this;
59     }
60
61     /**
62      * Add coordinates of current point to other point. Value of current point will not be changed.
63      * @return current point.
64      */
65     public Point3D addTo(final Point3D ... otherPoints) {
66         for (final Point3D otherPoint : otherPoints) otherPoint.add(this);
67         return this;
68     }
69
70     /**
71      * Create new point by cloning position of current point.
72      *
73      * @return newly created clone.
74      */
75     public Point3D clone() {
76         return new Point3D(this);
77     }
78
79     /**
80      * Copy coordinates from other point to current point. Value of other point will not be changed.
81      */
82     public Point3D clone(final Point3D otherPoint) {
83         x = otherPoint.x;
84         y = otherPoint.y;
85         z = otherPoint.z;
86         return this;
87     }
88
89     /**
90      * Set current point coordinates to the middle point between two other points.
91      *
92      * @param p1 first point.
93      * @param p2 second point.
94      * @return current point.
95      */
96     public Point3D computeMiddlePoint(final Point3D p1, final Point3D p2) {
97         x = (p1.x + p2.x) / 2d;
98         y = (p1.y + p2.y) / 2d;
99         z = (p1.z + p2.z) / 2d;
100         return this;
101     }
102
103     /**
104      * @return true if current point coordinates are equal to zero.
105      */
106     public boolean isZero() {
107         return (x == 0) && (y == 0) && (z == 0);
108     }
109
110     public double getAngleXZ(final Point3D anotherPoint) {
111         return Math.atan2(x - anotherPoint.x, z - anotherPoint.z);
112     }
113
114     public double getAngleYZ(final Point3D anotherPoint) {
115         return Math.atan2(y - anotherPoint.y, z - anotherPoint.z);
116     }
117
118     public double getAngleXY(final Point3D anotherPoint) {
119         return Math.atan2(x - anotherPoint.x, y - anotherPoint.y);
120     }
121
122     /**
123      * Compute distance to another point.
124      *
125      * @param anotherPoint point to compute distance to.
126      * @return distance to another point.
127      */
128     public double getDistanceTo(final Point3D anotherPoint) {
129         final double xDelta = x - anotherPoint.x;
130         final double yDelta = y - anotherPoint.y;
131         final double zDelta = z - anotherPoint.z;
132
133         return sqrt(((xDelta * xDelta) + (yDelta * yDelta) + (zDelta * zDelta)));
134     }
135
136     /**
137      * @return length of current vector.
138      */
139     public double getVectorLength() {
140         return sqrt(((x * x) + (y * y) + (z * z)));
141     }
142
143     /**
144      * Invert current point coordinates.
145      *
146      * @return current point.
147      */
148     public Point3D invert() {
149         x = -x;
150         y = -y;
151         z = -z;
152         return this;
153     }
154
155     /**
156      * Rotate current point around center point by angleXZ and angleYZ.
157      * <p>
158      * See also: <a href="https://marctenbosch.com/quaternions/">Let's remove Quaternions from every 3D Engine</a>
159      *
160      * @param center   center point.
161      * @param angleXZ angle around XZ axis.
162      * @param angleYZ angle around YZ axis.
163      */
164     public Point3D rotate(final Point3D center, final double angleXZ,
165                        final double angleYZ) {
166         final double s1 = sin(angleXZ);
167         final double c1 = cos(angleXZ);
168
169         final double s2 = sin(angleYZ);
170         final double c2 = cos(angleYZ);
171
172         x -= center.x;
173         y -= center.y;
174         z -= center.z;
175
176         final double y1 = (z * s2) + (y * c2);
177         final double z1 = (z * c2) - (y * s2);
178
179         final double x1 = (z1 * s1) + (x * c1);
180         final double z2 = (z1 * c1) - (x * s1);
181
182         x = x1 + center.x;
183         y = y1 + center.y;
184         z = z2 + center.z;
185
186         return this;
187     }
188
189     public Point3D rotate(final double angleXZ, final double angleYZ) {
190         return rotate(new Point3D(0, 0, 0), angleXZ, angleYZ);
191     }
192
193     /**
194      * Round current point coordinates to integer values.
195      */
196     public void roundToInteger() {
197         x = (int) x;
198         y = (int) y;
199         z = (int) z;
200     }
201
202     /**
203      * Scale down current point by factor.
204      * All coordinates will be divided by factor.
205      *
206      * @param factor factor to scale by.
207      * @return current point.
208      */
209     public Point3D scaleDown(final double factor) {
210         x /= factor;
211         y /= factor;
212         z /= factor;
213         return this;
214     }
215
216     /**
217      * Scale up current point by factor.
218      * All coordinates will be multiplied by factor.
219      *
220      * @param factor factor to scale by.
221      * @return current point.
222      */
223     public Point3D scaleUp(final double factor) {
224         x *= factor;
225         y *= factor;
226         z *= factor;
227         return this;
228     }
229
230     /**
231      * Set current point coordinates to given values.
232      * @param x X coordinate.
233      * @param y Y coordinate.
234      * @param z Z coordinate.
235      */
236     public void setValues(final double x, final double y, final double z) {
237         this.x = x;
238         this.y = y;
239         this.z = z;
240     }
241
242     /**
243      * Subtract other point from current point. Value of other point will not be changed.
244      *
245      * @return current point.
246      */
247     public Point3D subtract(final Point3D otherPoint) {
248         x -= otherPoint.x;
249         y -= otherPoint.y;
250         z -= otherPoint.z;
251         return this;
252     }
253
254     @Override
255     public String toString() {
256         return "x:" + x + " y:" + y + " z:" + z;
257     }
258
259     /**
260      * Translate current point along X axis by given increment.
261      *
262      * @return current point.
263      */
264     public Point3D translateX(final double xIncrement) {
265         x += xIncrement;
266         return this;
267     }
268
269     /**
270      * Translate current point along Y axis by given increment.
271      *
272      * @return current point.
273      */
274     public Point3D translateY(final double yIncrement) {
275         y += yIncrement;
276         return this;
277     }
278
279     /**
280      * Translate current point along Z axis by given increment.
281      *
282      * @return current point.
283      */
284     public Point3D translateZ(final double zIncrement) {
285         z += zIncrement;
286         return this;
287     }
288
289     /**
290      * Here we assume that Z coordinate is distance to the viewer.
291      * If Z is positive, then point is in front of the viewer, and therefore it is visible.
292      *
293      * @return point visibility status.
294      */
295     public boolean isVisible() {
296         return z > 0;
297     }
298
299     /**
300      * Resets point coordinates to zero along all axes.
301      *
302      * @return current point.
303      */
304     public Point3D zero() {
305         x = 0;
306         y = 0;
307         z = 0;
308         return this;
309     }
310
311 }