001/* 002 * SI Units 003 * Copyright (c) 2005-2016, Jean-Marie Dautelle, Werner Keil, V2COM. 004 * 005 * All rights reserved. 006 * 007 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 008 * 009 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 010 * 011 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 012 * 013 * 3. Neither the name of JSR-363 nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 014 * 015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 016 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 017 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 018 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 019 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 020 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 021 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 022 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 023 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 024 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 025 */ 026package si.uom; 027 028import javax.measure.Quantity; 029import javax.measure.Unit; 030import javax.measure.quantity.Acceleration; 031import javax.measure.quantity.Angle; 032import javax.measure.quantity.Area; 033import javax.measure.quantity.Dimensionless; 034import javax.measure.quantity.Energy; 035import javax.measure.quantity.Length; 036import javax.measure.quantity.Mass; 037 038import si.uom.quantity.Action; 039import si.uom.quantity.DynamicViscosity; 040import si.uom.quantity.ElectricPermittivity; 041import si.uom.quantity.IonizingRadiation; 042import si.uom.quantity.KinematicViscosity; 043import si.uom.quantity.Luminance; 044import si.uom.quantity.MagneticFieldStrength; 045import si.uom.quantity.MagneticPermeability; 046import si.uom.quantity.MagnetomotiveForce; 047import si.uom.quantity.WaveNumber; 048import tec.units.ri.AbstractSystemOfUnits; 049import tec.units.ri.AbstractUnit; 050import tec.units.ri.format.SimpleUnitFormat; 051import tec.units.ri.function.LogConverter; 052import tec.units.ri.function.MultiplyConverter; 053import tec.units.ri.function.PiMultiplierConverter; 054import tec.units.ri.function.RationalConverter; 055import tec.units.ri.unit.AlternateUnit; 056import tec.units.ri.unit.ProductUnit; 057import tec.units.ri.unit.TransformedUnit; 058import tec.units.ri.unit.Units; 059 060/** 061 * <p> This class defines all SI (Système International d'Unités) base units and 062 * derived units as well as units that are accepted for use with the 063 * SI units.</p> 064 * 065 * @see <a href="http://en.wikipedia.org/wiki/International_System_of_Units">Wikipedia: International System of Units</a> 066 * @see <a href="http://physics.nist.gov/cuu/Units/outside.html>Units outside the SI that are accepted for use with the SI</a> 067 * @see <a href="http://www.bipm.org/utils/common/pdf/si_brochure_8.pdf>SI 2006 - Official Specification</a> 068 * @see MetricPrefix 069 * 070 * @noextend This class is not intended to be extended by clients. 071 * 072 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> 073 * @author <a href="mailto:units@catmedia.us">Werner Keil</a> 074 * @version 1.0, October 7, 2016 075*/ 076public final class SI extends Units { 077 078 /** 079 * The singleton instance. 080 */ 081 private static final SI INSTANCE = new SI(); 082 083 /** 084 * Default constructor (prevents this class from being instantiated). 085 */ 086 private SI() { 087 } 088 089 /** 090 * Returns the singleton instance of this class. 091 * 092 * @return the metric system instance. 093 */ 094 public static SI getInstance() { 095 return INSTANCE; 096 } 097 098 //////////////////////////////// 099 // SI DERIVED ALTERNATE UNITS // 100 //////////////////////////////// 101 102 /** 103 * The SI unit for magnetomotive force (standard name <code>At</code>). 104 */ 105 public static final AlternateUnit<MagnetomotiveForce> AMPERE_TURN 106 = addUnit(new AlternateUnit<MagnetomotiveForce>(SI.AMPERE, "At"), 107 MagnetomotiveForce.class); 108 109 ////////////////////////////// 110 // SI DERIVED PRODUCT UNITS // 111 ////////////////////////////// 112 113 /** 114 * The SI unit for acceleration quantities (standard name <code>m/s2</code>). 115 */ 116 public static final Unit<Acceleration> METRES_PER_SQUARE_SECOND 117 = addUnit(new ProductUnit<Acceleration>( 118 METRES_PER_SECOND.divide(SECOND)), Acceleration.class); 119 120 /** 121 * The SI unit for action quantities (standard name <code>j.s</code>). 122 */ 123 public static final Unit<Action> JOULE_SECOND 124 = addUnit(new ProductUnit<Action>( 125 JOULE.multiply(SECOND)), Action.class); 126 127 /** 128 * The SI unit for electric permittivity (standard name <code>ε</code>, <code>F/m </code> or <code>F·m−1</code>). 129 * In electromagnetism, absolute permittivity is the measure of resistance 130 * that is encountered when forming an electric field in a medium. 131 */ 132 public static final Unit<ElectricPermittivity> FARADS_PER_METRE 133 = addUnit(new AlternateUnit<ElectricPermittivity>( 134 FARAD.divide(METRE), "ε"), ElectricPermittivity.class); 135 136 /** 137 * The SI unit for magnetic permeability quantities (standard name <code>N/A2</code>). 138 */ 139 public static final Unit<MagneticPermeability> NEWTONS_PER_SQUARE_AMPERE 140 = addUnit(new ProductUnit<MagneticPermeability>( 141 NEWTON.divide(AMPERE.pow(2))), MagneticPermeability.class); 142 143 /** 144 * The SI unit for wave number quantities (standard name <code>1/m</code>). 145 */ 146 public static final Unit<WaveNumber> RECIPROCAL_METRE 147 = addUnit(new ProductUnit<WaveNumber>( 148 METRE.pow(-1)), WaveNumber.class); 149 150 /** 151 * The SI unit for dynamic viscosity quantities (standard name <code>Pa.s</code>). 152 */ 153 public static final Unit<DynamicViscosity> PASCAL_SECOND 154 = addUnit(new ProductUnit<DynamicViscosity>( 155 PASCAL.multiply(SECOND)), DynamicViscosity.class); 156 157 /** 158 * Luminance is a photometric measure of the luminous intensity per unit area of light travelling in a given 159 * direction. It describes the amount of light that passes through, is emitted or reflected from a particular 160 * area, and falls within a given solid angle. The SI unit for luminance is candela per square metre (<code>cd/m2</code>). 161 * @see <a href="https://en.wikipedia.org/wiki/Luminance"> 162 * Wikipedia: Luminance</a> 163 */ 164 public static final Unit<Luminance> CANDELA_PER_SQUARE_METRE 165 = addUnit(new ProductUnit<Luminance>( 166 CANDELA.divide(SQUARE_METRE)), Luminance.class); 167 168 /** 169 * The SI unit for kinematic viscosity quantities (standard name <code>m2/s"</code>). 170 */ 171 public static final Unit<KinematicViscosity> SQUARE_METRES_PER_SECOND 172 = addUnit(new ProductUnit<KinematicViscosity>( 173 SQUARE_METRE.divide(SECOND)), KinematicViscosity.class); 174 175 /** 176 * The SI unit for magnetic field strength quantities (standard name <code>A/m"</code>). 177 */ 178 public static final Unit<MagneticFieldStrength> AMPERES_PER_METRE 179 = addUnit(new ProductUnit<MagneticFieldStrength>( 180 AMPERE.divide(METRE)), MagneticFieldStrength.class); 181 182 /** 183 * The SI unit for ionizing radiation quantities (standard name <code>C/kg"</code>). 184 */ 185 public static final Unit<IonizingRadiation> COULOMBS_PER_KILOGRAM 186 = addUnit(new ProductUnit<IonizingRadiation>( 187 COULOMB.divide(KILOGRAM)), IonizingRadiation.class); 188 189 ///////////////////////////////////////////////////////////////// 190 // Units outside the SI that are accepted for use with the SI. // 191 ///////////////////////////////////////////////////////////////// 192 193 /** 194 * An angle unit accepted for use with SI units (standard name <code>deg/code>). 195 */ 196 public static final Unit<Angle> DEGREE_ANGLE 197 = new TransformedUnit<Angle>(RADIAN, new PiMultiplierConverter().concatenate(new RationalConverter(1, 180))); 198 199 /** 200 * An angle unit accepted for use with SI units (standard name <code>'/code>). 201 */ 202 public static final Unit<Angle> MINUTE_ANGLE 203 = new TransformedUnit<Angle>(RADIAN, new PiMultiplierConverter().concatenate(new RationalConverter(1, 180 * 60))); 204 205 /** 206 * An angle unit accepted for use with SI units (standard name <code>''</code>). 207 */ 208 public static final Unit<Angle> SECOND_ANGLE 209 = new TransformedUnit<Angle>(RADIAN, new PiMultiplierConverter().concatenate(new RationalConverter(1, 180 * 60 * 60))); 210 211 /** 212 * A mass unit accepted for use with SI units (standard name <code>t</code>). 213 */ 214 public static final Unit<Mass> TONNE 215 = AbstractSystemOfUnits.Helper.addUnit(INSTANCE.units, 216 new TransformedUnit<Mass>(KILOGRAM, new RationalConverter(1000, 1)), 217 "Tonne", "t"); 218 /** 219 * A dimensionless unit accepted for use with SI units (standard name <code>Np</code>). 220 * Although the neper is coherent with SI units and is accepted by the CIPM, 221 * it has not been adopted by the General Conference on Weights and Measures 222 * (CGPM, Conférence Générale des Poids et Mesures) and is thus not an SI unit. 223 */ 224 public static final Unit<Dimensionless> NEPER 225 = new TransformedUnit<Dimensionless>(AbstractUnit.ONE, new LogConverter(E).inverse()); 226 227 /** 228 * A dimensionless unit accepted for use with SI units (standard name <code>B</code>). 229 * The bel is most commonly used with the SI prefix deci: 1 dB = 0.1 B 230 */ 231 public static final Unit<Dimensionless> BEL 232 = addUnit(new TransformedUnit<Dimensionless>(AbstractUnit.ONE, new LogConverter(10).inverse())); 233 234 /** 235 * An energy unit accepted for use with SI units (standard name <code>eV</code>). 236 * The electronvolt is the kinetic energy acquired by an electron passing 237 * through a potential difference of 1 V in vacuum. 238 * The value must be obtained by experiment, and is therefore not known exactly. 239 */ 240 public static final Unit<Energy> ELECTRON_VOLT 241 = new TransformedUnit<Energy>(JOULE, new MultiplyConverter(1.602176487E-19)); 242 // CODATA 2006 - http://physics.nist.gov/cuu/Constants/codata.pdf 243 244 /** 245 * A mass unit accepted for use with SI units (standard name <code>u</code>). 246 * The unified atomic mass unit is equal to 1/12 of the mass of an unbound 247 * atom of the nuclide 12C, at rest and in its ground state. The value must 248 * be obtained by experiment, and is therefore not known exactly. 249 */ 250 public static final Unit<Mass> UNIFIED_ATOMIC_MASS 251 = new TransformedUnit<Mass>(KILOGRAM, new MultiplyConverter(1.660538782E-27)); 252 // CODATA 2006 - http://physics.nist.gov/cuu/Constants/codata.pdf 253 254 /** 255 * A length unit accepted for use with SI units (standard name <code>UA</code>). 256 * The astronomical unit is a unit of length. Its value is such that, 257 * when used to describe the motion of bodies in the solar system, 258 * the heliocentric gravitation constant is (0.017 202 098 95)2 ua3·d-2. 259 * The value must be obtained by experiment, and is therefore not known exactly. 260 */ 261 public static final Unit<Length> ASTRONOMICAL_UNIT 262 = addUnit(new TransformedUnit<Length>(METRE, new MultiplyConverter(149597871000.0))); 263 // Best estimate source: http://maia.usno.navy.mil/NSFA/CBE.html 264 265 /** 266 * An angle unit accepted for use with SI units (standard name <code>rev</code>). 267 */ 268 public static final Unit<Angle> REVOLUTION 269 = new TransformedUnit<Angle>(RADIAN, new PiMultiplierConverter().concatenate(new RationalConverter(2, 1))); 270 271 /** 272 * An angle unit accepted for use with SI units (standard name <code>ha</code>). 273 */ 274 public static final Unit<Area> HECTARE 275 = new TransformedUnit<Area>(SQUARE_METRE, new RationalConverter(10000, 1)); 276 277 ///////////////////// 278 // Collection View // 279 ///////////////////// 280 281 @Override 282 public String getName() { 283 return "SI"; 284 } 285 286 /** 287 * Adds a new unit not mapped to any specified quantity type. 288 * 289 * @param unit the unit being added. 290 * @return <code>unit</code>. 291 */ 292 private static <U extends Unit<?>> U addUnit(U unit) { 293 INSTANCE.units.add(unit); 294 return unit; 295 } 296 297 /** 298 * Adds a new unit not mapped to any specified quantity type and puts a text 299 * as symbol or label. 300 * 301 * @param unit 302 * the unit being added. 303 * @param name 304 * the string to use as name 305 * @param text 306 * the string to use as label or symbol 307 * @param isLabel 308 * if the string should be used as a label or not 309 * @return <code>unit</code>. 310 */ 311 private static <U extends Unit<?>> U addUnit(U unit, String name, 312 String text, boolean isLabel) { 313 if (isLabel) { 314 SimpleUnitFormat.getInstance().label(unit, text); 315 } 316 if (name != null && unit instanceof AbstractUnit) { 317 return Helper.addUnit(INSTANCE.units, unit, name); 318 } else { 319 INSTANCE.units.add(unit); 320 } 321 return unit; 322 } 323 324 /** 325 * Adds a new unit not mapped to any specified quantity type and puts a text 326 * as symbol or label. 327 * 328 * @param unit 329 * the unit being added. 330 * @param text 331 * the string to use as label or symbol 332 * @param isLabel 333 * if the string should be used as a label or not 334 * @return <code>unit</code>. 335 */ 336 @SuppressWarnings("unused") 337 private static <U extends Unit<?>> U addUnit(U unit, String text, 338 boolean isLabel) { 339 return addUnit(unit, null, text, isLabel); 340 } 341 342 /** 343 * Adds a new unit and maps it to the specified quantity type. 344 * 345 * @param unit the unit being added. 346 * @param type the quantity type. 347 * @return <code>unit</code>. 348 */ 349 private static <U extends AbstractUnit<?>> U addUnit(U unit, Class<? extends Quantity<?>> type) { 350 INSTANCE.units.add(unit); 351 INSTANCE.quantityToUnit.put(type, unit); 352 return unit; 353 } 354}