2019-06-04 07:05:17 +00:00
|
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
#include "units.h"
|
|
|
|
|
#include "gettext.h"
|
2021-01-02 12:56:56 +00:00
|
|
|
|
#include "pref.h"
|
2019-06-04 07:05:17 +00:00
|
|
|
|
|
2024-02-28 21:01:51 +00:00
|
|
|
|
const struct units SI_units = SI_UNITS;
|
2024-05-02 05:56:47 +00:00
|
|
|
|
const struct units IMPERIAL_units = {
|
|
|
|
|
.length = units::FEET, .volume = units::CUFT, .pressure = units::PSI, .temperature = units::FAHRENHEIT, .weight = units::LBS,
|
|
|
|
|
.vertical_speed_time = units::MINUTES, .duration_units = units::MIXED, .show_units_table = false
|
|
|
|
|
};
|
2024-02-28 21:01:51 +00:00
|
|
|
|
|
2024-05-04 16:45:55 +00:00
|
|
|
|
int get_pressure_units(int mb, const char **units)
|
2019-06-04 07:05:17 +00:00
|
|
|
|
{
|
|
|
|
|
int pressure;
|
|
|
|
|
const char *unit;
|
|
|
|
|
const struct units *units_p = get_units();
|
|
|
|
|
|
|
|
|
|
switch (units_p->pressure) {
|
2024-05-02 05:56:47 +00:00
|
|
|
|
case units::BAR:
|
2019-06-04 07:05:17 +00:00
|
|
|
|
default:
|
|
|
|
|
pressure = (mb + 500) / 1000;
|
|
|
|
|
unit = translate("gettextFromC", "bar");
|
|
|
|
|
break;
|
2024-05-02 05:56:47 +00:00
|
|
|
|
case units::PSI:
|
core: return floating point from to_PSI() functions
Dive data are stored internally using integral types using
appropriately fine units (mm, mbar, mkelvin, etc.). These
are converted with functions defined in units.h for display
(m, bar, C, etc.). Usually floating points are returned by
these functions, to retain the necessary precision. There
is one exception: the to_PSI() and mbar_to_PSI() functions.
For consistency, make these functions likewise return floats.
This will be needed for the rework of the profile-axes.
The plan is to use the conversion functions to make the
axes aware of the displayed values. This in turn will be
necessary to place the ticks at sensible distances. However,
the conversions need to be precise, which is not the
case for the current to_PSI() functions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-09-24 13:07:11 +00:00
|
|
|
|
pressure = (int)lrint(mbar_to_PSI(mb));
|
2019-06-04 07:05:17 +00:00
|
|
|
|
unit = translate("gettextFromC", "psi");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (units)
|
|
|
|
|
*units = unit;
|
|
|
|
|
return pressure;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-04 16:45:55 +00:00
|
|
|
|
double get_temp_units(unsigned int mk, const char **units)
|
2019-06-04 07:05:17 +00:00
|
|
|
|
{
|
|
|
|
|
double deg;
|
|
|
|
|
const char *unit;
|
|
|
|
|
const struct units *units_p = get_units();
|
|
|
|
|
|
2024-05-02 05:56:47 +00:00
|
|
|
|
if (units_p->temperature == units::FAHRENHEIT) {
|
2019-06-04 07:05:17 +00:00
|
|
|
|
deg = mkelvin_to_F(mk);
|
|
|
|
|
unit = "°F";
|
|
|
|
|
} else {
|
|
|
|
|
deg = mkelvin_to_C(mk);
|
|
|
|
|
unit = "°C";
|
|
|
|
|
}
|
|
|
|
|
if (units)
|
|
|
|
|
*units = unit;
|
|
|
|
|
return deg;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-04 16:45:55 +00:00
|
|
|
|
double get_volume_units(unsigned int ml, int *frac, const char **units)
|
2019-06-04 07:05:17 +00:00
|
|
|
|
{
|
|
|
|
|
int decimals;
|
|
|
|
|
double vol;
|
|
|
|
|
const char *unit;
|
|
|
|
|
const struct units *units_p = get_units();
|
|
|
|
|
|
|
|
|
|
switch (units_p->volume) {
|
2024-05-02 05:56:47 +00:00
|
|
|
|
case units::LITER:
|
2019-06-04 07:05:17 +00:00
|
|
|
|
default:
|
|
|
|
|
vol = ml / 1000.0;
|
|
|
|
|
unit = translate("gettextFromC", "ℓ");
|
|
|
|
|
decimals = 1;
|
|
|
|
|
break;
|
2024-05-02 05:56:47 +00:00
|
|
|
|
case units::CUFT:
|
2019-06-04 07:05:17 +00:00
|
|
|
|
vol = ml_to_cuft(ml);
|
|
|
|
|
unit = translate("gettextFromC", "cuft");
|
|
|
|
|
decimals = 2;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (frac)
|
|
|
|
|
*frac = decimals;
|
|
|
|
|
if (units)
|
|
|
|
|
*units = unit;
|
|
|
|
|
return vol;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-04 16:45:55 +00:00
|
|
|
|
int units_to_sac(double volume)
|
2019-06-04 07:05:17 +00:00
|
|
|
|
{
|
2024-05-02 05:56:47 +00:00
|
|
|
|
if (get_units()->volume == units::CUFT)
|
2019-06-04 07:05:17 +00:00
|
|
|
|
return lrint(cuft_to_l(volume) * 1000.0);
|
|
|
|
|
else
|
|
|
|
|
return lrint(volume * 1000);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-04 16:45:55 +00:00
|
|
|
|
depth_t units_to_depth(double depth)
|
2019-06-04 07:05:17 +00:00
|
|
|
|
{
|
|
|
|
|
depth_t internaldepth;
|
2024-05-02 05:56:47 +00:00
|
|
|
|
if (get_units()->length == units::METERS) {
|
2019-06-04 07:05:17 +00:00
|
|
|
|
internaldepth.mm = lrint(depth * 1000);
|
|
|
|
|
} else {
|
|
|
|
|
internaldepth.mm = feet_to_mm(depth);
|
|
|
|
|
}
|
|
|
|
|
return internaldepth;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-04 16:45:55 +00:00
|
|
|
|
double get_depth_units(int mm, int *frac, const char **units)
|
2019-06-04 07:05:17 +00:00
|
|
|
|
{
|
|
|
|
|
int decimals;
|
|
|
|
|
double d;
|
|
|
|
|
const char *unit;
|
|
|
|
|
const struct units *units_p = get_units();
|
|
|
|
|
|
|
|
|
|
switch (units_p->length) {
|
2024-05-02 05:56:47 +00:00
|
|
|
|
case units::METERS:
|
2019-06-04 07:05:17 +00:00
|
|
|
|
default:
|
|
|
|
|
d = mm / 1000.0;
|
|
|
|
|
unit = translate("gettextFromC", "m");
|
|
|
|
|
decimals = d < 20;
|
|
|
|
|
break;
|
2024-05-02 05:56:47 +00:00
|
|
|
|
case units::FEET:
|
2019-06-04 07:05:17 +00:00
|
|
|
|
d = mm_to_feet(mm);
|
|
|
|
|
unit = translate("gettextFromC", "ft");
|
|
|
|
|
decimals = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (frac)
|
|
|
|
|
*frac = decimals;
|
|
|
|
|
if (units)
|
|
|
|
|
*units = unit;
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-04 16:45:55 +00:00
|
|
|
|
double get_vertical_speed_units(unsigned int mms, int *frac, const char **units)
|
2019-06-04 07:05:17 +00:00
|
|
|
|
{
|
|
|
|
|
double d;
|
|
|
|
|
const char *unit;
|
|
|
|
|
const struct units *units_p = get_units();
|
2024-05-02 05:56:47 +00:00
|
|
|
|
const double time_factor = units_p->vertical_speed_time == units::MINUTES ? 60.0 : 1.0;
|
2019-06-04 07:05:17 +00:00
|
|
|
|
|
|
|
|
|
switch (units_p->length) {
|
2024-05-02 05:56:47 +00:00
|
|
|
|
case units::METERS:
|
2019-06-04 07:05:17 +00:00
|
|
|
|
default:
|
|
|
|
|
d = mms / 1000.0 * time_factor;
|
2024-05-02 05:56:47 +00:00
|
|
|
|
if (units_p->vertical_speed_time == units::MINUTES)
|
2019-06-04 07:05:17 +00:00
|
|
|
|
unit = translate("gettextFromC", "m/min");
|
|
|
|
|
else
|
|
|
|
|
unit = translate("gettextFromC", "m/s");
|
|
|
|
|
break;
|
2024-05-02 05:56:47 +00:00
|
|
|
|
case units::FEET:
|
2019-06-04 07:05:17 +00:00
|
|
|
|
d = mm_to_feet(mms) * time_factor;
|
2024-05-02 05:56:47 +00:00
|
|
|
|
if (units_p->vertical_speed_time == units::MINUTES)
|
2019-06-04 07:05:17 +00:00
|
|
|
|
unit = translate("gettextFromC", "ft/min");
|
|
|
|
|
else
|
|
|
|
|
unit = translate("gettextFromC", "ft/s");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (frac)
|
|
|
|
|
*frac = d < 10;
|
|
|
|
|
if (units)
|
|
|
|
|
*units = unit;
|
|
|
|
|
return d;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-04 16:45:55 +00:00
|
|
|
|
double get_weight_units(unsigned int grams, int *frac, const char **units)
|
2019-06-04 07:05:17 +00:00
|
|
|
|
{
|
|
|
|
|
int decimals;
|
|
|
|
|
double value;
|
|
|
|
|
const char *unit;
|
|
|
|
|
const struct units *units_p = get_units();
|
|
|
|
|
|
2024-05-02 05:56:47 +00:00
|
|
|
|
if (units_p->weight == units::LBS) {
|
2019-06-04 07:05:17 +00:00
|
|
|
|
value = grams_to_lbs(grams);
|
|
|
|
|
unit = translate("gettextFromC", "lbs");
|
|
|
|
|
decimals = 0;
|
|
|
|
|
} else {
|
|
|
|
|
value = grams / 1000.0;
|
|
|
|
|
unit = translate("gettextFromC", "kg");
|
|
|
|
|
decimals = 1;
|
|
|
|
|
}
|
|
|
|
|
if (frac)
|
|
|
|
|
*frac = decimals;
|
|
|
|
|
if (units)
|
|
|
|
|
*units = unit;
|
|
|
|
|
return value;
|
|
|
|
|
}
|
2021-01-02 12:56:56 +00:00
|
|
|
|
|
2024-05-04 16:45:55 +00:00
|
|
|
|
const struct units *get_units()
|
2021-01-02 12:56:56 +00:00
|
|
|
|
{
|
|
|
|
|
return &prefs.units;
|
|
|
|
|
}
|
2024-05-11 13:18:37 +00:00
|
|
|
|
|
|
|
|
|
// Calculate the distance in meters between two coordinates.
|
|
|
|
|
unsigned int get_distance(location_t loc1, location_t loc2)
|
|
|
|
|
{
|
|
|
|
|
double lat1_r = udeg_to_radians(loc1.lat.udeg);
|
|
|
|
|
double lat2_r = udeg_to_radians(loc2.lat.udeg);
|
|
|
|
|
double lat_d_r = udeg_to_radians(loc2.lat.udeg - loc1.lat.udeg);
|
|
|
|
|
double lon_d_r = udeg_to_radians(loc2.lon.udeg - loc1.lon.udeg);
|
|
|
|
|
|
|
|
|
|
double a = sin(lat_d_r/2) * sin(lat_d_r/2) +
|
|
|
|
|
cos(lat1_r) * cos(lat2_r) * sin(lon_d_r/2) * sin(lon_d_r/2);
|
|
|
|
|
if (a < 0.0) a = 0.0;
|
|
|
|
|
if (a > 1.0) a = 1.0;
|
|
|
|
|
double c = 2 * atan2(sqrt(a), sqrt(1.0 - a));
|
|
|
|
|
|
|
|
|
|
// Earth radius in metres
|
|
|
|
|
return lrint(6371000 * c);
|
|
|
|
|
}
|
|
|
|
|
|