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:
|
2024-09-03 07:52:12 +00:00
|
|
|
|
pressure = int_cast<int>(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);
|
|
|
|
|
}
|
|
|
|
|
|