diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e12d0013..80652376c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,7 @@ set(SUPPORT src/core/textstream.cc src/core/usasciicodec.cc src/core/vector3d.cc + src/core/welzl.cc src/core/xmlstreamwriter.cc ) if(${QT_VERSION_MAJOR} EQUAL "6") @@ -193,6 +194,7 @@ set(HEADERS src/core/textstream.h src/core/usasciicodec.h src/core/vector3d.h + src/core/welzl.h src/core/xmlstreamwriter.h src/core/xmltag.h ) diff --git a/GPSBabel.pro b/GPSBabel.pro index 00bc8d03c..924bd3d2c 100644 --- a/GPSBabel.pro +++ b/GPSBabel.pro @@ -111,6 +111,7 @@ SUPPORT = route.cc waypt.cc filter_vecs.cc util.cc vecs.cc mkshort.cc \ src/core/textstream.cc \ src/core/usasciicodec.cc \ src/core/vector3d.cc \ + src/core/welzl.cc \ src/core/xmlstreamwriter.cc versionAtLeast(QT_VERSION, 6.0): SUPPORT += src/core/codecdevice.cc @@ -190,6 +191,7 @@ HEADERS = \ src/core/textstream.h \ src/core/usasciicodec.h \ src/core/vector3d.h \ + src/core/welzl.h \ src/core/xmlstreamwriter.h \ src/core/xmltag.h diff --git a/kml.cc b/kml.cc index 695b30d65..94f5058a0 100644 --- a/kml.cc +++ b/kml.cc @@ -49,6 +49,7 @@ #include "src/core/datetime.h" // for DateTime #include "src/core/file.h" // for File #include "src/core/logging.h" // for Warning, Fatal +#include "src/core/welzl.h" #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 @@ -364,7 +365,7 @@ void KmlFormat::rd_deinit() void KmlFormat::wr_init(const QString& fname) { char u = 's'; - waypt_init_bounds(&kml_bounds); + kml_points.clear(); kml_time_min = QDateTime(); kml_time_max = QDateTime(); @@ -814,7 +815,7 @@ void KmlFormat::kml_recompute_time_bounds(const Waypoint* waypointp) void KmlFormat::kml_add_to_bounds(const Waypoint* waypointp) { - waypt_add_to_bounds(&kml_bounds, waypointp); + kml_points.push_back(gpsbabel::NVector(waypointp->latitude, waypointp->longitude)); kml_recompute_time_bounds(waypointp); } @@ -1682,6 +1683,8 @@ void KmlFormat::kml_write_AbstractView() route_disp_all(nullptr, nullptr, kml_add_to_bounds_lambda); } + gpsbabel::Circle bounds = gpsbabel::Welzl::welzl(kml_points); + writer->writeStartElement(QStringLiteral("LookAt")); if (kml_time_min.isValid() || kml_time_max.isValid()) { @@ -1704,25 +1707,19 @@ void KmlFormat::kml_write_AbstractView() writer->writeEndElement(); // Close gx:TimeSpan tag } -// If our BB spans the antemeridian, flip sign on one. -// This doesn't make our BB optimal, but it at least prevents us from -// zooming to the wrong hemisphere. - if (kml_bounds.min_lon * kml_bounds.max_lon < 0) { - kml_bounds.min_lon = -kml_bounds.max_lon; - } - - writer->writeTextElement(QStringLiteral("longitude"), QString::number((kml_bounds.min_lon + kml_bounds.max_lon) / 2, 'f', precision)); - writer->writeTextElement(QStringLiteral("latitude"), QString::number((kml_bounds.min_lat + kml_bounds.max_lat) / 2, 'f', precision)); + writer->writeTextElement(QStringLiteral("longitude"), QString::number(bounds.center().longitude(), 'f', precision)); + writer->writeTextElement(QStringLiteral("latitude"), QString::number(bounds.center().latitude(), 'f', precision)); // It turns out the length of the diagonal of the bounding box gives us a // reasonable guess for setting the camera altitude. - double bb_size = gcgeodist(kml_bounds.min_lat, kml_bounds.min_lon, - kml_bounds.max_lat, kml_bounds.max_lon); + // TODO: we can easily calculate a range such that the camera sees a bit beyond the points + // for the cases that the range is reasonable. + double bb_size = 2.0 * bounds.radius(); // Clamp bottom zoom level. Otherwise, a single point zooms to grass. if (bb_size < 1000) { bb_size = 1000; } - writer->writeTextElement(QStringLiteral("range"), QString::number(bb_size * 1.3, 'f', 6)); + writer->writeTextElement(QStringLiteral("range"), QString::number(bb_size * 1.3, 'f', 3)); writer->writeEndElement(); // Close LookAt tag } diff --git a/kml.h b/kml.h index d324b167f..2533ba4cc 100644 --- a/kml.h +++ b/kml.h @@ -33,6 +33,8 @@ #include "format.h" #include "src/core/datetime.h" // for DateTime #include "src/core/file.h" // for File +#include "src/core/nvector.h" +#include "src/core/welzl.h" #include "src/core/xmlstreamwriter.h" // for XmlStreamWriter #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 @@ -216,7 +218,7 @@ class KmlFormat : public Format gpsbabel::XmlStreamWriter* writer{nullptr}; int realtime_positioning{}; - bounds kml_bounds{}; + gpsbabel::PointContainer kml_points; gpsbabel::DateTime kml_time_max; gpsbabel::DateTime kml_time_min; diff --git a/reference/LineStyles.kml b/reference/LineStyles.kml index 77c81ca37..79ad33378 100644 --- a/reference/LineStyles.kml +++ b/reference/LineStyles.kml @@ -3,9 +3,9 @@ GPS device - -122.275670 - 37.523278 - 5908.813619 + -122.276195 + 37.523328 + 5678.471 - + - + - + - Heart Rate + Heart Rate - Cadence + Cadence - Power + Power diff --git a/reference/track/segmented_tracks-track.kml b/reference/track/segmented_tracks-track.kml index 9e3e70ee2..31d7c829d 100644 --- a/reference/track/segmented_tracks-track.kml +++ b/reference/track/segmented_tracks-track.kml @@ -7,9 +7,9 @@ 2007-07-27T05:24:05Z 2007-07-27T05:35:00Z - -86.841461 + -86.841519 35.831217 - 1944.793167 + 1901.182