changes to the markers in google maps.

blue marker = start of ride
red marker = end of ride
green markers = interval markers.

interval markers has the interval metrics displayed.
end marker has the ride summary displayed.

Fixes #169.
This commit is contained in:
Greg Lonnon
2011-01-02 07:16:14 -07:00
committed by Mark Liversedge
parent 550ae22aa3
commit 93ad436c6a
2 changed files with 144 additions and 68 deletions

View File

@@ -23,11 +23,11 @@
#include "Zones.h"
#include "Settings.h"
#include "Units.h"
#include "TimeUtils.h"
#include <QDebug>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
@@ -115,7 +115,10 @@ namespace gm
totalHR += rfp.hr;
samples++;
}
int HR() { return totalHR / samples; }
int HR() {
if(samples == 0) return 0;
return totalHR / samples;
}
operator int() { return HR(); }
};
@@ -238,7 +241,7 @@ void GoogleMapControl::loadRide()
if(newRideToLoad == true)
{
createHtml();
createHtml(current);
newRideToLoad = false;
loadingPage = true;
@@ -257,7 +260,7 @@ void GoogleMapControl::loadRide()
}
}
void GoogleMapControl::createHtml()
void GoogleMapControl::createHtml(RideItem *ride)
{
currentPage.str("");
double minLat, minLon, maxLat, maxLon;
@@ -305,7 +308,7 @@ void GoogleMapControl::createHtml()
<< " {size: new GSize(" << width << "," << height << ") } );" << endl
<< "map.setUIToDefault()" << endl
<< CreatePolyLine() << endl
<< CreateIntervalMarkers() << endl
<< CreateMarkers(ride) << endl
<< "var sw = new GLatLng(" << minLat << "," << minLon << ");" << endl
<< "var ne = new GLatLng(" << maxLat << "," << maxLon << ");" << endl
<< "var bounds = new GLatLngBounds(sw,ne);" << endl
@@ -404,77 +407,146 @@ void GoogleMapControl::CreateSubPolyLine(const std::vector<RideFilePoint> &point
oss << "map.addOverlay (polyline);" << endl;
}
string GoogleMapControl::CreateIntervalMarkers()
string GoogleMapControl::CreateIntervalMarkers(RideItem *rideItem)
{
bool useMetricUnits = (GetApplicationSettings()->value(GC_UNIT).toString()
== "Metric");
ostringstream oss;
RideFile *ride = rideItem->ride();
if(ride->intervals().size() == 0)
return "";
boost::shared_ptr<QSettings> settings = GetApplicationSettings();
QVariant unit = settings->value(GC_UNIT);
bool metricUnits = (unit.toString() == "Metric");
QString s;
if (settings->contains(GC_SETTINGS_INTERVAL_METRICS))
s = settings->value(GC_SETTINGS_INTERVAL_METRICS).toString();
else
s = GC_SETTINGS_INTERVAL_METRICS_DEFAULT;
QStringList intervalMetrics = s.split(",");
int row = 0;
foreach (RideFileInterval interval, ride->intervals()) {
// create a temp RideFile to be used to figure out the metrics for the interval
RideFile f(ride->startTime(), ride->recIntSecs());
for (int i = ride->intervalBegin(interval); i < ride->dataPoints().size(); ++i) {
const RideFilePoint *p = ride->dataPoints()[i];
if (p->secs >= interval.stop)
break;
f.appendPoint(p->secs, p->cad, p->hr, p->km, p->kph, p->nm,
p->watts, p->alt, p->lon, p->lat, p->headwind, 0);
}
if (f.dataPoints().size() == 0) {
// Interval empty, do not compute any metrics
continue;
}
QHash<QString,RideMetricPtr> metrics =
RideMetric::computeMetrics(&f, parent->zones(), parent->hrZones(), intervalMetrics);
string html = CreateIntervalHtml(metrics,intervalMetrics,interval.name,metricUnits);
row++;
oss << CreateMarker(row,f.dataPoints().front()->lat,f.dataPoints().front()->lon,html);
}
return oss.str();
}
string GoogleMapControl::CreateIntervalHtml(QHash<QString,RideMetricPtr> &metrics, QStringList &intervalMetrics,
QString &intervalName, bool metricUnits)
{
ostringstream oss;
oss << "<p><h2>" << intervalName.toStdString() << "</h2>";
oss << "<table align=\\\"center\\\" cellspacing=0 border=0>";
int row = 0;
foreach (QString symbol, intervalMetrics) {
RideMetricPtr m = metrics.value(symbol);
if(m == NULL)
continue;
if (row % 2)
oss << "<tr>";
else {
QColor color = QApplication::palette().alternateBase().color();
color = QColor::fromHsv(color.hue(), color.saturation() * 2, color.value());
oss << "<tr bgcolor='" + color.name().toStdString() << "'>";
}
oss.setf(ios::fixed);
oss.precision(m->precision());
oss << "<td align=\\\"left\\\">" + m->name().toStdString() << "</td>";
oss << "<td align=\\\"left\\\">";
if (m->units(metricUnits) == "seconds")
oss << time_to_string(m->value(metricUnits)).toStdString();
else
{
oss << m->value(metricUnits);
oss << " " << m->units(metricUnits).toStdString();
}
oss <<"</td>";
oss << "</tr>";
row++;
}
oss << "</table>";
return oss.str();
}
string GoogleMapControl::CreateMarkers(RideItem *ride)
{
ostringstream oss;
oss.precision(6);
oss.setf(ios::fixed,ios::floatfield);
// start marker
oss << "var marker;" << endl;
int currentInterval = 0;
std::vector<RideFilePoint> intervalPoints;
BOOST_FOREACH(RideFilePoint rfp, rideData)
{
intervalPoints.push_back(rfp);
if(currentInterval < rfp.interval)
{
// want to see avg power, avg speed, alt changes, avg hr
double distance = intervalPoints.back().km -
intervalPoints.front().km ;
distance = (useMetricUnits ? distance : distance * MILES_PER_KM);
oss << "var blueIcon = new GIcon(G_DEFAULT_ICON);" << endl;
oss << "blueIcon.image = \"http://gmaps-samples.googlecode.com/svn/trunk/markers/blue/blank.png\"" << endl;
oss << "markerOptions = { icon:blueIcon };" << endl;
oss << "marker = new GMarker(new GLatLng(";
oss << rideData.front().lat << "," << rideData.front().lon << "),blueIcon);" << endl;
oss << "marker.bindInfoWindowHtml(\"<h3>Start</h3>\");" << endl;
oss << "map.addOverlay(marker);" << endl;
int secs = intervalPoints.back().secs -
intervalPoints.front().secs;
oss << CreateIntervalMarkers(ride);
double avgSpeed = (distance/((double)secs)) * 3600;
// end marker
boost::shared_ptr<QSettings> settings = GetApplicationSettings();
QVariant unit = settings->value(GC_UNIT);
bool metricUnits = (unit.toString() == "Metric");
QTime time;
time = time.addSecs(secs);
QString s;
if (settings->contains(GC_SETTINGS_INTERVAL_METRICS))
s = settings->value(GC_SETTINGS_INTERVAL_METRICS).toString();
else
s = GC_SETTINGS_INTERVAL_METRICS_DEFAULT;
QStringList intervalMetrics = s.split(",");
QHash<QString,RideMetricPtr> metrics =
RideMetric::computeMetrics(ride->ride(), parent->zones(), parent->hrZones(), intervalMetrics);
QString name = "Ride Summary";
string html = CreateIntervalHtml(metrics,intervalMetrics,name,metricUnits);
oss << "var redIcon = new GIcon(G_DEFAULT_ICON);" << endl;
oss << "redIcon.image = \"http://gmaps-samples.googlecode.com/svn/trunk/markers/red/blank.png\"" << endl;
oss << "markerOptions = { icon:redIcon };" << endl;
oss << "marker = new GMarker(new GLatLng(";
oss << rideData.back().lat << "," << rideData.back().lon << "),redIcon);" << endl;
oss << "marker.bindInfoWindowHtml(\""<< html << "\");" << endl;
oss << "map.addOverlay(marker);" << endl;
return oss.str();
}
AvgHR avgHr = for_each(intervalPoints.begin(),
intervalPoints.end(),
AvgHR());
AvgPower avgPower = for_each(intervalPoints.begin(),
intervalPoints.end(),
AvgPower());
int altGained =ceil(for_each(intervalPoints.begin(),
intervalPoints.end(),
AltGained()));
altGained = ceil((useMetricUnits ? altGained :
altGained * FEET_PER_METER));
oss.precision(6);
oss << "marker = new GMarker(new GLatLng( ";
oss<< rfp.lat << "," << rfp.lon << "));" << endl;
oss << "marker.bindInfoWindowHtml(" <<endl;
oss << "\"<p><h3>Lap: " << currentInterval << "</h3></p>" ;
oss.precision(1);
oss << "<p>Distance: " << distance << " "
<< (useMetricUnits ? "KM" : "Miles") << "</p>" ;
oss << "<p>Time: " << time.toString().toStdString() << "</p>";
oss << "<p>Avg Speed</>: " << avgSpeed << " "
<< (useMetricUnits ? tr("KPH") : tr("MPH")).toStdString()
<< "</p>";
if(avgHr != 0) {
oss << "<p>Avg HR: " << avgHr << "</p>";
}
if(avgPower != 0)
{
oss << "<p>Avg Power: " << avgPower << " Watts</p>";
}
oss << "<p>Alt Gained: " << altGained << " "
<< (useMetricUnits ? tr("Meters") : tr("Feet")).toStdString()
<< "</p>";
oss << "\");" << endl;
oss << "map.addOverlay(marker);" << endl;
currentInterval = rfp.interval;
intervalPoints.clear();
}
}
std::string GoogleMapControl::CreateMarker(int number, double lat, double lon, string &html)
{
ostringstream oss;
oss.precision(6);
oss << "intervalIcon = new GIcon(G_DEFAULT_ICON);" << endl;
oss << "intervalIcon.image = \"http://gmaps-samples.googlecode.com/svn/trunk/markers/green/marker" << number << ".png\"" << endl;
oss << "markerOptions = { icon:intervalIcon };" << endl;
oss << "marker = new GMarker(new GLatLng( ";
oss<< lat << "," << lon << "),intervalIcon);" << endl;
oss << "marker.bindInfoWindowHtml(\"" << html << "\");";
oss.precision(1);
oss << "map.addOverlay(marker);" << endl;
return oss.str();
}