/* * Units - Temporary implementation for Geotools 2 * Copyright (C) 1998 University Corporation for Atmospheric Research (Unidata) * 1998 Bill Hibbard & al. (VisAD) * 1999 Pêches et Océans Canada * 2000 Institut de Recherche pour le Développement * 2002 Centre for Computational Geography * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details (http://www.gnu.org/). * * * This package is inspired from the units package of VisAD. * Unidata and Visad's work is fully acknowledged here. * * THIS IS A TEMPORARY CLASS * * This is a placeholder for future Unit class. * This skeleton will be removed when the real classes from * JSR-108: Units specification will be publicly available. */ package org.geotools.units; // Divers import org.geotools.resources.i18n.ErrorKeys; import org.geotools.resources.i18n.Errors; /** * Classe représentant une unité dérivée de zero, un ou plusieurs unités fondamentales. * Les unités fondamentales sont définies par la classe {@link BaseUnit}. Elles représentent par * exemple des mesures de longueurs (m) ou de temps (s). Les objets de la classe DerivedUnit * combinent ensemble quelques unités fondamentales pour créer par exemple des unités de vitesses (m/s). * * @version 1.0 * @author Steven R. Emmerson * @author Bill Hibbard * @author Martin Desruisseaux * * @deprecated Replaced by the {@link javax.units.Unit} framework. */ /*public*/ final class DerivedUnit extends SimpleUnit { /** * Serial number for interoperability with different versions. */ private static final long serialVersionUID = -4476414709268904273L; /** * Unité sans dimensions. Cette * unité n'aura aucun symbole. */ static final Unit DIMENSIONLESS=new DerivedUnit().intern(); /** * Tableau d'unités fondamentales avec leur exposant (par exemple m²). Les différentes * méthodes de la classe DerivedUnit doivent s'assurer qu'une même unité * n'apparaît pas deux fois dans ce tableau, et qu'aucune unité n'a un exposant de 0. */ private final Factor[] factors; /** * Construit une unité sans dimension. */ private DerivedUnit() {this("dimensionless", "", null, new Factor[0]);} /** * Construit une unité dérivée avec le tableau * d'unités fondamentales spécifié ainsi qu'un * certain symbole. * * @param factors Tableau d'unités fondamentales avec leurs * exposants. Ce tableau sera supposé déjà simplifié, * c'est-à-dire que la même unité fondamentale n'y * apparait pas deux fois et aucun exposant n'est 0. */ private DerivedUnit(final Factor[] factors) { super(null, UnitFormat.DEFAULT.format(factors, new StringBuffer()).toString(), null); this.factors=factors; } /** * Construit une unité dérivée avec le tableau * d'unités fondamentales spécifié ainsi qu'un * certain symbole. * * @param quantityName Nom de la quantité (exemple: "Speed"). * @param symbol Symbole de cette unité dérivée. Ce symbole * ne doit pas être nul. * @param prefix Liste des préfix qui peuvent être placés devant le symbole * symbol, ou null s'il n'y en a pas. Cette * liste sera prise en compte par la méthode {@link #scale}. * @param factors Tableau d'unités fondamentales avec leurs * exposants. Ce tableau sera supposé déjà simplifié, * c'est-à-dire que la même unité fondamentale n'y * apparait pas deux fois et aucun exposant n'est 0. */ private DerivedUnit(final String quantityName, final String symbol, final PrefixSet prefix, final Factor[] factors) { super(quantityName, symbol, prefix); this.factors=factors; } /** * Construit une unité dérivée avec le tableau d'unités fondamentales spécifié. Un symbole par défaut * sera attribué. Ce symbole ne sera pas nécessairement le plus approprié. Par exemple le symbole * "kg*m²/s²" pourrait être créé à la place de "J" pour les unités d'énergie. */ public static SimpleUnit getInstance(final Factor[] factors) { return getInstance(null, null, null, factors); } /** * Crée une nouvelle unité dérivée de une ou plusieurs unités de bases. * Par exemple si SECOND est une unité de base mesurant * le temps en secondes et METRE une unité de base pour les * distances, alors on pourrait créer une unité de vitesse avec le code * suivant: * *
     *  Unit METRE_PER_SECOND=DerivedUnit.getInstance("speed", "m/s", null, new Factor[]
     *  {
     *      Factor.getFactor(METRE,  +1),
     *      Factor.getFactor(SECOND, -1)
     *  });
     * 
* * @param quantityName Nom de la quantité (exemple: "Speed"). * @param symbol Le symbole qui représentera cette unité dérivée * (par exemple "J" pour les joules). Si nul, alors un symbole * par défaut sera créé. Par exemple le symbole "kg*m²/s²" * pourrait être créé à la place de "J" pour les unités d'énergie. * @param prefix Liste des préfix qui peuvent être placés devant le symbole * symbol, ou null s'il n'y en a pas. Cette * liste sera prise en compte par la méthode {@link #scale}. * @param factors Liste des unités de bases ainsi que de * leurs exposants qui composeront l'unité dérivées. * Les éléments nuls ainsi que ceux qui ont un exposant * de 0 seront ignorés. * @return Une nouvelle unité dérivées. S'il existait déjà * une unité dérivée qui répondait aux spécifications, * celle-ci sera retournée. Il est possible que cette * méthode retourne un objet {@link BaseUnit} au lieu * d'un objet {@link DerivedUnit}, si une telle * simplification était possible. * * @see BaseUnit#getInstance * @see ScaledUnit#getInstance * @see OffsetUnit#getInstance */ public static SimpleUnit getInstance(final String quantityName, final String symbol, final PrefixSet prefix, Factor[] factors) { /* * Construit un tableau de facteurs dans lequel les doublons auront été fusionnés. * Le tableau retourné sera toujours une copie du tableau original, de sorte que * son contenu ne sera pas affecté par d'éventuels changements du tableau original. */ Factor[] oldFactors=factors; factors=new Factor[oldFactors.length]; System.arraycopy(oldFactors, 0, factors, 0, factors.length); for (int i=0; i=0;) { final Factor fi=oldFactors[i]; if (fi!=null && fi.power!=0) { factors[--length]=fi; } } } /* * Maintenant que le tableau factors a * été simplifié, construit des unités avec ce tableau. */ switch (factors.length) { case 0: return (SimpleUnit) DIMENSIONLESS; case 1: if (factors[0].power==1) return factors[0].baseUnit; } if (symbol!=null) { return (SimpleUnit) new DerivedUnit(quantityName, symbol, prefix, factors).intern(); } else { return (SimpleUnit) new DerivedUnit(factors).internIgnoreSymbol(); } } /** * Renvoie une unité identique à celle-ci, mais * avec un nouveau symbole et de nouveaux préfix. * * @param symbol Nouveau symbole représentant cette unité. Si ce * paramètre est nul, un symbole par défaut sera créé. * @param prefix Liste des préfix autorisés pour le symbole. * @return La même unité, mais avec le nouveau symbole. Peut être * this, mais ne sera jamais null. */ public Unit rename(final String symbol, final PrefixSet prefix) {// CAST return getInstance(quantityName, symbol, prefix, factors); } /** * Élève cette unité à une puissance entière. * * @param power La puissance à laquelle élever cette unité. * @return Les unités résultant de l'élévation des unités * this à la puissance power. * * @see #multiply * @see #divide * @see #scale * @see #shift */ public Unit pow(final int power) { switch (power) { case 0: return DIMENSIONLESS; case 1: return this; default: { final Factor[] newFactors=new Factor[factors.length]; for (int i=0; ithis à la puissance power. * @throws UnitException Si cette unité ne peut pas être élevée * à une puissance non-entière. */ public Unit pow(final double power) throws UnitException { final int integer=(int) power; if (integer==power) return pow(integer); final Factor[] newFactors=new Factor[factors.length]; for (int i=0; ithis par that. * @throws UnitException Si l'unité that est de la * classe {@link OffsetUnit} ou d'une autre classe invalide. * * @see #pow * @see #divide * @see #scale * @see #shift */ public Unit multiply(final Unit that) throws UnitException { return that.inverseMultiply(this); } /** * Multiply a base unit by a derived unit * (that*this). */ Unit inverseMultiply(final BaseUnit that) throws UnitException { return multiply(new Factor[] {Factor.getFactor(that, 1)}, factors, +1); } /** * Multiply a derived unit by another derived unit * (that*this). */ Unit inverseMultiply(final DerivedUnit that) throws UnitException { return that.multiply(factors); } /** * Retourne une unité qui résulte de la multiplication de * this par les facteurs f. */ final SimpleUnit multiply(final Factor[] f) { return multiply(factors, f, +1); } /** * Retourne une unité qui résulte de la multiplication des * facteurs f1 par les facteurs f2. */ private static SimpleUnit multiply(final Factor[] f1, final Factor[] f2, final int power2) { final Factor[] factors=new Factor[f1.length + f2.length]; System.arraycopy(f1, 0, factors, 0, f1.length); System.arraycopy(f2, 0, factors, f1.length, f2.length); switch (power2) { case +1: break; case -1: for (int i=f1.length; ithis par that. * @throws UnitException Si l'unité that est de la * classe {@link OffsetUnit} ou d'une autre classe invalide. * * @see #pow * @see #multiply * @see #scale * @see #shift */ public Unit divide(final Unit that) throws UnitException { return that.inverseDivide(this); } /** * Divide a base unit by a derived unit * (that/this). */ Unit inverseDivide(final BaseUnit that) throws UnitException { return multiply(new Factor[] {Factor.getFactor(that, 1)}, factors, -1); } /** * Divide a derived unit by another derived unit * (that/this). */ Unit inverseDivide(final DerivedUnit that) throws UnitException { return multiply(that.factors, factors, -1); } /** * Indicate whether or not this unit has the same dimensionality * or the reciprocal dimensionality as a base unit. Is is required * that this.compareDimensionality(that) give the same * result as that.compareDimensionality(this). * * @param that The base unit. * @return +1 if both units have the same dimensionality.
* -1 if the unit dimensionalities are reciprocals of * each other (for example length/time * and time/length). * 0 if the unit dimensionalities are neither the same * or reciprocals each other. */ private int compareDimensionality(final BaseUnit that) { if (factors.length==1) { final Factor factor=factors[0]; if (factor.baseUnit.equalsIgnoreSymbol(that)) { switch (factor.power) { case -1: return -1; case +1: return +1; } } } return 0; } /** * Indicate whether or not this unit has the same dimensionality * or the reciprocal dimensionality as a derived unit. Is is required * that this.compareDimensionality(that) give the same * result as that.compareDimensionality(this). * * @param that The derived unit. * @return +1 if both units have the same dimensionality.
* -1 if the unit dimensionalities are reciprocals of * each other (for example length/time * and time/length). * 0 if the unit dimensionalities are neither the same * or reciprocals each other. */ private int compareDimensionality(final DerivedUnit that) { int result=0; int count=that.factors.length; final Factor[] cmpFactors=new Factor[count]; System.arraycopy(that.factors, 0, cmpFactors, 0, count); loop: for (int i=0; ithis et that sont compatibles. * Si elles le sont, alors les méthodes convert ne lanceront jamais * d'exception pour ces unités. * * @param that Autre unités avec laquelle on veut * vérifier si ces unités sont compatibles. * @return true Si l'on garantie que les méthodes * convert ne lanceront pas d'exceptions. */ public boolean canConvert(final Unit that) {return that.canConvert(this);} // Do not move in superclass boolean canConvert(final BaseUnit that) {return compareDimensionality(that)!=0;} boolean canConvert(final DerivedUnit that) {return compareDimensionality(that)!=0;} /** * Effectue la conversion d'une mesure exprimée selon d'autres unités. Par * exemple METRE_PER_SECOND.convert(1, KILOMETRE_PER_HOUR) * retournera 0.2778. * * @param value La valeur exprimée selon les autres unités (fromUnit). * @param fromUnit Les autres unités. * @return La valeur convertie selon ces unités (this). * @throws UnitException Si les unités ne sont pas compatibles. */ public double convert(final double value, final Unit fromUnit) throws UnitException { return fromUnit.inverseConvert(value, this); // Do not move in superclass } double convert(final double value, final BaseUnit fromUnit) throws UnitException { switch (compareDimensionality(fromUnit)) { case -1: return 1/value; case +1: return value; default: throw incompatibleUnitsException(fromUnit); } } double convert(final double value, final DerivedUnit fromUnit) throws UnitException { switch (compareDimensionality(fromUnit)) { case -1: return 1/value; case +1: return value; default: throw incompatibleUnitsException(fromUnit); } } /** * Effectue sur-place la conversion de mesures exprimées selon d'autres * unités. Les valeurs converties remplaceront les anciennes valeurs. * * @param values En entré, les valeurs exprimées selon les autres unités * (fromUnit). En sortie, les valeurs exprimées selon ces * unités (this). * @param fromUnit Les autres unités. * @throws UnitException Si les unités ne sont pas compatibles. Dans ce * cas, aucun élément de values n'aura été modifié. */ public void convert(final double[] values, final Unit fromUnit) throws UnitException { fromUnit.inverseConvert(values, this); // Do not move in superclass } void convert(final double[] values, final BaseUnit fromUnit) throws UnitException { switch (compareDimensionality(fromUnit)) { case -1: for (int i=0; ifromUnit est de la classe {@link OffsetUnit}. * * @param values En entré, les valeurs exprimées selon les autres * unités (fromUnit). En sortie, les valeurs exprimées * selon ces unités (this). * @param fromUnit Les autres unités. * @throws UnitException Si les unités ne sont pas compatibles. Dans ce * cas, aucun élément de values n'aura été modifié. */ public void convert(final float[] values, final Unit fromUnit) throws UnitException { fromUnit.inverseConvert(values, this); // Do not move in superclass } void convert(final float[] values, final BaseUnit fromUnit) throws UnitException { switch (compareDimensionality(fromUnit)) { case -1: for (int i=0; ifromUnit * vers les unités this. Cette méthode ne * retourne jamais null. * @throws UnitException Si les unités ne sont pas compatibles. */ public UnitTransform getTransform(final Unit fromUnit) throws UnitException { return fromUnit.getInverseTransform(this); // Do not move in superclass } UnitTransform getTransform(final BaseUnit fromUnit) throws UnitException { switch (compareDimensionality(fromUnit)) { case -1: return InverseTransform .getInstance(fromUnit, this); case +1: return IdentityTransform .getInstance(fromUnit, this); default: throw this.incompatibleUnitsException(fromUnit); } } UnitTransform getTransform(final DerivedUnit fromUnit) throws UnitException { switch (compareDimensionality(fromUnit)) { case -1: return InverseTransform .getInstance(fromUnit, this); case +1: return IdentityTransform .getInstance(fromUnit, this); default: throw this.incompatibleUnitsException(fromUnit); } } /** * Convertit une mesure vers d'autre unités. Par exemple * METRE_PER_SECOND.inverseConvert(1, KILOMETRE_PER_HOUR) * retournera 3.6. Cette méthode est l'inverse de la méthode * {@link #convert(double,Unit)}. * * @param value La valeur exprimée selon ces unités (this). * @param toUnit Les autres unités. * @return La valeur convertie selon les autres unités (toUnit). * @throws UnitException Si les unités ne sont pas compatibles. */ protected double inverseConvert(final double value, final Unit toUnit) throws UnitException { return toUnit.convert(value, this); // Do not move in superclass } double inverseConvert(final double value, final BaseUnit toUnit) throws UnitException { switch (compareDimensionality(toUnit)) { case -1: return 1/value; case +1: return value; default: throw toUnit.incompatibleUnitsException(this); } } double inverseConvert(final double value, final DerivedUnit toUnit) throws UnitException { switch (compareDimensionality(toUnit)) { case -1: return 1/value; case +1: return value; default: throw toUnit.incompatibleUnitsException(this); } } /** * Effectue sur-place la conversion de mesures vers d'autres unités. * Les valeurs converties remplaceront les anciennes valeurs. Cette * méthode est l'inverse de la méthode {@link #convert(double[],Unit)}. * * @param values En entré, les valeur exprimées selon ces unités * (this). En sortie, les valeurs exprimées * selon les autres unités (toUnit). * @param toUnit Les autres unités. * @throws UnitException Si les unités ne sont pas compatibles. Dans ce * cas, aucun élément de values n'aura été modifié. */ protected void inverseConvert(final double[] values, final Unit toUnit) throws UnitException { toUnit.convert(values, this); // Do not move in superclass } void inverseConvert(final double[] values, final BaseUnit toUnit) throws UnitException { switch (compareDimensionality(toUnit)) { case -1: for (int i=0; ithis). En sortie, les valeurs exprimées * selon les autres unités (toUnit). * @param toUnit Les autres unités. * @throws UnitException Si les unités ne sont pas compatibles. Dans ce * cas, aucun élément de values n'aura été modifié. */ protected void inverseConvert(final float[] values, final Unit toUnit) throws UnitException { toUnit.convert(values, this); // Do not move in superclass } void inverseConvert(final float[] values, final BaseUnit toUnit) throws UnitException { switch (compareDimensionality(toUnit)) { case -1: for (int i=0; ithis * vers les unités toUnit. Cette méthode * ne retourne jamais null. * @throws UnitException Si les unités ne sont pas compatibles. */ protected UnitTransform getInverseTransform(final Unit toUnit) throws UnitException { return toUnit.getTransform(this); // Do not move in superclass } UnitTransform getInverseTransform(final BaseUnit toUnit) throws UnitException { switch (compareDimensionality(toUnit)) { case -1: return InverseTransform .getInstance(this, toUnit); case +1: return IdentityTransform .getInstance(this, toUnit); default: throw toUnit.incompatibleUnitsException(this); } } UnitTransform getInverseTransform(final DerivedUnit toUnit) throws UnitException { switch (compareDimensionality(toUnit)) { case -1: return InverseTransform .getInstance(this, toUnit); case +1: return IdentityTransform .getInstance(this, toUnit); default: throw toUnit.incompatibleUnitsException(this); } } /** * Indique si deux unités sont égales, en ignorant leurs symboles. Il n'est pas nécessaire que * les unités fondamentales y apparaissent dans le même ordre. Par exemple, "m²*s" sera considéré * identique à "s*m²". */ public boolean equalsIgnoreSymbol(final Unit unit) { return (unit instanceof DerivedUnit) && compareDimensionality((DerivedUnit) unit)==1; } /** * Retourne un code * pour cette unité. */ public int hashCode() { int code=92718538; for (int i=0; i