001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.openimaj.math.geometry.point;
031
032import java.io.DataInput;
033import java.io.DataOutput;
034import java.io.IOException;
035import java.io.PrintWriter;
036import java.util.Scanner;
037
038import Jama.Matrix;
039
040/**
041 * Simple concrete implementation of a three dimensional point.
042 *
043 * @author Jonathon Hare
044 */
045public class Point3dImpl implements Point3d, Cloneable {
046        /**
047         * The x-ordinate
048         */
049        public double x;
050
051        /**
052         * The y-ordinate
053         */
054        public double y;
055
056        /**
057         * The z-ordinate
058         */
059        public double z;
060
061        /**
062         * Construct a Point3dImpl with the given (x, y, z) coordinates
063         *
064         * @param x
065         *            x-ordinate
066         * @param y
067         *            y-ordinate
068         * @param z
069         *            z-ordinate
070         */
071        public Point3dImpl(double x, double y, double z)
072        {
073                this.x = x;
074                this.y = y;
075                this.z = z;
076        }
077
078        /**
079         * Construct a Point3dImpl with the given (x, y, z) coordinates packed into
080         * an array
081         *
082         * @param array
083         *            the coordinates ([x, y, z])
084         */
085        public Point3dImpl(double[] array)
086        {
087                this.x = array[0];
088                this.y = array[1];
089                this.z = array[2];
090        }
091
092        /**
093         * Construct a Point3dImpl with the (x,y,z) coordinates given via another
094         * point.
095         *
096         * @param p
097         *            The point to copy from.
098         */
099        public Point3dImpl(Point3d p)
100        {
101                this.copyFrom(p);
102        }
103
104        /**
105         * Construct a Point3dImpl at the origin.
106         */
107        public Point3dImpl()
108        {
109                // do nothing
110        }
111
112        @Override
113        public double getX() {
114                return x;
115        }
116
117        @Override
118        public void setX(double x) {
119                this.x = x;
120        }
121
122        @Override
123        public double getY() {
124                return y;
125        }
126
127        @Override
128        public void setY(double y) {
129                this.y = y;
130        }
131
132        @Override
133        public double getZ() {
134                return z;
135        }
136
137        @Override
138        public void setZ(double z) {
139                this.z = z;
140        }
141
142        @Override
143        public void copyFrom(Point3d p)
144        {
145                this.x = p.getX();
146                this.y = p.getY();
147                this.z = p.getZ();
148        }
149
150        @Override
151        public String toString() {
152                return "(" + x + "," + y + "," + z + ")";
153        }
154
155        @Override
156        public Point3dImpl clone() {
157                Point3dImpl clone;
158                try {
159                        clone = (Point3dImpl) super.clone();
160                } catch (final CloneNotSupportedException e) {
161                        return null;
162                }
163                return clone;
164        }
165
166        @Override
167        public Double getOrdinate(int dimension) {
168                if (dimension == 0)
169                        return x;
170                if (dimension == 1)
171                        return y;
172                return z;
173        }
174
175        @Override
176        public int getDimensions() {
177                return 3;
178        }
179
180        @Override
181        public void translate(double x, double y, double z) {
182                this.x += x;
183                this.y += y;
184                this.z += z;
185        }
186
187        @Override
188        public void translate(Point3d v) {
189                this.x += v.getX();
190                this.y += v.getY();
191                this.z += v.getZ();
192        }
193
194        @Override
195        public Point3dImpl transform(Matrix transform) {
196                if (transform.getRowDimension() == 4) {
197                        double xt = transform.get(0, 0) * getX() + transform.get(0, 1) * getY() + transform.get(0, 2) * getZ()
198                                        + transform.get(0, 3);
199                        double yt = transform.get(1, 0) * getX() + transform.get(1, 1) * getY() + transform.get(1, 2) * getZ()
200                                        + transform.get(1, 3);
201                        double zt = transform.get(2, 0) * getX() + transform.get(2, 1) * getY() + transform.get(2, 2) * getZ()
202                                        + transform.get(2, 3);
203                        final double ft = transform.get(3, 0) * getX() + transform.get(3, 1) * getY() + transform.get(3, 2) * getZ()
204                                        + transform.get(3, 3);
205
206                        xt /= ft;
207                        yt /= ft;
208                        zt /= ft;
209
210                        return new Point3dImpl(xt, yt, zt);
211                }
212                throw new IllegalArgumentException("Transform matrix has unexpected size");
213        }
214
215        @Override
216        public boolean equals(Object o) {
217                if (!(o instanceof Point3d))
218                        return false;
219                final Point3d p = (Point3d) o;
220                return p.getX() == this.x && p.getY() == this.y && p.getZ() == this.getZ();
221        }
222
223        @Override
224        public int hashCode()
225        {
226                return toString().hashCode();
227        }
228
229        @Override
230        public Point3d minus(Point3d a) {
231                return new Point3dImpl(this.x - a.getX(), this.y - a.getY(), this.z - a.getZ());
232        }
233
234        @Override
235        public void readASCII(Scanner in) throws IOException {
236                x = in.nextDouble();
237                y = in.nextDouble();
238                z = in.nextDouble();
239        }
240
241        @Override
242        public String asciiHeader() {
243                return "Point3d";
244        }
245
246        @Override
247        public void readBinary(DataInput in) throws IOException {
248                x = in.readDouble();
249                y = in.readDouble();
250                z = in.readDouble();
251        }
252
253        @Override
254        public byte[] binaryHeader() {
255                return "PT3D".getBytes();
256        }
257
258        @Override
259        public void writeASCII(PrintWriter out) throws IOException {
260                out.format("%f %f %f", x, y, z);
261        }
262
263        @Override
264        public void writeBinary(DataOutput out) throws IOException {
265                out.writeDouble(x);
266                out.writeDouble(y);
267                out.writeDouble(z);
268        }
269
270        @Override
271        public Point3dImpl copy() {
272                return clone();
273        }
274
275        /**
276         * Create a random point in ([0..1], [0..1], [0..1]).
277         *
278         * @return random point.
279         */
280        public static Point3d createRandomPoint() {
281                return new Point3dImpl(Math.random(), Math.random(), Math.random());
282        }
283
284        @Override
285        public void setOrdinate(int dimension, Number value) {
286                if (dimension == 0)
287                        x = value.floatValue();
288                if (dimension == 1)
289                        y = value.floatValue();
290                if (dimension == 2)
291                        z = value.floatValue();
292        }
293}