1 package org.djunits.unit.scale;
2
3 import org.djutils.exceptions.Throw;
4
5 /**
6 * A Scale for linear transformations not involving a zero-offset, e.g. for Length, Time, Area. <br>
7 * A linear scale is a scale that is linearly relates a unit to the underlying SI standard unit. E.g. Mile is linearly related
8 * to meter (the SI unit for length) and the conversion is zero-based (0 miles equals 0 meter). Unlike temperature in degrees
9 * Celsius which is <strong>not</strong> linearly related to the Kelvin (the SI unit for temperature) because the conversion is
10 * not zero-based (0°C is 273.15K).
11 * <p>
12 * Copyright (c) 2013-2026 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
13 * BSD-style license. See <a href="https://djunits.org/docs/license.html">DJUNITS License</a>.
14 * @author Alexander Verbraeck
15 * @author Peter Knoppers
16 */
17 public class LinearScale implements Scale
18 {
19 /** */
20 private static final long serialVersionUID = 600L;
21
22 /** multiply by this number to convert to the base (e.g., SI) unit. */
23 private final double scaleFactorToBaseUnit;
24
25 /**
26 * Construct a Scale for linear transformations. To transform, e.g., a minute to a second, a scale factor of 60 is used.
27 * @param scaleFactorToBaseUnit the conversion factor by which this number has to be multiplied to convert it to the base
28 * (e.g., SI) unit.
29 */
30 public LinearScale(final double scaleFactorToBaseUnit)
31 {
32 Throw.when(scaleFactorToBaseUnit <= 0.0 || !Double.isFinite(scaleFactorToBaseUnit), IllegalArgumentException.class,
33 "scale factor for linear scale must be positive and cannnot be NaN or infinity");
34 this.scaleFactorToBaseUnit = scaleFactorToBaseUnit;
35 }
36
37 /**
38 * Construct a Scale for linear transformations, with a numerator and denominator. To transform, e.g., m/s to km/h, a
39 * numerator of 1000 (a km is 1000 m) and a denominator of 3600 (an hour is 3600 seconds) is used.
40 * @param numerator the factor by which this number has to be multiplied to convert it to the base (e.g., SI) unit.
41 * @param denominator the factor by which this number has to be divided to convert it to the base (e.g., SI) unit.
42 */
43 public LinearScale(final double numerator, final double denominator)
44 {
45 this(numerator / denominator);
46 }
47
48 @Override
49 public double toBaseValue(final double value)
50 {
51 return value * this.scaleFactorToBaseUnit;
52 }
53
54 @Override
55 public double fromBaseValue(final double value)
56 {
57 return value / this.scaleFactorToBaseUnit;
58 }
59
60 /**
61 * Retrieve the factor for conversion to the standard unit.
62 * @return the factor for conversion to the standard unit
63 */
64 public final double getScaleFactorToBaseUnit()
65 {
66 return this.scaleFactorToBaseUnit;
67 }
68
69 @Override
70 public boolean isBaseScale()
71 {
72 return this.scaleFactorToBaseUnit == 1.0;
73 }
74
75 @Override
76 public int hashCode()
77 {
78 final int prime = 31;
79 int result = 1;
80 long temp;
81 temp = Double.doubleToLongBits(this.scaleFactorToBaseUnit);
82 result = prime * result + (int) (temp ^ (temp >>> 32));
83 return result;
84 }
85
86 @SuppressWarnings("checkstyle:needbraces")
87 @Override
88 public boolean equals(final Object obj)
89 {
90 if (this == obj)
91 return true;
92 if (obj == null)
93 return false;
94 if (getClass() != obj.getClass())
95 return false;
96 LinearScale other = (LinearScale) obj;
97 if (Double.doubleToLongBits(this.scaleFactorToBaseUnit) != Double.doubleToLongBits(other.scaleFactorToBaseUnit))
98 return false;
99 return true;
100 }
101
102 @Override
103 public String toString()
104 {
105 return "LinearScale [scaleFactorToBaseUnit=" + this.scaleFactorToBaseUnit + "]";
106 }
107
108 }