001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * Icy is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.type.point;
020
021import java.awt.Point;
022import java.awt.geom.Point2D;
023
024/**
025 * Point4D class.<br>
026 * Incomplete implementation (work in progress...)
027 * 
028 * @author Stephane
029 */
030public abstract class Point4D implements Cloneable
031{
032    /**
033     * Returns the X coordinate of this <code>Point4D</code> in <code>double</code> precision.
034     * 
035     * @return the X coordinate of this <code>Point4D</code>.
036     */
037    public abstract double getX();
038
039    /**
040     * Returns the Y coordinate of this <code>Point4D</code> in <code>double</code> precision.
041     * 
042     * @return the Y coordinate of this <code>Point4D</code>.
043     */
044    public abstract double getY();
045
046    /**
047     * Returns the Z coordinate of this <code>Point4D</code> in <code>double</code> precision.
048     * 
049     * @return the Z coordinate of this <code>Point4D</code>.
050     */
051    public abstract double getZ();
052
053    /**
054     * Returns the T coordinate of this <code>Point4D</code> in <code>double</code> precision.
055     * 
056     * @return the T coordinate of this <code>Point4D</code>.
057     */
058    public abstract double getT();
059
060    /**
061     * Sets the X coordinate of this <code>Point4D</code> in <code>double</code> precision.
062     */
063    public abstract void setX(double x);
064
065    /**
066     * Sets the Y coordinate of this <code>Point4D</code> in <code>double</code> precision.
067     */
068    public abstract void setY(double y);
069
070    /**
071     * Sets the Z coordinate of this <code>Point4D</code> in <code>double</code> precision.
072     */
073    public abstract void setZ(double z);
074
075    /**
076     * Sets the T coordinate of this <code>Point4D</code> in <code>double</code> precision.
077     */
078    public abstract void setT(double t);
079
080    /**
081     * Sets the location of this <code>Point4D</code> to the
082     * specified <code>double</code> coordinates.
083     * 
084     * @param x
085     *        the new X coordinate of this {@code Point4D}
086     * @param y
087     *        the new Y coordinate of this {@code Point4D}
088     * @param z
089     *        the new Z coordinate of this {@code Point4D}
090     * @param t
091     *        the new T coordinate of this {@code Point4D}
092     */
093    public void setLocation(double x, double y, double z, double t)
094    {
095        setX(x);
096        setY(y);
097        setZ(z);
098        setT(t);
099    }
100
101    /**
102     * Sets the location of this <code>Point4D</code> to the same
103     * coordinates as the specified <code>Point4D</code> object.
104     * 
105     * @param p
106     *        the specified <code>Point4D</code> to which to set
107     *        this <code>Point4D</code>
108     */
109    public void setLocation(Point4D p)
110    {
111        setLocation(p.getX(), p.getY(), p.getZ(), p.getT());
112    }
113
114    /**
115     * Convert to 2D point
116     */
117    public abstract Point2D toPoint2D();
118
119    /**
120     * Convert to 3D point
121     */
122    public abstract Point3D toPoint3D();
123
124    @Override
125    public boolean equals(Object obj)
126    {
127        if (obj instanceof Point4D)
128        {
129            final Point4D pt = (Point4D) obj;
130            return (getX() == pt.getX()) && (getY() == pt.getY()) && (getZ() == pt.getZ()) && (getT() == pt.getT());
131        }
132
133        return super.equals(obj);
134    }
135
136    /**
137     * Creates a new object of the same class as this object.
138     * 
139     * @return a clone of this instance.
140     * @exception OutOfMemoryError
141     *            if there is not enough memory.
142     * @see java.lang.Cloneable
143     */
144    @Override
145    public Object clone()
146    {
147        try
148        {
149            return super.clone();
150        }
151        catch (CloneNotSupportedException e)
152        {
153            // this shouldn't happen, since we are Cloneable
154            throw new InternalError();
155        }
156    }
157
158    @Override
159    public String toString()
160    {
161        return getClass().getName() + "[" + getX() + "," + getY() + "," + getZ() + "," + getT() + "]";
162    }
163
164    public static class Double extends Point4D
165    {
166        /**
167         * Create an array of Point4D.Double from the input double array.<br>
168         * <br>
169         * The format of the input array should be as follow:<br>
170         * <code>input.lenght</code> = number of point * 4.<br>
171         * <code>input[(pt * 4) + 0]</code> = X coordinate for point <i>pt</i><br>
172         * <code>input[(pt * 4) + 1]</code> = Y coordinate for point <i>pt</i><br>
173         * <code>input[(pt * 4) + 2]</code> = Z coordinate for point <i>pt</i><br>
174         * <code>input[(pt * 4) + 3]</code> = T coordinate for point <i>pt</i><br>
175         */
176        public static Point4D.Double[] toPoint4D(double[] input)
177        {
178            final Point4D.Double[] result = new Point4D.Double[input.length / 4];
179
180            int pt = 0;
181            for (int i = 0; i < input.length; i += 4)
182                result[pt++] = new Point4D.Double(input[i + 0], input[i + 1], input[i + 2], input[i + 3]);
183
184            return result;
185        }
186
187        /**
188         * Create an array of double from the input Point4D.Double array.<br>
189         * <br>
190         * The format of the output array is as follow:<br>
191         * <code>result.lenght</code> = number of point * 4.<br>
192         * <code>result[(pt * 4) + 0]</code> = X coordinate for point <i>pt</i><br>
193         * <code>result[(pt * 4) + 1]</code> = Y coordinate for point <i>pt</i><br>
194         * <code>result[(pt * 4) + 2]</code> = Z coordinate for point <i>pt</i><br>
195         * <code>result[(pt * 4) + 3]</code> = T coordinate for point <i>pt</i><br>
196         */
197        public static double[] toDoubleArray(Point4D.Double[] input)
198        {
199            final double[] result = new double[input.length * 4];
200
201            int off = 0;
202            for (Point4D.Double pt : input)
203            {
204                result[off++] = pt.x;
205                result[off++] = pt.y;
206                result[off++] = pt.z;
207                result[off++] = pt.t;
208            }
209
210            return result;
211        }
212
213        public double x;
214        public double y;
215        public double z;
216        public double t;
217
218        public Double(double x, double y, double z, double t)
219        {
220            super();
221
222            this.x = x;
223            this.y = y;
224            this.z = z;
225            this.t = t;
226        }
227
228        public Double(double[] xyzt)
229        {
230            final int len = xyzt.length;
231
232            if (len > 0)
233                this.x = xyzt[0];
234            if (len > 1)
235                this.y = xyzt[1];
236            if (len > 2)
237                this.z = xyzt[2];
238            if (len > 3)
239                this.t = xyzt[3];
240        }
241
242        public Double()
243        {
244            this(0, 0, 0, 0);
245        }
246
247        @Override
248        public double getX()
249        {
250            return x;
251        }
252
253        @Override
254        public void setX(double x)
255        {
256            this.x = x;
257        }
258
259        @Override
260        public double getY()
261        {
262            return y;
263        }
264
265        @Override
266        public void setY(double y)
267        {
268            this.y = y;
269        }
270
271        @Override
272        public double getZ()
273        {
274            return z;
275        }
276
277        @Override
278        public void setZ(double z)
279        {
280            this.z = z;
281        }
282
283        @Override
284        public double getT()
285        {
286            return t;
287        }
288
289        @Override
290        public void setT(double t)
291        {
292            this.t = t;
293        }
294
295        @Override
296        public void setLocation(double x, double y, double z, double t)
297        {
298            this.x = x;
299            this.y = y;
300            this.z = z;
301            this.t = t;
302        }
303
304        @Override
305        public Point2D toPoint2D()
306        {
307            return new Point2D.Double(x, y);
308        }
309
310        @Override
311        public Point3D toPoint3D()
312        {
313            return new Point3D.Double(x, y, z);
314        }
315
316    }
317
318    public static class Float extends Point4D
319    {
320        /**
321         * Create an array of Point4D.Float from the input float array.<br>
322         * <br>
323         * The format of the input array should be as follow:<br>
324         * <code>input.lenght</code> = number of point * 4.<br>
325         * <code>input[(pt * 4) + 0]</code> = X coordinate for point <i>pt</i><br>
326         * <code>input[(pt * 4) + 1]</code> = Y coordinate for point <i>pt</i><br>
327         * <code>input[(pt * 4) + 2]</code> = Z coordinate for point <i>pt</i><br>
328         * <code>input[(pt * 4) + 3]</code> = T coordinate for point <i>pt</i><br>
329         */
330        public static Point4D.Float[] toPoint4D(float[] input)
331        {
332            final Point4D.Float[] result = new Point4D.Float[input.length / 4];
333
334            int pt = 0;
335            for (int i = 0; i < input.length; i += 4)
336                result[pt++] = new Point4D.Float(input[i + 0], input[i + 1], input[i + 2], input[i + 3]);
337
338            return result;
339        }
340
341        /**
342         * Create an array of float from the input Point4D.Float array.<br>
343         * <br>
344         * The format of the output array is as follow:<br>
345         * <code>result.lenght</code> = number of point * 4.<br>
346         * <code>result[(pt * 4) + 0]</code> = X coordinate for point <i>pt</i><br>
347         * <code>result[(pt * 4) + 1]</code> = Y coordinate for point <i>pt</i><br>
348         * <code>result[(pt * 4) + 2]</code> = Z coordinate for point <i>pt</i><br>
349         * <code>result[(pt * 4) + 3]</code> = T coordinate for point <i>pt</i><br>
350         */
351        public static float[] toFloatArray(Point4D.Float[] input)
352        {
353            final float[] result = new float[input.length * 4];
354
355            int off = 0;
356            for (Point4D.Float pt : input)
357            {
358                result[off++] = pt.x;
359                result[off++] = pt.y;
360                result[off++] = pt.z;
361                result[off++] = pt.t;
362            }
363
364            return result;
365        }
366
367        public float x;
368        public float y;
369        public float z;
370        public float t;
371
372        public Float(float x, float y, float z, float t)
373        {
374            super();
375
376            this.x = x;
377            this.y = y;
378            this.z = z;
379            this.t = t;
380        }
381
382        public Float(float[] xyzt)
383        {
384            final int len = xyzt.length;
385
386            if (len > 0)
387                this.x = xyzt[0];
388            if (len > 1)
389                this.y = xyzt[1];
390            if (len > 2)
391                this.z = xyzt[2];
392            if (len > 3)
393                this.t = xyzt[3];
394        }
395
396        public Float()
397        {
398            this(0, 0, 0, 0);
399        }
400
401        @Override
402        public double getX()
403        {
404            return x;
405        }
406
407        @Override
408        public void setX(double x)
409        {
410            this.x = (float) x;
411        }
412
413        @Override
414        public double getY()
415        {
416            return y;
417        }
418
419        @Override
420        public void setY(double y)
421        {
422            this.y = (float) y;
423        }
424
425        @Override
426        public double getZ()
427        {
428            return z;
429        }
430
431        @Override
432        public void setZ(double z)
433        {
434            this.z = (float) z;
435        }
436
437        @Override
438        public double getT()
439        {
440            return t;
441        }
442
443        @Override
444        public void setT(double t)
445        {
446            this.t = (float) t;
447        }
448
449        @Override
450        public void setLocation(double x, double y, double z, double t)
451        {
452            this.x = (float) x;
453            this.y = (float) y;
454            this.z = (float) z;
455            this.t = (float) t;
456        }
457
458        @Override
459        public Point2D toPoint2D()
460        {
461            return new Point2D.Float(x, y);
462        }
463
464        @Override
465        public Point3D toPoint3D()
466        {
467            return new Point3D.Float(x, y, z);
468        }
469
470    }
471
472    public static class Integer extends Point4D
473    {
474        /**
475         * Create an array of Point4D.Integer from the input integer array.<br>
476         * <br>
477         * The format of the input array should be as follow:<br>
478         * <code>input.lenght</code> = number of point * 4.<br>
479         * <code>input[(pt * 4) + 0]</code> = X coordinate for point <i>pt</i><br>
480         * <code>input[(pt * 4) + 1]</code> = Y coordinate for point <i>pt</i><br>
481         * <code>input[(pt * 4) + 2]</code> = Z coordinate for point <i>pt</i><br>
482         * <code>input[(pt * 4) + 3]</code> = T coordinate for point <i>pt</i><br>
483         */
484        public static Point4D.Integer[] toPoint4D(int[] input)
485        {
486            final Point4D.Integer[] result = new Point4D.Integer[input.length / 4];
487
488            int pt = 0;
489            for (int i = 0; i < input.length; i += 4)
490                result[pt++] = new Point4D.Integer(input[i + 0], input[i + 1], input[i + 2], input[i + 3]);
491
492            return result;
493        }
494
495        /**
496         * Create an array of integer from the input Point4D.Integer array.<br>
497         * <br>
498         * The format of the output array is as follow:<br>
499         * <code>result.lenght</code> = number of point * 4.<br>
500         * <code>result[(pt * 4) + 0]</code> = X coordinate for point <i>pt</i><br>
501         * <code>result[(pt * 4) + 1]</code> = Y coordinate for point <i>pt</i><br>
502         * <code>result[(pt * 4) + 2]</code> = Z coordinate for point <i>pt</i><br>
503         * <code>result[(pt * 4) + 3]</code> = T coordinate for point <i>pt</i><br>
504         */
505        public static int[] toIntegerArray(Point4D.Integer[] input)
506        {
507            final int[] result = new int[input.length * 4];
508
509            int off = 0;
510            for (Point4D.Integer pt : input)
511            {
512                result[off++] = pt.x;
513                result[off++] = pt.y;
514                result[off++] = pt.z;
515                result[off++] = pt.t;
516            }
517
518            return result;
519        }
520
521        public int x;
522        public int y;
523        public int z;
524        public int t;
525
526        public Integer(int x, int y, int z, int t)
527        {
528            super();
529
530            this.x = x;
531            this.y = y;
532            this.z = z;
533            this.t = t;
534        }
535
536        public Integer(int[] xyzt)
537        {
538            final int len = xyzt.length;
539
540            if (len > 0)
541                this.x = xyzt[0];
542            if (len > 1)
543                this.y = xyzt[1];
544            if (len > 2)
545                this.z = xyzt[2];
546            if (len > 3)
547                this.t = xyzt[3];
548        }
549
550        public Integer()
551        {
552            this(0, 0, 0, 0);
553        }
554
555        @Override
556        public double getX()
557        {
558            return x;
559        }
560
561        @Override
562        public void setX(double x)
563        {
564            this.x = (int) x;
565        }
566
567        @Override
568        public double getY()
569        {
570            return y;
571        }
572
573        @Override
574        public void setY(double y)
575        {
576            this.y = (int) y;
577        }
578
579        @Override
580        public double getZ()
581        {
582            return z;
583        }
584
585        @Override
586        public void setZ(double z)
587        {
588            this.z = (int) z;
589        }
590
591        @Override
592        public double getT()
593        {
594            return t;
595        }
596
597        @Override
598        public void setT(double t)
599        {
600            this.t = (int) t;
601        }
602
603        @Override
604        public void setLocation(double x, double y, double z, double t)
605        {
606            this.x = (int) x;
607            this.y = (int) y;
608            this.z = (int) z;
609            this.t = (int) t;
610        }
611
612        @Override
613        public Point2D toPoint2D()
614        {
615            return new Point(x, y);
616        }
617
618        @Override
619        public Point3D toPoint3D()
620        {
621            return new Point3D.Integer(x, y, z);
622        }
623    }
624}