1 /*
2 * Copyright (C) 2020 Alberto Irurueta Carro (alberto@irurueta.com)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.irurueta.navigation.inertial.wmm;
17
18 import com.irurueta.algebra.Matrix;
19 import com.irurueta.algebra.WrongSizeException;
20 import com.irurueta.navigation.inertial.calibration.MagneticFluxDensityTriad;
21 import com.irurueta.units.MagneticFluxDensity;
22 import com.irurueta.units.MagneticFluxDensityConverter;
23 import com.irurueta.units.MagneticFluxDensityUnit;
24
25 import java.io.Serial;
26 import java.io.Serializable;
27 import java.util.Objects;
28
29 /**
30 * Contains magnetic flux density resolved around NED frame.
31 */
32 public class NEDMagneticFluxDensity implements Serializable, Cloneable {
33
34 /**
35 * Number of components.
36 */
37 public static final int COMPONENTS = 3;
38
39 /**
40 * Serialization version. This is used to ensure compatibility of deserialization of permanently stored serialized
41 * instances.
42 */
43 @Serial
44 private static final long serialVersionUID = 0L;
45
46 /**
47 * North component of magnetic flux density expressed in Teslas (T).
48 */
49 private double bn;
50
51 /**
52 * East component of magnetic flux density expressed in Teslas (T).
53 */
54 private double be;
55
56 /**
57 * Down component of magnetic flux density expressed in Teslas (T).
58 */
59 private double bd;
60
61 /**
62 * Constructor.
63 */
64 public NEDMagneticFluxDensity() {
65 }
66
67 /**
68 * Constructor.
69 *
70 * @param bn north component of magnetic flux density expressed in
71 * Teslas (T).
72 * @param be east component of magnetic flux density expressed in
73 * Teslas (T).
74 * @param bd down component of magnetic flux density expressed in
75 * Teslas (T).
76 */
77 public NEDMagneticFluxDensity(final double bn, final double be, final double bd) {
78 setCoordinates(bn, be, bd);
79 }
80
81 /**
82 * Constructor.
83 *
84 * @param bn north component of magnetic flux density.
85 * @param be east component of magnetic flux density.
86 * @param bd down component of magnetic flux density.
87 */
88 public NEDMagneticFluxDensity(
89 final MagneticFluxDensity bn, final MagneticFluxDensity be, final MagneticFluxDensity bd) {
90 setCoordinates(bn, be, bd);
91 }
92
93 /**
94 * Constructor.
95 *
96 * @param triad triad containing magnetic flux density values, where x,y,z
97 * coordinates correspond to north, east, down coordinates.
98 */
99 public NEDMagneticFluxDensity(final MagneticFluxDensityTriad triad) {
100 setCoordinates(triad);
101 }
102
103 /**
104 * Constructor.
105 *
106 * @param input instance to copy data from.
107 */
108 public NEDMagneticFluxDensity(final NEDMagneticFluxDensity input) {
109 copyFrom(input);
110 }
111
112 /**
113 * Gets north component of magnetic flux density expressed in Teslas
114 * (T).
115 *
116 * @return north component of magnetic flux density.
117 */
118 public double getBn() {
119 return bn;
120 }
121
122 /**
123 * Sets north component of magnetic flux density expressed in Teslas
124 * (T).
125 *
126 * @param bn north component of magnetic flux density.
127 */
128 public void setBn(final double bn) {
129 this.bn = bn;
130 }
131
132 /**
133 * Gets north component of magnetic flux density.
134 *
135 * @return north component of magnetic flux density.
136 */
137 public MagneticFluxDensity getBnAsMagneticFluxDensity() {
138 return new MagneticFluxDensity(bn, MagneticFluxDensityUnit.TESLA);
139 }
140
141 /**
142 * Gets north component of magnetic flux density.
143 *
144 * @param result instance where result will be stored.
145 */
146 public void getBnAsMagneticFluxDensity(final MagneticFluxDensity result) {
147 result.setValue(bn);
148 result.setUnit(MagneticFluxDensityUnit.TESLA);
149 }
150
151 /**
152 * Sets north component of magnetic flux density.
153 *
154 * @param bn north component of magnetic flux density.
155 */
156 public void setBn(final MagneticFluxDensity bn) {
157 this.bn = convertMagneticFluxDensity(bn);
158 }
159
160 /**
161 * Gets east component of magnetic flux density expressed in Teslas
162 * (T).
163 *
164 * @return east component of magnetic flux density.
165 */
166 public double getBe() {
167 return be;
168 }
169
170 /**
171 * Sets east component of magnetic flux density expressed in Teslas
172 * (T).
173 *
174 * @param be est component of magnetic flux density.
175 */
176 public void setBe(final double be) {
177 this.be = be;
178 }
179
180 /**
181 * Gets east component of magnetic flux density.
182 *
183 * @return east component of magnetic flux density.
184 */
185 public MagneticFluxDensity getBeAsMagneticFluxDensity() {
186 return new MagneticFluxDensity(be, MagneticFluxDensityUnit.TESLA);
187 }
188
189 /**
190 * Gets east component of magnetic flux density.
191 *
192 * @param result instance where result will be stored.
193 */
194 public void getBeAsMagneticFluxDensity(final MagneticFluxDensity result) {
195 result.setValue(be);
196 result.setUnit(MagneticFluxDensityUnit.TESLA);
197 }
198
199 /**
200 * Sets east component of magnetic flux density.
201 *
202 * @param be east component of magnetic flux density.
203 */
204 public void setBe(final MagneticFluxDensity be) {
205 this.be = convertMagneticFluxDensity(be);
206 }
207
208 /**
209 * Gets down component of magnetic flux density expressed in Teslas
210 * (T).
211 *
212 * @return down component of magnetic flux density.
213 */
214 public double getBd() {
215 return bd;
216 }
217
218 /**
219 * Sets down component of magnetic flux density expressed in Teslas
220 * (T).
221 *
222 * @param bd down component of magnetic flux density.
223 */
224 public void setBd(final double bd) {
225 this.bd = bd;
226 }
227
228 /**
229 * Gets down component of magnetic flux density.
230 *
231 * @return down component of magnetic flux density.
232 */
233 public MagneticFluxDensity getBdAsMagneticFluxDensity() {
234 return new MagneticFluxDensity(bd, MagneticFluxDensityUnit.TESLA);
235 }
236
237 /**
238 * Gets down component of magnetic flux density.
239 *
240 * @param result instance where result will be stored.
241 */
242 public void getBdAsMagneticFluxDensity(final MagneticFluxDensity result) {
243 result.setValue(bd);
244 result.setUnit(MagneticFluxDensityUnit.TESLA);
245 }
246
247 /**
248 * Sets down component of magnetic flux density.
249 *
250 * @param bd down component of magnetic flux density.
251 */
252 public void setBd(final MagneticFluxDensity bd) {
253 this.bd = convertMagneticFluxDensity(bd);
254 }
255
256 /**
257 * Sets NED coordinates of magnetic flux density expressed in Teslas (T).
258 *
259 * @param bn north component of magnetic flux density.
260 * @param be east component of magnetic flux density.
261 * @param bd down component of magnetic flux density.
262 */
263 public void setCoordinates(final double bn, final double be, final double bd) {
264 this.bn = bn;
265 this.be = be;
266 this.bd = bd;
267 }
268
269 /**
270 * Sets NED coordinates of magnetic flux density.
271 *
272 * @param bn north component of magnetic flux density.
273 * @param be east component of magnetic flux density.
274 * @param bd down component of magnetic flux density.
275 */
276 public void setCoordinates(
277 final MagneticFluxDensity bn, final MagneticFluxDensity be, final MagneticFluxDensity bd) {
278 setCoordinates(convertMagneticFluxDensity(bn), convertMagneticFluxDensity(be), convertMagneticFluxDensity(bd));
279 }
280
281 /**
282 * Gets NED coordinates of magnetic flux density as a triad.
283 * x,y,z coordinates correspond to north, east, down coordinates.
284 *
285 * @return NED coordinates of magnetic flux density as a triad.
286 */
287 public MagneticFluxDensityTriad getCoordinatesAsTriad() {
288 return new MagneticFluxDensityTriad(MagneticFluxDensityUnit.TESLA, bn, be, bd);
289 }
290
291 /**
292 * Gets NED coordinates of magnetic flux density as a triad.
293 * x,y,z coordinates correspond to north, east, down coordinates.
294 *
295 * @param result instance where result will be stored.
296 */
297 public void getCoordinatesAsTriad(final MagneticFluxDensityTriad result) {
298 result.setValueCoordinatesAndUnit(bn, be, bd, MagneticFluxDensityUnit.TESLA);
299 }
300
301 /**
302 * Sets NED coordinates of magnetic flux density.
303 *
304 * @param triad triad containing magnetic flux density values, where x,y,z
305 * coordinates correspond to north, east, down coordinates.
306 */
307 public void setCoordinates(final MagneticFluxDensityTriad triad) {
308 final var tmpBn = convertMagneticFluxDensity(triad.getValueX(), triad.getUnit());
309 final var tmpBe = convertMagneticFluxDensity(triad.getValueY(), triad.getUnit());
310 final var tmpBd = convertMagneticFluxDensity(triad.getValueZ(), triad.getUnit());
311 setCoordinates(tmpBn, tmpBe, tmpBd);
312 }
313
314 /**
315 * Gets magnetic flux density magnitude (e.g. norm) expressed in
316 * Teslas (T).
317 *
318 * @return magnetic flux density magnitude.
319 */
320 public double getNorm() {
321 return Math.sqrt(bn * bn + be * be + bd * bd);
322 }
323
324 /**
325 * Gets magnetic flux density magnitude (e.g. norm).
326 *
327 * @return magnetic flux density magnitude.
328 */
329 public MagneticFluxDensity getNormAsMagneticFluxDensity() {
330 return new MagneticFluxDensity(getNorm(), MagneticFluxDensityUnit.TESLA);
331 }
332
333 /**
334 * Gets magnetic flux density magnitude (e.g. norm).
335 *
336 * @param result instance where result will be stored.
337 */
338 public void getNormAsMagneticFluxDensity(final MagneticFluxDensity result) {
339 result.setValue(getNorm());
340 result.setUnit(MagneticFluxDensityUnit.TESLA);
341 }
342
343 /**
344 * Copies this instance data into provided instance.
345 *
346 * @param output destination instance where data will be copied to.
347 */
348 public void copyTo(final NEDMagneticFluxDensity output) {
349 output.bn = bn;
350 output.be = be;
351 output.bd = bd;
352 }
353
354 /**
355 * Copies data of provided instance into this instance.
356 *
357 * @param input instance to copy data from.
358 */
359 public void copyFrom(final NEDMagneticFluxDensity input) {
360 bn = input.bn;
361 be = input.be;
362 bd = input.bd;
363 }
364
365 /**
366 * Gets magnetic flux density as an array.
367 *
368 * @param result array instance where magnetic flux density coordinates
369 * will be stored in n,e,d order.
370 * @throws IllegalArgumentException if provided array does not have length 3.
371 */
372 public void asArray(final double[] result) {
373 if (result.length != COMPONENTS) {
374 throw new IllegalArgumentException();
375 }
376
377 result[0] = bn;
378 result[1] = be;
379 result[2] = bd;
380 }
381
382 /**
383 * Gets magnetic flux density as an array.
384 *
385 * @return array containing magnetic flux density coordinates in n,e,d
386 * order.
387 */
388 public double[] asArray() {
389 final var result = new double[COMPONENTS];
390 asArray(result);
391 return result;
392 }
393
394 /**
395 * Gets magnetic flux density as a column matrix.
396 * If provided matrix does not have size 3x1, it will be resized.
397 *
398 * @param result matrix instance where magnetic flux density coordinates
399 * will be stored in n,e,d order.
400 */
401 @SuppressWarnings("DuplicatedCode")
402 public void asMatrix(final Matrix result) {
403 if (result.getColumns() != COMPONENTS || result.getRows() != 1) {
404 try {
405 result.resize(COMPONENTS, 1);
406 } catch (final WrongSizeException ignore) {
407 // never happens
408 }
409 }
410
411 result.setElementAtIndex(0, bn);
412 result.setElementAtIndex(1, be);
413 result.setElementAtIndex(2, bd);
414 }
415
416 /**
417 * Gets magnetic flux density as a column matrix.
418 *
419 * @return a matrix containing magnetic flux density coordinates stored
420 * in n,e,d order.
421 */
422 public Matrix asMatrix() {
423 Matrix result;
424 try {
425 result = new Matrix(COMPONENTS, 1);
426 asMatrix(result);
427 } catch (final WrongSizeException ignore) {
428 // never happens
429 result = null;
430 }
431 return result;
432 }
433
434 /**
435 * Computes and returns hash code for this instance. Hash codes are almost unique
436 * values that are useful for fast classification and storage of objects in collections.
437 *
438 * @return Hash code.
439 */
440 @Override
441 public int hashCode() {
442 return Objects.hash(bn, be, bd);
443 }
444
445 /**
446 * Check if provided object is a NEDMagneticFluxDensity instance having
447 * exactly the same contents as this instance.
448 *
449 * @param obj object to be compared.
450 * @return true if both objects are considered to be equal, false
451 * otherwise.
452 */
453 @Override
454 public boolean equals(final Object obj) {
455 if (obj == null) {
456 return false;
457 }
458 if (obj == this) {
459 return true;
460 }
461 if (!(obj instanceof NEDMagneticFluxDensity)) {
462 return false;
463 }
464
465 //noinspection PatternVariableCanBeUsed
466 final var other = (NEDMagneticFluxDensity) obj;
467 return equals(other);
468 }
469
470 /**
471 * Checks if provided instance has exactly the same contents as this
472 * instance.
473 *
474 * @param other instance to be compared.
475 * @return true if both instances are considered to be equal, false
476 * otherwise.
477 */
478 public boolean equals(final NEDMagneticFluxDensity other) {
479 return equals(other, 0.0);
480 }
481
482 /**
483 * Checks if provided instance has contents similar to this instance up
484 * to provided threshold value.
485 *
486 * @param other instance to be compared.
487 * @param threshold maximum allowed difference between gravity coordinates.
488 * @return true if both instances are considered to be equal (up to provided
489 * threshold), false otherwise.
490 */
491 public boolean equals(final NEDMagneticFluxDensity other, final double threshold) {
492 if (other == null) {
493 return false;
494 }
495
496 return Math.abs(bn - other.bn) <= threshold && Math.abs(be - other.be) <= threshold
497 && Math.abs(bd - other.bd) <= threshold;
498 }
499
500 /**
501 * Makes a copy of this instance.
502 *
503 * @return a copy of this instance.
504 * @throws CloneNotSupportedException if clone fails for same reason.
505 */
506 @Override
507 protected Object clone() throws CloneNotSupportedException {
508 final var result = (NEDMagneticFluxDensity) super.clone();
509 copyTo(result);
510 return result;
511 }
512
513 /**
514 * Converts magnetic flux density to Teslas.
515 *
516 * @param b magnetic flux density to be converted.
517 * @return converted value.
518 */
519 private double convertMagneticFluxDensity(final MagneticFluxDensity b) {
520 return MagneticFluxDensityConverter.convert(b.getValue().doubleValue(), b.getUnit(),
521 MagneticFluxDensityUnit.TESLA);
522 }
523
524 /**
525 * Converts magnetic flux density to Teslas.
526 *
527 * @param value value to be converted.
528 * @param unit unit of value to be converted
529 * @return converted value.
530 */
531 private double convertMagneticFluxDensity(final double value, final MagneticFluxDensityUnit unit) {
532 return MagneticFluxDensityConverter.convert(value, unit, MagneticFluxDensityUnit.TESLA);
533 }
534 }