View Javadoc
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 }