001/*
002 * Copyright 2006 - 2013
003 *     Stefan Balev     <stefan.balev@graphstream-project.org>
004 *     Julien Baudry    <julien.baudry@graphstream-project.org>
005 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
006 *     Yoann Pigné      <yoann.pigne@graphstream-project.org>
007 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
008 * 
009 * This file is part of GraphStream <http://graphstream-project.org>.
010 * 
011 * GraphStream is a library whose purpose is to handle static or dynamic
012 * graph, create them from scratch, file or any source and display them.
013 * 
014 * This program is free software distributed under the terms of two licenses, the
015 * CeCILL-C license that fits European law, and the GNU Lesser General Public
016 * License. You can  use, modify and/ or redistribute the software under the terms
017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
019 * the Free Software Foundation, either version 3 of the License, or (at your
020 * option) any later version.
021 * 
022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
024 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Lesser General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * 
029 * The fact that you are presently reading this means that you have had
030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
031 */
032package org.graphstream.ui.geom;
033
034/**
035 * 3D point.
036 * 
037 * A Point3 is a 3D location in an affine space described by three values along
038 * the X, the Y and the Z axis. Note the difference with Vector3 wich is defined
039 * as an array and ensures that the three coordinates X, Y and Z are consecutive
040 * in memory. Here there are three separate attributes. Further, a point has no
041 * vector arithmetic bound to it (to points cannot be added, this would have no
042 * mathematical meaning).
043 * 
044 * @author Antoine Dutot
045 * @since 19990829
046 * @version 0.1
047 */
048public class Point3 extends Point2 implements java.io.Serializable {
049        // Attributes
050
051        private static final long serialVersionUID = 5971336344439693816L;
052
053        /**
054         * Z axis value.
055         */
056        public double z;
057
058        // Attributes -- Shared
059
060        /**
061         * Specific point at (0,0,0).
062         */
063        public static final Point3 NULL_POINT3 = new Point3(0, 0, 0);
064
065        // Constructors
066
067        /**
068         * New 3D point at(0,0,0).
069         */
070        public Point3() {
071        }
072
073        /**
074         * New 3D point at (x,y,0).
075         */
076        public Point3(double x, double y) {
077                set(x, y, 0);
078        }
079
080        /**
081         * New 3D point at(x,y,z).
082         */
083        public Point3(double x, double y, double z) {
084                set(x, y, z);
085        }
086
087        /**
088         * New copy of other.
089         */
090        public Point3(Point3 other) {
091                copy(other);
092        }
093
094        public Point3(Vector3 vec) {
095                copy(vec);
096        }
097        
098        public Point3(float data[]) {
099                this(0, data);
100        }
101        
102        public Point3(double data[]) {
103                this(0, data);
104        }
105
106        public Point3(int start, float data[]) {
107                if(data != null) {
108                        if(data.length>start+0) x = data[start+0];
109                        if(data.length>start+1) y = data[start+1];
110                        if(data.length>start+2) z = data[start+2];
111                }
112        }
113        
114        public Point3(int start, double data[]) {
115                if(data != null) {
116                        if(data.length>start+0) x = data[start+0];
117                        if(data.length>start+1) y = data[start+1];
118                        if(data.length>start+2) z = data[start+2];
119                }
120        }
121
122        // Predicates
123
124        /**
125         * Are all components to zero?.
126         */
127        @Override
128        public boolean isZero() {
129                return (x == 0 && y == 0 && z == 0);
130        }
131
132        // /**
133        // * Is other equal to this ?
134        // */
135        // public boolean
136        // equals( const Point3 < double > & other ) const
137        // {
138        // return( x == other.x
139        // and y == other.y
140        // and z == other.z );
141        // }
142
143        /**
144         * Create a new point linear interpolation of this and <code>other</code>.
145         * The new point is located between this and <code>other</code> if
146         * <code>factor</code> is between 0 and 1 (0 yields this point, 1 yields the
147         * <code>other</code> point).
148         */
149        public Point3 interpolate(Point3 other, double factor) {
150                Point3 p = new Point3(x + ((other.x - x) * factor), y
151                                + ((other.y - y) * factor), z + ((other.z - z) * factor));
152
153                return p;
154        }
155
156        /**
157         * Distance between this and <code>other</code>.
158         */
159        public double distance(Point3 other) {
160                double xx = other.x - x;
161                double yy = other.y - y;
162                double zz = other.z - z;
163                return Math.abs(Math.sqrt((xx * xx) + (yy * yy) + (zz * zz)));
164        }
165
166        /**
167         * Distance between this and point (x,y,z).
168         */
169        public double distance(double x, double y, double z) {
170                double xx = x - this.x;
171                double yy = y - this.y;
172                double zz = z - this.z;
173                return Math.abs(Math.sqrt((xx * xx) + (yy * yy) + (zz * zz)));
174        }
175
176        // Commands
177
178        /**
179         * Make this a copy of other.
180         */
181        public void copy(Point3 other) {
182                x = other.x;
183                y = other.y;
184                z = other.z;
185        }
186
187        public void copy(Vector3 vec) {
188                x = vec.data[0];
189                y = vec.data[1];
190                z = vec.data[2];
191        }
192
193        /**
194         * Like #moveTo().
195         */
196        public void set(double x, double y, double z) {
197                this.x = x;
198                this.y = y;
199                this.z = z;
200        }
201
202        // Commands -- moving
203
204        /**
205         * Move to absolute position (x,y,z).
206         */
207        public void moveTo(double x, double y, double z) {
208                this.x = x;
209                this.y = y;
210                this.z = z;
211        }
212
213        /**
214         * Move of given vector(dx,dy,dz).
215         */
216        public void move(double dx, double dy, double dz) {
217                this.x += dx;
218                this.y += dy;
219                this.z += dz;
220        }
221
222        /**
223         * Move of given point <code>p</code>.
224         */
225        public void move(Point3 p) {
226                this.x += p.x;
227                this.y += p.y;
228                this.z += p.z;
229        }
230
231        /**
232         * Move of given vector d.
233         */
234        public void move(Vector3 d) {
235                this.x += d.data[0];
236                this.y += d.data[1];
237                this.z += d.data[2];
238        }
239
240        /**
241         * Move in depth of dz.
242         */
243        public void moveZ(double dz) {
244                z += dz;
245        }
246
247        /**
248         * Scale of factor (sx,sy,sz).
249         */
250        public void scale(double sx, double sy, double sz) {
251                x *= sx;
252                y *= sy;
253                z *= sz;
254        }
255
256        /**
257         * Scale by factor s.
258         */
259        public void scale(Point3 s) {
260                x *= s.x;
261                y *= s.y;
262                z *= s.z;
263        }
264
265        /**
266         * Scale by factor s.
267         */
268        public void scale(Vector3 s) {
269                x *= s.data[0];
270                y *= s.data[1];
271                z *= s.data[2];
272        }
273
274        /**
275         * Scale by a given scalar.
276         * 
277         * @param scalar
278         *            The multiplier.
279         */
280        public void scale(double scalar) {
281                x *= scalar;
282                y *= scalar;
283                z *= scalar;
284        }
285
286        /**
287         * Change only depth at absolute coordinate z.
288         */
289        public void setZ(double z) {
290                this.z = z;
291        }
292
293        /**
294         * Exchange the values of this and other.
295         */
296        public void swap(Point3 other) {
297                double t;
298
299                if (other != this) {
300                        t = this.x;
301                        this.x = other.x;
302                        other.x = t;
303
304                        t = this.y;
305                        this.y = other.y;
306                        other.y = t;
307
308                        t = this.z;
309                        this.z = other.z;
310                        other.z = t;
311                }
312        }
313
314        // Commands -- misc.
315
316        @Override
317        public String toString() {
318                StringBuffer buf;
319
320                buf = new StringBuffer("Point3[");
321
322                buf.append(x);
323                buf.append('|');
324                buf.append(y);
325                buf.append('|');
326                buf.append(z);
327                buf.append("]");
328
329                return buf.toString();
330        }
331}