Skip to content

Commit

Permalink
modernize units (GPSBabel#969)
Browse files Browse the repository at this point in the history
* modernize units

fmt_* returns a std::pair of the value and the units.
use structured binding to unpack the pair.
use scoped enumeration for the units system.

* make units formatter a class.

* cleanup unitsformatter instance.
  • Loading branch information
tsteven4 authored Jan 2, 2023
1 parent 70e7f1a commit 0ccae9f
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 85 deletions.
43 changes: 18 additions & 25 deletions kml.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <QList> // for QList
#include <QString> // for QString, QStringLiteral, operator+, operator!=
#include <QStringList> // for QStringList
#include <QStringLiteral> // for qMakeStringPrivate, QStringLit...
#include <QVector> // for QVector
#include <QXmlStreamAttributes> // for QXmlStreamAttributes
#include <Qt> // for ISODate
Expand All @@ -53,7 +54,7 @@
#include "src/core/logging.h" // for Warning, Fatal
#include "src/core/xmlstreamwriter.h" // for XmlStreamWriter
#include "src/core/xmltag.h" // for xml_findfirst, xml_tag, fs_xml, xml_attribute, xml_findnext
#include "units.h" // for fmt_setunits, fmt_speed, fmt_altitude, fmt_distance, units_aviation, units_metric, units_nautical, units_statute
#include "units.h" // for UnitsFormatter, UnitsFormatter...
#include "xmlgeneric.h" // for cb_cdata, cb_end, cb_start, xg_callback, xg_string, xg_cb_type, xml_deinit, xml_ignore_tags, xml_init, xml_read, xg_tag_mapping


Expand Down Expand Up @@ -357,18 +358,19 @@ void KmlFormat::wr_init(const QString& fname)
u = tolower(opt_units[0]);
}

unitsformatter = new UnitsFormatter();
switch (u) {
case 's':
fmt_setunits(units_statute);
unitsformatter->setunits(UnitsFormatter::units_t::statute);
break;
case 'm':
fmt_setunits(units_metric);
unitsformatter->setunits(UnitsFormatter::units_t::metric);
break;
case 'n':
fmt_setunits(units_nautical);
unitsformatter->setunits(UnitsFormatter::units_t::nautical);
break;
case 'a':
fmt_setunits(units_aviation);
unitsformatter->setunits(UnitsFormatter::units_t::aviation);
break;
default:
fatal("Units argument '%s' should be 's' for statute units, 'm' for metric, 'n' for nautical or 'a' for aviation.\n", opt_units);
Expand Down Expand Up @@ -404,6 +406,8 @@ void KmlFormat::wr_deinit()
oqfile->close();
delete oqfile;
oqfile = nullptr;
delete unitsformatter;
unitsformatter = nullptr;

if (!posnfilenametmp.isEmpty()) {
// QFile::rename() can't replace an existing file, so do a QFile::remove()
Expand Down Expand Up @@ -572,34 +576,28 @@ void KmlFormat::kml_output_trkdescription(const route_head* header, const comput
if (!header->rte_desc.isEmpty()) {
kml_td(hwriter, QStringLiteral("Description"), QStringLiteral(" %1 ").arg(header->rte_desc));
}
const char* distance_units;
double distance = fmt_distance(td->distance_meters, &distance_units);
auto [distance, distance_units] = unitsformatter->fmt_distance(td->distance_meters);
kml_td(hwriter, QStringLiteral("Distance"), QStringLiteral(" %1 %2 ").arg(QString::number(distance, 'f', 1), distance_units));
if (td->min_alt) {
const char* min_alt_units;
double min_alt = fmt_altitude(*td->min_alt, &min_alt_units);
auto [min_alt, min_alt_units] = unitsformatter->fmt_altitude(*td->min_alt);
kml_td(hwriter, QStringLiteral("Min Alt"), QStringLiteral(" %1 %2 ").arg(QString::number(min_alt, 'f', 3), min_alt_units));
}
if (td->max_alt) {
const char* max_alt_units;
double max_alt = fmt_altitude(*td->max_alt, &max_alt_units);
auto [max_alt, max_alt_units] = unitsformatter->fmt_altitude(*td->max_alt);
kml_td(hwriter, QStringLiteral("Max Alt"), QStringLiteral(" %1 %2 ").arg(QString::number(max_alt, 'f', 3), max_alt_units));
}
if (td->min_spd) {
const char* spd_units;
double spd = fmt_speed(*td->min_spd, &spd_units);
auto [spd, spd_units] = unitsformatter->fmt_speed(*td->min_spd);
kml_td(hwriter, QStringLiteral("Min Speed"), QStringLiteral(" %1 %2 ").arg(QString::number(spd, 'f', 1), spd_units));
}
if (td->max_spd) {
const char* spd_units;
double spd = fmt_speed(*td->max_spd, &spd_units);
auto [spd, spd_units] = unitsformatter->fmt_speed(*td->max_spd);
kml_td(hwriter, QStringLiteral("Max Speed"), QStringLiteral(" %1 %2 ").arg(QString::number(spd, 'f', 1), spd_units));
}
if (td->max_spd && td->start.isValid() && td->end.isValid()) {
double elapsed = td->start.msecsTo(td->end)/1000.0;
if (elapsed > 0.0) {
const char* spd_units;
double spd = fmt_speed(td->distance_meters / elapsed, &spd_units);
auto [spd, spd_units] = unitsformatter->fmt_speed(td->distance_meters / elapsed);
if (spd > 1.0) {
kml_td(hwriter, QStringLiteral("Avg Speed"), QStringLiteral(" %1 %2 ").arg(QString::number(spd, 'f', 1), spd_units));
}
Expand Down Expand Up @@ -723,17 +721,13 @@ void KmlFormat::kml_output_positioning(bool tessellate) const
/* Output something interesting when we can for route and trackpoints */
void KmlFormat::kml_output_description(const Waypoint* pt) const
{
const char* alt_units;

if (!trackdata) {
return;
}

QString hstring;
gpsbabel::XmlStreamWriter hwriter(&hstring);

double alt = fmt_altitude(pt->altitude, &alt_units);

writer->writeStartElement(QStringLiteral("description"));
hwriter.writeCharacters(QStringLiteral("\n"));
hwriter.writeStartElement(QStringLiteral("table"));
Expand All @@ -742,6 +736,7 @@ void KmlFormat::kml_output_description(const Waypoint* pt) const
kml_td(hwriter, QStringLiteral("Latitude: %1 ").arg(QString::number(pt->latitude, 'f', precision)));

if (kml_altitude_known(pt)) {
auto [alt, alt_units] = unitsformatter->fmt_altitude(pt->altitude);
kml_td(hwriter, QStringLiteral("Altitude: %1 %2 ").arg(QString::number(alt, 'f', 3), alt_units));
}

Expand All @@ -763,14 +758,12 @@ void KmlFormat::kml_output_description(const Waypoint* pt) const
}

if WAYPT_HAS(pt, depth) {
const char* depth_units;
double depth = fmt_distance(pt->depth, &depth_units);
auto [depth, depth_units] = unitsformatter->fmt_distance(pt->depth);
kml_td(hwriter, QStringLiteral("Depth: %1 %2 ").arg(QString::number(depth, 'f', 1), depth_units));
}

if WAYPT_HAS(pt, speed) {
const char* spd_units;
double spd = fmt_speed(pt->speed, &spd_units);
auto [spd, spd_units] = unitsformatter->fmt_speed(pt->speed);
kml_td(hwriter, QStringLiteral("Speed: %1 %2 ").arg(QString::number(spd, 'f', 1), spd_units));
}

Expand Down
2 changes: 2 additions & 0 deletions kml.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "src/core/datetime.h" // for DateTime
#include "src/core/file.h" // for File
#include "src/core/xmlstreamwriter.h" // for XmlStreamWriter
#include "units.h" // for UnitsFormatter
#include "xmlgeneric.h" // for cb_cdata, cb_end, cb_start, xg_callback, xg_string, xg_cb_type, xml_deinit, xml_ignore_tags, xml_init, xml_read, xg_tag_mapping


Expand Down Expand Up @@ -226,6 +227,7 @@ class KmlFormat : public Format
QList<gpsbabel::DateTime>* gx_trk_times{nullptr};
QList<std::tuple<int, double, double, double>>* gx_trk_coords{nullptr};

UnitsFormatter* unitsformatter{nullptr};
gpsbabel::File* oqfile{nullptr};
gpsbabel::XmlStreamWriter* writer{nullptr};

Expand Down
93 changes: 48 additions & 45 deletions units.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,50 +22,51 @@
#include "defs.h"
#include "units.h"

static int units = units_statute;

int
fmt_setunits(fmt_units u)
void
UnitsFormatter::setunits(units_t u)
{
switch (u) {
case units_statute:
case units_metric:
case units_nautical:
case units_aviation:
case units_t::statute:
case units_t::metric:
case units_t::nautical:
case units_t::aviation:
units = u;
return 0;
break;
default:
return 1;
fatal("not done yet");
break;
}
}

double
fmt_distance(const double distance_meters, const char** tag)
std::pair<double, QString>
UnitsFormatter::fmt_distance(const double distance_meters) const
{
double d;
const char* tag;

switch (units) {
case units_statute:
case units_t::statute:
d = METERS_TO_FEET(distance_meters);
if (d < 5280) {
*tag = "ft";
tag = "ft";
} else {
d = METERS_TO_MILES(distance_meters);
*tag = "mi";
tag = "mi";
}
break;
case units_nautical:
case units_aviation:
case units_t::nautical:
case units_t::aviation:
d = METERS_TO_NMILES(distance_meters);
*tag = "NM";
tag = "NM";
break;
case units_metric:
case units_t::metric:
d = distance_meters;
if (d < 1000) {
*tag = "meters";
tag = "meters";
} else {
d = d / 1000.0;
*tag = "km";
tag = "km";
}
break;

Expand All @@ -74,63 +75,65 @@ fmt_distance(const double distance_meters, const char** tag)
break;
}

return d;
return {d, tag};
}

double
fmt_altitude(const double distance_meters, const char** tag)
std::pair<double, QString>
UnitsFormatter::fmt_altitude(const double distance_meters) const
{
double d;
const char* tag;

switch (units) {
case units_statute:
case units_aviation:
case units_t::statute:
case units_t::aviation:
d = METERS_TO_FEET(distance_meters);
*tag = "ft";
tag = "ft";
break;
case units_nautical:
case units_t::nautical:
d = METERS_TO_NMILES(distance_meters);
*tag = "NM";
tag = "NM";
break;
case units_metric:
case units_t::metric:
d = distance_meters;
*tag = "meters";
tag = "meters";
break;

default:
fatal("not done yet");
break;
}

return d;
return {d, tag};
}

double
fmt_speed(const double distance_meters_sec, const char** tag)
std::pair<double, QString>
UnitsFormatter::fmt_speed(const double speed_meters_per_sec) const
{
double d;
const char* tag;

switch (units) {
case units_statute:
d = METERS_TO_MILES(distance_meters_sec) * SECONDS_PER_HOUR ;
*tag = "mph";
case units_t::statute:
d = METERS_TO_MILES(speed_meters_per_sec) * SECONDS_PER_HOUR ;
tag = "mph";
break;
case units_nautical:
case units_aviation:
d = METERS_TO_NMILES(distance_meters_sec) * SECONDS_PER_HOUR ;
*tag = "knts";
case units_t::nautical:
case units_t::aviation:
d = METERS_TO_NMILES(speed_meters_per_sec) * SECONDS_PER_HOUR ;
tag = "knts";
break;
case units_metric:
d = distance_meters_sec * SECONDS_PER_HOUR;
*tag = "meters/hour";
case units_t::metric:
d = speed_meters_per_sec * SECONDS_PER_HOUR;
tag = "meters/hour";
if (d > 1000.0) {
d /= 1000.0;
*tag = "km/hour";
tag = "km/hour";
}
break;
default:
fatal("not done yet");

}
return d;
return {d, tag};
}
39 changes: 24 additions & 15 deletions units.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,34 @@
#ifndef GPSBABEL_UNITS_H
#define GPSBABEL_UNITS_H

/*
* From units.c
*/
enum fmt_units {
units_unknown = 0,
units_statute = 1,
units_metric = 2,
units_nautical =3,
units_aviation =4
};
#include <utility> // for pair

#include <QString> // for QString

int fmt_setunits(fmt_units);

double fmt_distance(double, const char** tag);
class UnitsFormatter
{
public:

double fmt_altitude(double, const char** tag);
/* Types */

double fmt_speed(double, const char** tag);
enum class units_t {
statute,
metric,
nautical,
aviation
};

#include "defs.h"
/* Member Functions */

void setunits(units_t u);
std::pair<double, QString> fmt_distance(double distance_meters) const;
std::pair<double, QString> fmt_altitude(double distance_meters) const;
std::pair<double, QString> fmt_speed(double speed_meters_per_sec) const;

/* Data Members */

units_t units{units_t::statute};

};
#endif //GPSBABEL_UNITS_H

0 comments on commit 0ccae9f

Please sign in to comment.