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-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
37 * BSD-style license. See <a href="https://djunits.org/docs/license.html">DJUNITS 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 }