Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance gpx test to validate gpx writer. #1191

Merged
merged 5 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions formspec.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
enum FsType {
kFsUnknown = 0L,
kFsGpx = 0x67707800L,
kFsGpxWpt = 0x67707877L,
kFsOzi = 0x6f7a6900L,
kFsGmsd = 0x474d5344L, /* GMSD = Garmin specific data */
kFsQstarzBl1000 = 0x5173747aL,
Expand Down
119 changes: 83 additions & 36 deletions gpx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,10 @@ GpxFormat::gpx_end(QStringView /*unused*/)
delete link_;
link_ = nullptr;
}
if (wpt_fsdata != nullptr) {
wpt_tmp->fs.FsChainAdd(wpt_fsdata);
wpt_fsdata = nullptr;
}
waypt_add(wpt_tmp);
logpoint_ct = 0;
cur_tag = nullptr;
Expand Down Expand Up @@ -621,6 +625,10 @@ GpxFormat::gpx_end(QStringView /*unused*/)
delete link_;
link_ = nullptr;
}
if (wpt_fsdata != nullptr) {
wpt_tmp->fs.FsChainAdd(wpt_fsdata);
wpt_fsdata = nullptr;
}
route_add_wpt(rte_head, wpt_tmp);
wpt_tmp = nullptr;
break;
Expand Down Expand Up @@ -665,6 +673,10 @@ GpxFormat::gpx_end(QStringView /*unused*/)
delete link_;
link_ = nullptr;
}
if (wpt_fsdata != nullptr) {
wpt_tmp->fs.FsChainAdd(wpt_fsdata);
wpt_fsdata = nullptr;
}
track_add_wpt(trk_head, wpt_tmp);
wpt_tmp = nullptr;
break;
Expand Down Expand Up @@ -727,6 +739,12 @@ GpxFormat::gpx_end(QStringView /*unused*/)
case tt_wpttype_time:
wpt_tmp->SetCreationTime(xml_parse_time(cdatastr));
break;
case tt_wpttype_magvar:
if (wpt_fsdata == nullptr) {
wpt_fsdata = new gpx_wpt_fsdata;
}
wpt_fsdata->magvar = cdatastr;
break;
case tt_wpttype_geoidheight:
wpt_tmp->set_geoidheight(cdatastr.toDouble());
break;
Expand All @@ -736,6 +754,18 @@ GpxFormat::gpx_end(QStringView /*unused*/)
case tt_wpttype_desc:
wpt_tmp->notes = cdatastr;
break;
case tt_wpttype_src:
if (wpt_fsdata == nullptr) {
wpt_fsdata = new gpx_wpt_fsdata;
}
wpt_fsdata->src = cdatastr;
break;
case tt_wpttype_type:
if (wpt_fsdata == nullptr) {
wpt_fsdata = new gpx_wpt_fsdata;
}
wpt_fsdata->type = cdatastr;
break;
case tt_wpttype_pdop:
wpt_tmp->pdop = cdatastr.toFloat();
break;
Expand All @@ -745,6 +775,18 @@ GpxFormat::gpx_end(QStringView /*unused*/)
case tt_wpttype_vdop:
wpt_tmp->vdop = cdatastr.toFloat();
break;
case tt_wpttype_ageofdgpsdata:
if (wpt_fsdata == nullptr) {
wpt_fsdata = new gpx_wpt_fsdata;
}
wpt_fsdata->ageofdgpsdata = cdatastr;
break;
case tt_wpttype_dgpsid:
if (wpt_fsdata == nullptr) {
wpt_fsdata = new gpx_wpt_fsdata;
}
wpt_fsdata->dgpsid = cdatastr;
break;
case tt_wpttype_sat:
wpt_tmp->sat = cdatastr.toInt();
break;
Expand Down Expand Up @@ -1065,7 +1107,7 @@ GpxFormat::write_attributes(const QXmlStreamAttributes& attributes) const
}

void
GpxFormat::fprint_xml_chain(XmlTag* tag, const Waypoint* wpt) const
GpxFormat::fprint_xml_chain(XmlTag* tag) const
{
while (tag) {
writer->writeStartElement(tag->tagname);
Expand All @@ -1078,7 +1120,7 @@ GpxFormat::fprint_xml_chain(XmlTag* tag, const Waypoint* wpt) const
writer->writeCharacters(tag->cdata);
}
if (tag->child) {
fprint_xml_chain(tag->child, wpt);
fprint_xml_chain(tag->child);
}
writer->writeEndElement();
}
Expand Down Expand Up @@ -1138,7 +1180,7 @@ GpxFormat::write_gpx_url(const route_head* rh) const
* Order counts.
*/
void
GpxFormat::gpx_write_common_acc(const Waypoint* waypointp) const
GpxFormat::gpx_write_common_acc(const Waypoint* waypointp, const gpx_wpt_fsdata* fs_gpxwpt) const
{
const char* fix = nullptr;

Expand Down Expand Up @@ -1179,13 +1221,15 @@ GpxFormat::gpx_write_common_acc(const Waypoint* waypointp) const
if (waypointp->pdop) {
writer->writeTextElement(QStringLiteral("pdop"), toString(waypointp->pdop));
}
/* TODO: ageofdgpsdata should go here */
/* TODO: dgpsid should go here */
if (fs_gpxwpt) {
writer->writeOptionalTextElement(QStringLiteral("ageofdgpsdata"), fs_gpxwpt->ageofdgpsdata);
writer->writeOptionalTextElement(QStringLiteral("dgpsid"), fs_gpxwpt->dgpsid);
}
}


void
GpxFormat::gpx_write_common_position(const Waypoint* waypointp, const gpx_point_type point_type) const
GpxFormat::gpx_write_common_position(const Waypoint* waypointp, const gpx_point_type point_type, const gpx_wpt_fsdata* fs_gpxwpt) const
{
if (waypointp->altitude != unknown_alt) {
writer->writeTextElement(QStringLiteral("ele"), QString::number(waypointp->altitude, 'f', elevation_precision));
Expand All @@ -1201,7 +1245,9 @@ GpxFormat::gpx_write_common_position(const Waypoint* waypointp, const gpx_point_
writer->writeTextElement(QStringLiteral("speed"), toString(waypointp->speed_value()));
}
}
/* TODO: magvar should go here */
if (fs_gpxwpt) {
writer->writeOptionalTextElement(QStringLiteral("magvar"), fs_gpxwpt->magvar);
}
if (waypointp->geoidheight_has_value()) {
writer->writeOptionalTextElement(QStringLiteral("geoidheight"),QString::number(waypointp->geoidheight_value(), 'f', 1));
}
Expand Down Expand Up @@ -1294,8 +1340,13 @@ GpxFormat::gpx_write_common_extensions(const Waypoint* waypointp, const gpx_poin
}

void
GpxFormat::gpx_write_common_description(const Waypoint* waypointp, const QString& oname) const
GpxFormat::gpx_write_common_description(const Waypoint* waypointp, const gpx_point_type point_type, const gpx_wpt_fsdata* fs_gpxwpt) const
{
QString oname;
if (!((point_type == gpxpt_track) && waypointp->wpt_flags.shortname_is_synthetic)) {
oname = global_opts.synthesize_shortnames ?
mkshort_handle->mkshort_from_wpt(waypointp) : waypointp->shortname;
}
writer->writeOptionalTextElement(QStringLiteral("name"), oname);

writer->writeOptionalTextElement(QStringLiteral("cmt"), waypointp->description);
Expand All @@ -1304,10 +1355,24 @@ GpxFormat::gpx_write_common_description(const Waypoint* waypointp, const QString
} else {
writer->writeOptionalTextElement(QStringLiteral("desc"), waypointp->description);
}
/* TODO: src should go here */
if (fs_gpxwpt) {
writer->writeOptionalTextElement(QStringLiteral("src"), fs_gpxwpt->src);
}
write_gpx_url(waypointp);
writer->writeOptionalTextElement(QStringLiteral("sym"), waypointp->icon_descr);
/* TODO: type should go here */
if (fs_gpxwpt) {
writer->writeOptionalTextElement(QStringLiteral("type"), fs_gpxwpt->type);
}
}

void GpxFormat::gpx_write_common_core(const Waypoint* waypointp,
const gpx_point_type point_type) const
{
const auto* fs_gpxwpt = reinterpret_cast<gpx_wpt_fsdata*>(waypointp->fs.FsChainFind(kFsGpxWpt));

gpx_write_common_position(waypointp, point_type, fs_gpxwpt);
gpx_write_common_description(waypointp, point_type, fs_gpxwpt);
gpx_write_common_acc(waypointp, fs_gpxwpt);
}

void
Expand All @@ -1317,19 +1382,14 @@ GpxFormat::gpx_waypt_pr(const Waypoint* waypointp) const
writer->writeAttribute(QStringLiteral("lat"), toString(waypointp->latitude));
writer->writeAttribute(QStringLiteral("lon"), toString(waypointp->longitude));

QString oname = global_opts.synthesize_shortnames ?
mkshort_handle->mkshort_from_wpt(waypointp) :
waypointp->shortname;
gpx_write_common_position(waypointp, gpxpt_waypoint);
gpx_write_common_description(waypointp, oname);
gpx_write_common_acc(waypointp);
gpx_write_common_core(waypointp, gpxpt_waypoint);

if (!(opt_humminbirdext || opt_garminext)) {
const auto* fs_gpx = reinterpret_cast<fs_xml*>(waypointp->fs.FsChainFind(kFsGpx));
auto* gmsd = garmin_fs_t::find(waypointp); /* gARmIN sPECIAL dATA */
if (fs_gpx) {
if (! gmsd) {
fprint_xml_chain(fs_gpx->tag, waypointp);
fprint_xml_chain(fs_gpx->tag);
}
}
if (gmsd && (gpx_write_version > gpx_1_0)) {
Expand Down Expand Up @@ -1360,7 +1420,7 @@ GpxFormat::gpx_track_hdr(const route_head* rte)
if (!(opt_humminbirdext || opt_garminext)) {
const auto* fs_gpx = reinterpret_cast<fs_xml*>(rte->fs.FsChainFind(kFsGpx));
if (fs_gpx) {
fprint_xml_chain(fs_gpx->tag, nullptr);
fprint_xml_chain(fs_gpx->tag);
}
} else if (opt_garminext) {
if (rte->line_color.bbggrr > unknown_color) {
Expand Down Expand Up @@ -1394,20 +1454,12 @@ GpxFormat::gpx_track_disp(const Waypoint* waypointp) const
writer->writeAttribute(QStringLiteral("lat"), toString(waypointp->latitude));
writer->writeAttribute(QStringLiteral("lon"), toString(waypointp->longitude));

gpx_write_common_position(waypointp, gpxpt_track);

QString oname = global_opts.synthesize_shortnames ?
mkshort_handle->mkshort_from_wpt(waypointp) :
waypointp->shortname;
gpx_write_common_description(waypointp,
waypointp->wpt_flags.shortname_is_synthetic ?
nullptr : oname);
gpx_write_common_acc(waypointp);
gpx_write_common_core(waypointp, gpxpt_track);

if (!(opt_humminbirdext || opt_garminext)) {
const auto* fs_gpx = reinterpret_cast<fs_xml*>(waypointp->fs.FsChainFind(kFsGpx));
if (fs_gpx) {
fprint_xml_chain(fs_gpx->tag, waypointp);
fprint_xml_chain(fs_gpx->tag);
}
} else {
gpx_write_common_extensions(waypointp, gpxpt_track);
Expand Down Expand Up @@ -1458,7 +1510,7 @@ GpxFormat::gpx_route_hdr(const route_head* rte) const
if (!(opt_humminbirdext || opt_garminext)) {
const auto* fs_gpx = reinterpret_cast<fs_xml*>(rte->fs.FsChainFind(kFsGpx));
if (fs_gpx) {
fprint_xml_chain(fs_gpx->tag, nullptr);
fprint_xml_chain(fs_gpx->tag);
}
} else if (opt_garminext) {
if (rte->line_color.bbggrr > unknown_color) {
Expand All @@ -1485,17 +1537,12 @@ GpxFormat::gpx_route_disp(const Waypoint* waypointp) const
writer->writeAttribute(QStringLiteral("lat"), toString(waypointp->latitude));
writer->writeAttribute(QStringLiteral("lon"), toString(waypointp->longitude));

QString oname = global_opts.synthesize_shortnames ?
mkshort_handle->mkshort_from_wpt(waypointp) :
waypointp->shortname;
gpx_write_common_position(waypointp, gpxpt_route);
gpx_write_common_description(waypointp, oname);
gpx_write_common_acc(waypointp);
gpx_write_common_core(waypointp, gpxpt_route);

if (!(opt_humminbirdext || opt_garminext)) {
const auto* fs_gpx = reinterpret_cast<fs_xml*>(waypointp->fs.FsChainFind(kFsGpx));
if (fs_gpx) {
fprint_xml_chain(fs_gpx->tag, waypointp);
fprint_xml_chain(fs_gpx->tag);
}
} else {
gpx_write_common_extensions(waypointp, gpxpt_route);
Expand Down
42 changes: 37 additions & 5 deletions gpx.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,28 @@ class GpxFormat : public Format
void exit() override;

private:
/*
* This structure holds the element contents of elements in the
* the gpx namespace that are only passed from the gpx reader to
* the gpx writer.
* We explcitly write these instead of passing them through so they
* are written in the correct sequence.
*/
struct gpx_wpt_fsdata : FormatSpecificData {
gpx_wpt_fsdata() : FormatSpecificData(kFsGpxWpt) {}

gpx_wpt_fsdata* clone() const override
{
return new gpx_wpt_fsdata(*this);
}

QString magvar;
QString src;
QString type;
QString ageofdgpsdata;
QString dgpsid;
};

enum gpx_point_type {
gpxpt_waypoint,
gpxpt_track,
Expand All @@ -91,10 +113,12 @@ class GpxFormat : public Format
tt_wpt,
tt_wpttype_ele,
tt_wpttype_time,
tt_wpttype_magvar,
tt_wpttype_geoidheight,
tt_wpttype_name,
tt_wpttype_cmt,
tt_wpttype_desc,
tt_wpttype_src,
tt_wpttype_url, /* Not in GPX 1.1 */
tt_wpttype_urlname, /* Not in GPX 1.1 */
tt_wpttype_link, /* New in GPX 1.1 */
Expand All @@ -107,6 +131,8 @@ class GpxFormat : public Format
tt_wpttype_hdop, /* HDOPS are common for all three */
tt_wpttype_vdop, /* VDOPS are common for all three */
tt_wpttype_pdop, /* PDOPS are common for all three */
tt_wpttype_ageofdgpsdata,
tt_wpttype_dgpsid,
tt_cache,
tt_cache_name,
tt_cache_container,
Expand Down Expand Up @@ -197,15 +223,16 @@ class GpxFormat : public Format
void gpx_cdata(QStringView s);
QString qualifiedName() const;
void write_attributes(const QXmlStreamAttributes& attributes) const;
void fprint_xml_chain(XmlTag* tag, const Waypoint* wpt) const;
void fprint_xml_chain(XmlTag* tag) const;
void write_gpx_url(const UrlList& urls) const;
void write_gpx_url(const Waypoint* waypointp) const;
void write_gpx_url(const route_head* rh) const;
void gpx_write_common_acc(const Waypoint* waypointp) const;
void gpx_write_common_position(const Waypoint* waypointp, gpx_point_type point_type) const;
void gpx_write_common_acc(const Waypoint* waypointp, const gpx_wpt_fsdata* fs_gpxwpt) const;
void gpx_write_common_position(const Waypoint* waypointp, gpx_point_type point_type, const gpx_wpt_fsdata* fs_gpxwpt) const;
void gpx_write_common_extensions(const Waypoint* waypointp, gpx_point_type point_type) const;
void gpx_write_common_description(const Waypoint* waypointp, const QString& oname) const;
void gpx_write_common_description(const Waypoint* waypointp, gpx_point_type point_type, const gpx_wpt_fsdata* fs_gpxwpt) const;
void gpx_waypt_pr(const Waypoint* waypointp) const;
void gpx_write_common_core(const Waypoint* waypointp, gpx_point_type point_type) const;
void gpx_track_hdr(const route_head* rte);
void gpx_track_disp(const Waypoint* waypointp) const;
void gpx_track_tlr(const route_head* unused);
Expand Down Expand Up @@ -261,6 +288,7 @@ class GpxFormat : public Format
int next_trkpt_is_new_seg{};

FormatSpecificDataList* fs_ptr{};
gpx_wpt_fsdata* wpt_fsdata{nullptr};

/*
* The file-level information.
Expand Down Expand Up @@ -409,22 +437,26 @@ class GpxFormat : public Format
/* Common to tracks, routes, and waypts */
GPXWPTTYPETAG("ele", tt_wpttype_ele, false),
GPXWPTTYPETAG("time", tt_wpttype_time, false),
GPXWPTTYPETAG("magvar", tt_wpttype_magvar, false),
GPXWPTTYPETAG("geoidheight", tt_wpttype_geoidheight, false),
GPXWPTTYPETAG("name", tt_wpttype_name, false),
GPXWPTTYPETAG("cmt", tt_wpttype_cmt, false),
GPXWPTTYPETAG("desc", tt_wpttype_desc, false),
GPXWPTTYPETAG("src", tt_wpttype_src, false),
GPXWPTTYPETAG("url", tt_wpttype_url, false), /* GPX 1.0 */
GPXWPTTYPETAG("urlname", tt_wpttype_urlname, false), /* GPX 1.0 */
GPXWPTTYPETAG("link", tt_wpttype_link, false), /* GPX 1.1 */
GPXWPTTYPETAG("link/text", tt_wpttype_link_text, false), /* GPX 1.1 */
GPXWPTTYPETAG("link/type", tt_wpttype_link_type, false), /* GPX 1.1 */
GPXWPTTYPETAG("sym", tt_wpttype_sym, false),
GPXWPTTYPETAG("type", tt_wpttype_type, true),
GPXWPTTYPETAG("type", tt_wpttype_type, false),
GPXWPTTYPETAG("fix", tt_wpttype_fix, false),
GPXWPTTYPETAG("sat", tt_wpttype_sat, false),
GPXWPTTYPETAG("hdop", tt_wpttype_hdop, false),
GPXWPTTYPETAG("vdop", tt_wpttype_vdop, false),
GPXWPTTYPETAG("pdop", tt_wpttype_pdop, false),
GPXWPTTYPETAG("ageofdgpsdata", tt_wpttype_ageofdgpsdata, false),
GPXWPTTYPETAG("dgpsid", tt_wpttype_dgpsid, false),
};

QVector<arglist_t> gpx_args = {
Expand Down
2 changes: 2 additions & 0 deletions reference/basecamp~gpx.gpx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<cmt>Hwy 119</cmt>
<desc>Hwy 119</desc>
<sym>Flag, Blue</sym>
<type>user</type>
<extensions>
<gpxx:WaypointExtension xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3">
<gpxx:DisplayMode>SymbolAndName</gpxx:DisplayMode>
Expand All @@ -25,6 +26,7 @@
<cmt>Hwy 72</cmt>
<desc>Hwy 72</desc>
<sym>Flag, Blue</sym>
<type>user</type>
<extensions>
<gpxx:WaypointExtension xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3">
<gpxx:DisplayMode>SymbolAndName</gpxx:DisplayMode>
Expand Down
Loading