78efbdaf74d4bc1f228ab69ab24cd032cf6d62c7
[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     public Point3D clone() {
62         return new Point3D(this);
63     }
64
65     /**
66      * Copy coordinates from other point to current point. Value of other point will not be changed.
67      */
68     public Point3D clone(final Point3D otherPoint) {
69         x = otherPoint.x;
70         y = otherPoint.y;
71         z = otherPoint.z;
72         return this;
73     }
74
75     /**
76      * Set current point coordinates to the middle point between two other points.
77      *
78      * @param p1 first point.
79      * @param p2 second point.
80      * @return current point.
81      */
82     public Point3D computeMiddlePoint(final Point3D p1, final Point3D p2) {
83         x = (p1.x + p2.x) / 2d;
84         y = (p1.y + p2.y) / 2d;
85         z = (p1.z + p2.z) / 2d;
86         return this;
87     }
88
89     /**
90      * @return true if current point coordinates are equal to zero.
91      */
92     public boolean isZero() {
93         return (x == 0) && (y == 0) && (z == 0);
94     }
95
96     public double getAngleXZ(final Point3D anotherPoint) {
97         return Math.atan2(x - anotherPoint.x, z - anotherPoint.z);
98     }
99
100     public double getAngleYZ(final Point3D anotherPoint) {
101         return Math.atan2(y - anotherPoint.y, z - anotherPoint.z);
102     }
103
104     public double getAngleXY(final Point3D anotherPoint) {
105         return Math.atan2(x - anotherPoint.x, y - anotherPoint.y);
106     }
107
108     /**
109      * Compute distance to another point.
110      *
111      * @param anotherPoint point to compute distance to.
112      * @return distance to another point.
113      */
114     public double getDistanceTo(final Point3D anotherPoint) {
115         final double xDelta = x - anotherPoint.x;
116         final double yDelta = y - anotherPoint.y;
117         final double zDelta = z - anotherPoint.z;
118
119         return sqrt(((xDelta * xDelta) + (yDelta * yDelta) + (zDelta * zDelta)));
120     }
121
122     /**
123      * @return length of current vector.
124      */
125     public double getVectorLength() {
126         return sqrt(((x * x) + (y * y) + (z * z)));
127     }
128
129     /**
130      * Invert current point coordinates.
131      *
132      * @return current point.
133      */
134     public Point3D invert() {
135         x = -x;
136         y = -y;
137         z = -z;
138         return this;
139     }
140
141     /**
142      * Rotate current point around center point by angleXZ and angleYZ.
143      * <p>
144      * See also: <a href="https://marctenbosch.com/quaternions/">Let's remove Quaternions from every 3D Engine</a>
145      *
146      * @param center   center point.
147      * @param angleXZ angle around XZ axis.
148      * @param angleYZ angle around YZ axis.
149      */
150     public Point3D rotate(final Point3D center, final double angleXZ,
151                        final double angleYZ) {
152         final double s1 = sin(angleXZ);
153         final double c1 = cos(angleXZ);
154
155         final double s2 = sin(angleYZ);
156         final double c2 = cos(angleYZ);
157
158         x -= center.x;
159         y -= center.y;
160         z -= center.z;
161
162         final double y1 = (z * s2) + (y * c2);
163         final double z1 = (z * c2) - (y * s2);
164
165         final double x1 = (z1 * s1) + (x * c1);
166         final double z2 = (z1 * c1) - (x * s1);
167
168         x = x1 + center.x;
169         y = y1 + center.y;
170         z = z2 + center.z;
171
172         return this;
173     }
174
175     /**
176      * Round current point coordinates to integer values.
177      */
178     public void roundToInteger() {
179         x = (int) x;
180         y = (int) y;
181         z = (int) z;
182     }
183
184     /**
185      * Scale down current point by factor.
186      * All coordinates will be divided by factor.
187      *
188      * @param factor factor to scale by.
189      * @return current point.
190      */
191     public Point3D scaleDown(final double factor) {
192         x /= factor;
193         y /= factor;
194         z /= factor;
195         return this;
196     }
197
198     /**
199      * Scale up current point by factor.
200      * All coordinates will be multiplied by factor.
201      *
202      * @param factor factor to scale by.
203      * @return current point.
204      */
205     public Point3D scaleUp(final double factor) {
206         x *= factor;
207         y *= factor;
208         z *= factor;
209         return this;
210     }
211
212     /**
213      * Set current point coordinates to given values.
214      * @param x X coordinate.
215      * @param y Y coordinate.
216      * @param z Z coordinate.
217      */
218     public void setValues(final double x, final double y, final double z) {
219         this.x = x;
220         this.y = y;
221         this.z = z;
222     }
223
224     /**
225      * Subtract other point from current point. Value of other point will not be changed.
226      *
227      * @return current point.
228      */
229     public Point3D subtract(final Point3D otherPoint) {
230         x -= otherPoint.x;
231         y -= otherPoint.y;
232         z -= otherPoint.z;
233         return this;
234     }
235
236     @Override
237     public String toString() {
238         return "x:" + x + " y:" + y + " z:" + z;
239     }
240
241     /**
242      * Translate current point along X axis by given increment.
243      *
244      * @return current point.
245      */
246     public Point3D translateX(final double xIncrement) {
247         x += xIncrement;
248         return this;
249     }
250
251     /**
252      * Translate current point along Y axis by given increment.
253      *
254      * @return current point.
255      */
256     public Point3D translateY(final double yIncrement) {
257         y += yIncrement;
258         return this;
259     }
260
261     /**
262      * Translate current point along Z axis by given increment.
263      *
264      * @return current point.
265      */
266     public Point3D translateZ(final double zIncrement) {
267         z += zIncrement;
268         return this;
269     }
270
271     /**
272      * Here we assume that Z coordinate is distance to the viewer.
273      * If Z is positive, then point is in front of the viewer, and therefore it is visible.
274      *
275      * @return point visibility status.
276      */
277     public boolean isVisible() {
278         return z > 0;
279     }
280
281     /**
282      * Resets point coordinates to zero along all axes.
283      *
284      * @return current point.
285      */
286     public Point3D zero() {
287         x = 0;
288         y = 0;
289         z = 0;
290         return this;
291     }
292
293 }