001/*
002 *   Coordinate3D -- A three element vector of Parameter objects representing a 3D coordinate.
003 *
004 *   Copyright (C) 2008-2015, by Joseph A. Huwaldt.
005 *   All rights reserved.
006 *   
007 *   This library is free software; you can redistribute it and/or
008 *   modify it under the terms of the GNU Lesser General Public
009 *   License as published by the Free Software Foundation; either
010 *   version 2 of the License, or (at your option) any later version.
011 *   
012 *   This library is distributed in the hope that it will be useful,
013 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
014 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015 *   Lesser General Public License for more details.
016 *
017 *   You should have received a copy of the GNU Lesser General Public License
018 *   along with this program; if not, write to the Free Software
019 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
020 *   Or visit:  http://www.gnu.org/licenses/lgpl.html
021 */
022package jahuwaldt.js.param;
023
024import jahuwaldt.tools.math.MathTools;
025import javax.measure.quantity.Dimensionless;
026import javax.measure.quantity.Quantity;
027import javolution.lang.ValueType;
028
029/**
030 * This class represents a 3 element vector of {@link Parameter} elements representing a
031 * geometrical coordinate.
032 * 
033 * <p> Modified by: Joseph A. Huwaldt </p>
034 * 
035 * @author Joseph A. Huwaldt, Date: November 21, 2008
036 * @version November 4, 2015
037 *
038 * @param <Q> The Quantity (unit type, such as Length or Volume) of this parameter.
039 */
040public abstract class Coordinate3D<Q extends Quantity> extends
041        AbstractParamVector<Q, Coordinate3D<Q>> implements ValueType {
042
043    /**
044     * Returns the number of elements held by this vector. This implementation always
045     * returns a value of 3.
046     *
047     * @return this vector dimension.
048     */
049    @Override
050    public int getDimension() {
051        return 3;
052    }
053
054    /**
055     * Compares this Coordinate3D against the specified Coordinate3D for approximate
056     * equality (a Coordinate3D object with Vector3D values equal to this one to within
057     * the numerical roundoff tolerance).
058     *
059     * @param obj the Coordinate3D object to compare with.
060     * @return <code>true</code> if this Coordinate3D is approximately identical to that
061     *         Coordinate3D; <code>false</code> otherwise.
062     */
063    public boolean isApproxEqual(Coordinate3D<?> obj) {
064        if (this == obj)
065            return true;
066        if (obj == null)
067            return false;
068
069        //  Check for approximate equality of Vector3D's.
070        try {
071            Vector3D<Q> thisV3D = this.toVector3D();
072            Vector3D<Q> thatV3D = obj.to(this.getUnit()).toVector3D();
073            for (int i = 0; i < 3; ++i) {
074                double thisVal = thisV3D.getValue(i);
075                double thatVal = thatV3D.getValue(i);
076                double eps2 = MathTools.epsilon(thisVal) * 10;
077                double eps = (eps2 > Parameter.EPS10 ? eps2 : Parameter.EPS10);
078                if (!MathTools.isApproxEqual(thisVal, thatVal, eps))
079                    return false;
080            }
081        } catch (Exception e) {
082            return false;
083        }
084
085        return true;
086    }
087
088    /**
089     * Compares this Coordinate3D for approximate equality to zero (all the values are
090     * within the numerical roundoff error of zero).
091     *
092     * @return <code>true</code> if this Coordinate3D is approximately equal to zero;
093     *         <code>false</code> otherwise.
094     */
095    public boolean isApproxZero() {
096
097        Vector3D<Q> thisV3D = this.toVector3D();
098        for (int i = 0; i < 3; ++i) {
099            double thisVal = thisV3D.getValue(i);
100            if (MathTools.isApproxZero(thisVal))
101                return false;
102        }
103
104        return true;
105    }
106
107    /**
108     * Casts this Coordinate3D to a parameterized unit of specified nature or throw a
109     * <code>ClassCastException</code> if the dimension of the specified quantity and this
110     * parameter's unit dimension do not match.
111     *
112     * @param <R>  The Quantity (unit type) to cast this parameter as.
113     * @param type the quantity class identifying the nature of the unit.
114     * @return this AbstractParamVector parameterized with the specified type.
115     * @throws ClassCastException if the dimension of this parameter's unit is different
116     * from the specified quantity dimension.
117     * @throws UnsupportedOperationException if the specified quantity class does not have
118     * a public static field named "UNIT" holding the standard unit for the quantity.
119     */
120    public abstract <R extends Quantity> Coordinate3D<R> asType(Class<R> type) throws ClassCastException;
121
122    /**
123     * Returns this vector converted to a unit vector with a vector magnitude of 1.0.
124     *
125     * @return this vector converted to a unit vector
126     */
127    public abstract Coordinate3D<Dimensionless> toUnitVector();
128
129}