001 /*
002 * Java GPX Library (jpx-3.1.0).
003 * Copyright (c) 2016-2023 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019 */
020 package io.jenetics.jpx;
021
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024
025 import java.io.DataInput;
026 import java.io.DataOutput;
027 import java.io.IOException;
028 import java.io.InvalidObjectException;
029 import java.io.ObjectInputStream;
030 import java.io.Serial;
031 import java.io.Serializable;
032
033 /**
034 * Represents the GPS speed value in m/s.
035 *
036 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
037 * @version 1.2
038 * @since 1.0
039 */
040 public final class Speed
041 extends Number
042 implements
043 Comparable<Speed>,
044 Serializable
045 {
046
047 @Serial
048 private static final long serialVersionUID = 2L;
049
050 /**
051 * Represents a given speed unit.
052 */
053 public enum Unit {
054
055 /**
056 * Represents the speed unit <em>meters per second</em>: <b>m/s</b>.
057 */
058 METERS_PER_SECOND(1.0),
059
060 /**
061 * Represents the speed unit <em>kilometers per hour</em>: <b>km/h</b>.
062 */
063 KILOMETERS_PER_HOUR(5.0/18.0),
064
065 /**
066 * Represents the speed unit <em>miles per hour</em>: <b>mi/h</b>.
067 */
068 MILES_PER_HOUR(1_397.0/3_125.0),
069
070 /**
071 * Represents the speed unit <em>knots</em>: <b>kt</b>.
072 */
073 KNOTS(463.0/900.0),
074
075 /**
076 * Represents the speed unit <em>mach</em>: <b>Ma</b>.
077 */
078 MACH(331.3);
079
080 // The conversion factor to the base unit m/s.
081 private final double _factor;
082
083 Unit(final double factor) {
084 _factor = factor;
085 }
086
087 /**
088 * Convert the given speed value of the given {@code sourceUnit} into a
089 * speed value of {@code this} speed unit. The given example converts 3
090 * knots into kilometers per hour.
091 *
092 * <pre>{@code
093 * final double kilometersPerHour = KILOMETERS_PER_HOUR.convert(3, KNOTS);
094 * }</pre>
095 *
096 * @param speed the speed value
097 * @param sourceUnit the source speed unit
098 * @return the speed value of {@code this} speed unit
099 */
100 public double convert(final double speed, final Unit sourceUnit) {
101 requireNonNull(sourceUnit);
102 final double metersPerSecond = speed*sourceUnit._factor;
103 return metersPerSecond/_factor;
104 }
105
106 }
107
108
109 private final double _value;
110
111 /**
112 * Create a new GPS {@code Speed} object in m/s.
113 *
114 * @param value the GPS speed value in m/s.
115 */
116 private Speed(final double value) {
117 _value = value;
118 }
119
120 /**
121 * Return the GPS speed value in m/s.
122 *
123 * @return the GPS speed value in m/s
124 */
125 @Override
126 public double doubleValue() {
127 return _value;
128 }
129
130 /**
131 * Return the GPS speed value in the desired unit.
132 *
133 * @param unit the speed unit
134 * @return the GPS speed value in the desired unit
135 * @throws NullPointerException if the given speed {@code unit} is
136 * {@code null}
137 */
138 public double to(final Unit unit) {
139 requireNonNull(unit);
140 return unit.convert(_value, Unit.METERS_PER_SECOND);
141 }
142
143 @Override
144 public int intValue() {
145 return (int)doubleValue();
146 }
147
148 @Override
149 public long longValue() {
150 return (long)doubleValue();
151 }
152
153 @Override
154 public float floatValue() {
155 return (float)doubleValue();
156 }
157
158 @Override
159 public int compareTo(final Speed speed) {
160 return Double.compare(_value, speed._value);
161 }
162
163 @Override
164 public int hashCode() {
165 return Double.hashCode(_value);
166 }
167
168 @Override
169 public boolean equals(final Object obj) {
170 return obj == this ||
171 obj instanceof Speed speed &&
172 Double.compare(speed._value, _value) == 0;
173 }
174
175 @Override
176 public String toString() {
177 return format("%s m/s", _value);
178 }
179
180
181 /* *************************************************************************
182 * Static object creation methods
183 * ************************************************************************/
184
185 /**
186 * Create a new GPS {@code Speed} object.
187 *
188 * @param speed the GPS speed value
189 * @param unit the speed unit
190 * @return a new GPS {@code Speed} object
191 * @throws NullPointerException if the given speed {@code unit} is
192 * {@code null}
193 */
194 public static Speed of(final double speed, final Unit unit) {
195 requireNonNull(unit);
196 return new Speed(Unit.METERS_PER_SECOND.convert(speed, unit));
197 }
198
199 static Speed parse(final String value) {
200 final String speed = Strings.trim(value);
201 return speed != null
202 ? Speed.of(Double.parseDouble(speed), Unit.METERS_PER_SECOND)
203 : null;
204 }
205
206 /* *************************************************************************
207 * Java object serialization
208 * ************************************************************************/
209
210 @Serial
211 private Object writeReplace() {
212 return new SerialProxy(SerialProxy.SPEED, this);
213 }
214
215 @Serial
216 private void readObject(final ObjectInputStream stream)
217 throws InvalidObjectException
218 {
219 throw new InvalidObjectException("Serialization proxy required.");
220 }
221
222 void write(final DataOutput out) throws IOException {
223 out.writeDouble(_value);
224 }
225
226 static Speed read(final DataInput in) throws IOException {
227 return new Speed(in.readDouble());
228 }
229
230 }
|