1 package org.djunits.unit.scale; 2 3 /** 4 * Scale with factor and zero point offset. 5 * <p> 6 * A Scale for linear transformations with an offset that has to be applied first when converting to the standard (SI) unit, 7 * before the scaling takes place, e.g. for Temperature. As an example, transform from Degrees Fahrenheit to Kelvin (SI). The 8 * conversion is K = (F + 459.67) × 5⁄9, and F = K × 9⁄5 − 459.67. 9 * </p> 10 * <p> 11 * When we have an original scale with offset o1 and scalefactor f1, the calculation to the base unit is 12 * 13 * <pre> 14 * valueSI = (value1 + o1) * f1 15 * </pre> 16 * <p> 17 * So the offset is expressed in the "unit" of the value. As an example, when we transform degrees Fahrenheit to Kelvin, the 18 * factor is 5/9, and the offset is 459.67 (degrees Fahrenheit of 0 degrees Fahrenheit expressed in Kelvin). The formula 19 * becomes: K = (F + 459.67) * 5/9. So 0 F is 459.67 * 5/9 = 255.372 K. For Celcius to Kelvin, the scale factor is 1, and the 20 * offset 273.15. From Fahrenheit to Celcius, the offset is -32, and the factor is 5/9. 21 * </p> 22 * <p> 23 * When we apply a second offset transformation on a scale, e.g. from Fahrenheit to Celcius to Kelvin, this works as follows: If 24 * we combine a second scale factor for a derived unit with offset o2 and scalefactor f2, we need to calculate the ultimate 25 * scale to the base (si) unit. The factor then becomes: 26 * 27 * <pre> 28 * value1 = (value2 + o2) * f2 29 * valueSI = (value1 + o1) * f1 = value2 * (f1 * f2) + (f1 * f2 * o2 + f1 * o1) 30 * </pre> 31 * <p> 32 * as an example for F --2--> C --1--> K: o1 = 273.15, f1 = 1, o2 = -32, f2 = 5/9: <br> 33 * 110 F = 110*5/9 -32*5/9 + 273.15 = 316.483 K. 34 * </p> 35 * <p> 36 * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br> 37 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>. 38 * </p> 39 * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a> 40 * @author <a href="https://www.tudelft.nl/staff/p.knoppers/">Peter Knoppers</a> 41 */ 42 public class OffsetLinearScale extends LinearScale 43 { 44 /** */ 45 private static final long serialVersionUID = 20151011L; 46 47 /** The offset that has to be taken into account for conversions, multiplied by the conversionFactorToStandardUnit. */ 48 private final double offsetToStandardUnit; 49 50 /** 51 * Construct a Scale for linear transformations with an offset, e.g. for Temperature. 52 * @param conversionFactorToStandardUnit double; the conversion factor by which this number has to be multiplied to convert 53 * it to the standard (e.g., SI) unit. 54 * @param offsetToStandardUnit the offset that has to be taken into account for conversions; when converting to a standard 55 * unit, the offset is applied first. 56 */ 57 public OffsetLinearScale(final double conversionFactorToStandardUnit, final double offsetToStandardUnit) 58 { 59 super(conversionFactorToStandardUnit); 60 this.offsetToStandardUnit = offsetToStandardUnit; 61 } 62 63 /** {@inheritDoc} */ 64 @Override 65 public final double toStandardUnit(final double value) 66 { 67 return (value + this.offsetToStandardUnit) * getConversionFactorToStandardUnit(); 68 } 69 70 /** {@inheritDoc} */ 71 @Override 72 public final double fromStandardUnit(final double value) 73 { 74 return value / getConversionFactorToStandardUnit() - this.offsetToStandardUnit; 75 } 76 77 /** 78 * Retrieve the offset from the standard unit. 79 * @return double; the offset from the standard unit 80 */ 81 public final double getOffsetToStandardUnit() 82 { 83 return this.offsetToStandardUnit; 84 } 85 86 /** {@inheritDoc} */ 87 @Override 88 public boolean isBaseSIScale() 89 { 90 return super.isBaseSIScale() && this.offsetToStandardUnit == 0.0; 91 } 92 93 /** {@inheritDoc} */ 94 @Override 95 public int hashCode() 96 { 97 final int prime = 31; 98 int result = super.hashCode(); 99 long temp; 100 temp = Double.doubleToLongBits(this.offsetToStandardUnit); 101 result = prime * result + (int) (temp ^ (temp >>> 32)); 102 return result; 103 } 104 105 /** {@inheritDoc} */ 106 @SuppressWarnings("checkstyle:needbraces") 107 @Override 108 public boolean equals(final Object obj) 109 { 110 if (this == obj) 111 return true; 112 if (!super.equals(obj)) 113 return false; 114 if (getClass() != obj.getClass()) 115 return false; 116 OffsetLinearScale./org/djunits/unit/scale/OffsetLinearScale.html#OffsetLinearScale">OffsetLinearScale other = (OffsetLinearScale) obj; 117 if (Double.doubleToLongBits(this.offsetToStandardUnit) != Double.doubleToLongBits(other.offsetToStandardUnit)) 118 return false; 119 return true; 120 } 121 122 /** {@inheritDoc} */ 123 @Override 124 public String toString() 125 { 126 return "OffsetLinearScale [offsetToStandardUnit=" + this.offsetToStandardUnit + ", conversionFactorToStandardUnit=" 127 + this.getConversionFactorToStandardUnit() + "]"; 128 } 129 130 }