1 /**
  2  * The Render Engine
  3  * Point3D
  4  *
  5  * @fileoverview A Point3D class
  6  *
  7  * @author: Brett Fattori (brettf@renderengine.com)
  8  * @author: $Author: bfattori $
  9  * @version: $Revision: 1555 $
 10  *
 11  * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com)
 12  *
 13  * Permission is hereby granted, free of charge, to any person obtaining a copy
 14  * of this software and associated documentation files (the "Software"), to deal
 15  * in the Software without restriction, including without limitation the rights
 16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 17  * copies of the Software, and to permit persons to whom the Software is
 18  * furnished to do so, subject to the following conditions:
 19  *
 20  * The above copyright notice and this permission notice shall be included in
 21  * all copies or substantial portions of the Software.
 22  *
 23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 26  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 28  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 29  * THE SOFTWARE.
 30  *
 31  */
 32 
 33 // The class this file defines and its required classes
 34 R.Engine.define({
 35     "class":"R.math.Point3D",
 36     "requires":[
 37         "R.math.PooledMathObject",
 38         "R.math.Math2D",
 39         "R.math.Point2D"
 40     ]
 41 });
 42 
 43 /**
 44  * @class A 3D point class with helpful methods for manipulation
 45  *
 46  * @param x {R.math.Point3D|Number} If this arg is a R.math.Point3D, its values will be
 47  *                           copied into the new point.
 48  * @param y {Number} The Y coordinate of the point.  Only required if X
 49  *                   was a number.
 50  * @param z {Number} The Z coordinate of the point.  Only required if X
 51  *                   was a number.
 52  * @constructor
 53  * @description Create a new 3D point.
 54  * @extends R.math.PooledMathObject
 55  */
 56 R.math.Point3D = function () {
 57     "use strict";
 58     return R.math.PooledMathObject.extend(/** @scope R.math.Point3D.prototype */{
 59 
 60         x:0,
 61         y:0,
 62         z:0,
 63         __POINT3D:true,
 64 
 65         /**
 66          * @private
 67          */
 68         constructor:function (x, y, z) {
 69             this.base("Point3D");
 70             this.__POINT3D = true;
 71             return this.set(x, y, z);
 72         },
 73 
 74         /**
 75          * Release the point back into the pool for reuse
 76          */
 77         release:function () {
 78             this.base();
 79             this.x = 0;
 80             this.y = 0;
 81             this.z = 0;
 82         },
 83 
 84         /**
 85          * Returns a simplified version of a R.math.Point3D.  The simplified version is
 86          * an array with three elements: X, Y, Z.
 87          * @return {Array}
 88          */
 89         simplify:function () {
 90             return [this.x, this.y, this.z];
 91         },
 92 
 93         /**
 94          * Returns <tt>true</tt> if this point is equal to the specified point.
 95          *
 96          * @param point {R.math.Point3D} The point to compare to
 97          * @return {Boolean} <tt>true</tt> if the two points are equal
 98          */
 99         equals:function (point) {
100             return this.x == point.x && this.y == point.y && this.z == point.z;
101         },
102 
103         /**
104          * Set the position of a 3D point.
105          *
106          * @param x {R.math.Point3D|Number|Array} If this arg is a R.math.Point3D, its values will be
107          *                           copied into the new point.
108          * @param y {Number} The Y coordinate of the point.  Only required if X
109          *                   was a number.
110          * @param z {Number} The Z coordinate of the point.  Only required if X
111          *                         was a number.
112          */
113         set:function (x, y, z) {
114             if (x.length && x.splice && x.shift) {
115                 // An array
116                 this.x = x[0];
117                 this.y = x[1];
118                 this.z = x[2];
119             }
120             else if (x.__POINT3D) {
121                 this.x = x.x;
122                 this.y = x.y;
123                 this.z = x.z;
124             }
125             else {
126                 AssertWarn((y != null), "Undefined Y value for point initialized to zero.");
127                 AssertWarn((z != null), "Undefined Z value for point initialized to zero.");
128                 this.x = x;
129                 this.y = y || 0;
130                 this.z = z || 0;
131             }
132             return this;
133         },
134 
135         /**
136          * Set the X coordinate.
137          *
138          * @param x {Number} The X coordinate
139          */
140         setX:function (x) {
141             this.x = x;
142         },
143 
144         /**
145          * Set the Y coordinate.
146          *
147          * @param y {Number} The Y coordinate
148          */
149         setY:function (y) {
150             this.y = y;
151         },
152 
153         /**
154          * Set the Z coordinate.
155          *
156          * @param z {Number} The Z coordinate
157          */
158         setZ:function (z) {
159             this.z = z;
160         },
161 
162         /**
163          * A method that mutates this point by adding the point to it.
164          *
165          * @param point {R.math.Point3D} A point
166          * @return {R.math.Point3D} This point
167          */
168         add:function (point) {
169             this.x += point.x;
170             this.y += point.y;
171             this.z += point.z;
172             return this;
173         },
174 
175         /**
176          * A mutator method that adds the scalar value to each component of this point.
177          * @param scalar {Number} A number
178          * @return {R.math.Point3D} This point
179          */
180         addScalar:function (scalar) {
181             this.x += scalar;
182             this.y += scalar;
183             this.z += scalar;
184             return this;
185         },
186 
187         /**
188          * A mutator method that subtracts the specified point from this point.
189          * @param point {R.math.Point3D} a point
190          * @return {R.math.Point3D} This point
191          */
192         sub:function (point) {
193             this.x -= point.x;
194             this.y -= point.y;
195             this.z -= point.z;
196             return this;
197         },
198 
199         /**
200          * A mutator method that multiplies the components of this point with another.
201          * @param point {R.math.Point3D} A point
202          * @return {R.math.Point3D} This point
203          */
204         convolve:function (point) {
205             this.x *= point.x;
206             this.y *= point.y;
207             this.z *= point.z;
208             return this;
209         },
210 
211         /**
212          * A mutator method that divides the components of this point by another.  The point
213          * cannot contain zeros for its components.
214          * @param point {R.math.Point3D} A point
215          * @return {R.math.Point3D} This point
216          */
217         convolveInverse:function (point) {
218             Assert((point.x != 0 && point.y != 0 && point.z != 0), "Division by zero in Point3D.convolveInverse");
219             this.x /= point.x;
220             this.y /= point.y;
221             this.z /= point.z;
222             return this;
223         },
224 
225         /**
226          * A mutator method that multiplies the components of this point by a scalar value.
227          * @param scalar {Number} A number
228          * @return {R.math.Point3D} This point
229          */
230         mul:function (scalar) {
231             this.x *= scalar;
232             this.y *= scalar;
233             this.z *= scalar;
234             return this;
235         },
236 
237         /**
238          * A mutator method that divides the components of this point by a scalar value.
239          * @param scalar {Number} A number - cannot be zero
240          * @return {R.math.Point3D} This point
241          */
242         div:function (scalar) {
243             Assert((scalar != 0), "Division by zero in Point3D.divScalar");
244             this.x /= scalar;
245             this.y /= scalar;
246             this.z /= scalar;
247             return this;
248         },
249 
250         /**
251          * A mutator method that negates this point, inversing it's components.
252          * @return {R.math.Point3D} This point
253          */
254         neg:function () {
255             this.x *= -1;
256             this.y *= -1;
257             this.z *= -1;
258             return this;
259         },
260 
261         /**
262          * Returns true if the point is the zero point.
263          * @return {Boolean} <tt>true</tt> if the point's elements are all zero.
264          */
265         isZero:function () {
266             return this.x == 0 && this.y == 0 && this.z == 0;
267         },
268 
269         /**
270          * Returns the distance between this and another point.
271          * @param point {R.math.Point3D} The point to compare against
272          * @return {Number} The distance between the two points
273          */
274         dist:function (point) {
275             return Math.sqrt((point.x - this.x) * (point.x - this.x) +
276                 (point.y - this.y) * (point.y - this.y) +
277                 (point.z - this.z) * (point.z - this.z));
278         },
279 
280         /**
281          * Returns a printable version of this object fixed to two decimal places.
282          * @return {String} Formatted as "x,y"
283          */
284         toString:function () {
285             return Number(this.x).toFixed(2) + "," + Number(this.y).toFixed(2) + "," + Number(this.z).toFixed(2);
286         }
287 
288     }, /** @scope R.math.Point3D.prototype */{
289         /**
290          * Return the classname of the this object
291          * @return {String} "R.math.Point3D"
292          */
293         getClassName:function () {
294             return "R.math.Point3D";
295         },
296 
297         /** @private */
298         resolved:function () {
299             R.math.Point3D.ZERO = R.math.Point3D.create(0, 0, 0);
300             if (Object.freeze) {
301                 Object.freeze(R.math.Point3D.ZERO);
302             }
303         },
304 
305         /**
306          * The "zero" point
307          * @type {R.math.Point3D}
308          * @memberOf R.math.Point3D
309          */
310         ZERO:null
311     });
312 };