mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
Added Map and StreetView charts to the TrainTool.
Following changes * added google Map and Streetview charts. * changed the telemetryUpdate to use a const reference instead of a value. * RealtimeData is const correct, or more const correct than it was... * added a new resource files to support the new charts. * changed the NullController to return a constant speed to help with development.
This commit is contained in:
@@ -85,7 +85,7 @@ DialWindow::pause()
|
||||
}
|
||||
|
||||
void
|
||||
DialWindow::telemetryUpdate(RealtimeData rtData)
|
||||
DialWindow::telemetryUpdate(const RealtimeData &rtData)
|
||||
{
|
||||
// we got some!
|
||||
RealtimeData::DataSeries series = static_cast<RealtimeData::DataSeries>
|
||||
|
||||
@@ -68,7 +68,7 @@ class DialWindow : public GcWindow
|
||||
public slots:
|
||||
|
||||
// trap signals
|
||||
void telemetryUpdate(RealtimeData rtData); // got new data
|
||||
void telemetryUpdate(const RealtimeData &rtData); // got new data
|
||||
void lap(int lapnumber);
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
@@ -77,6 +77,8 @@ GcWindowRegistry GcWindows[] = {
|
||||
{ "Realtime Dial",GcWindowTypes::DialWindow },
|
||||
{ "Realtime Plot",GcWindowTypes::RealtimePlot },
|
||||
{ "Workout Plot",GcWindowTypes::WorkoutPlot },
|
||||
{ "Train Map Window", GcWindowTypes::MapWindow },
|
||||
{ "Train StreetView Window", GcWindowTypes::StreetViewWindow },
|
||||
{ "", GcWindowTypes::None }};
|
||||
|
||||
// instantiate a new window
|
||||
@@ -122,6 +124,8 @@ GcWindowRegistry::newGcWindow(GcWinID id, MainWindow *main) //XXX mainWindow wil
|
||||
case GcWindowTypes::RealtimePlot: returning = new RealtimePlotWindow(main); break;
|
||||
case GcWindowTypes::WorkoutPlot: returning = new WorkoutPlotWindow(main); break;
|
||||
case GcWindowTypes::BingMap: returning = new BingMap(main); break;
|
||||
case GcWindowTypes::MapWindow: returning = new MapWindow(main); break;
|
||||
case GcWindowTypes::StreetViewWindow: returning = new StreetViewWindow(main); break;
|
||||
default: return NULL; break;
|
||||
}
|
||||
if (returning) returning->setProperty("type", QVariant::fromValue<GcWinID>(id));
|
||||
|
||||
@@ -51,8 +51,10 @@ enum gcwinid {
|
||||
MetadataWindow = 23,
|
||||
RealtimePlot = 24,
|
||||
WorkoutPlot = 25,
|
||||
BingMap = 26,
|
||||
RealtimeControls = 27
|
||||
MapWindow = 26,
|
||||
StreetViewWindow = 27,
|
||||
BingMap = 28,
|
||||
RealtimeControls = 29,
|
||||
};
|
||||
};
|
||||
typedef enum GcWindowTypes::gcwinid GcWinID;
|
||||
|
||||
@@ -142,7 +142,7 @@ class MainWindow : public QMainWindow
|
||||
void notifyRideDirty() { rideDirty(); }
|
||||
|
||||
// realtime signals
|
||||
void notifyTelemetryUpdate(RealtimeData rtData) { telemetryUpdate(rtData); }
|
||||
void notifyTelemetryUpdate(const RealtimeData &rtData) { telemetryUpdate(rtData); }
|
||||
void notifyErgFileSelected(ErgFile *x) { ergFileSelected(x); }
|
||||
void notifySetNow(long now) { setNow(now); }
|
||||
|
||||
|
||||
@@ -46,10 +46,11 @@ int NullController::restart() {
|
||||
}
|
||||
|
||||
void NullController::getRealtimeData(RealtimeData &rtData) {
|
||||
RealtimeData null;
|
||||
null.setName((char *)"Null");
|
||||
null.setWatts(load);
|
||||
rtData = null;
|
||||
rtData.setName((char *)"Null");
|
||||
rtData.setWatts(load);
|
||||
rtData.setSpeed(20);
|
||||
rtData.setCadence(90);
|
||||
rtData.setHr(145);
|
||||
}
|
||||
|
||||
void NullController::pushRealtimeData(RealtimeData &) {
|
||||
|
||||
@@ -81,56 +81,56 @@ void RealtimeData::setXPower(long x)
|
||||
this->xPower = x;
|
||||
}
|
||||
|
||||
char *
|
||||
RealtimeData::getName()
|
||||
const char *
|
||||
RealtimeData::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
double RealtimeData::getWatts()
|
||||
double RealtimeData::getWatts() const
|
||||
{
|
||||
return watts;
|
||||
}
|
||||
double RealtimeData::getHr()
|
||||
double RealtimeData::getHr() const
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
double RealtimeData::getSpeed()
|
||||
double RealtimeData::getSpeed() const
|
||||
{
|
||||
return speed;
|
||||
}
|
||||
double RealtimeData::getWheelRpm()
|
||||
double RealtimeData::getWheelRpm() const
|
||||
{
|
||||
return wheelRpm;
|
||||
}
|
||||
double RealtimeData::getCadence()
|
||||
double RealtimeData::getCadence() const
|
||||
{
|
||||
return cadence;
|
||||
}
|
||||
double RealtimeData::getLoad()
|
||||
double RealtimeData::getLoad() const
|
||||
{
|
||||
return load;
|
||||
}
|
||||
long RealtimeData::getMsecs()
|
||||
long RealtimeData::getMsecs() const
|
||||
{
|
||||
return msecs;
|
||||
}
|
||||
long RealtimeData::getLapMsecs()
|
||||
long RealtimeData::getLapMsecs() const
|
||||
{
|
||||
return lapMsecs;
|
||||
}
|
||||
double RealtimeData::getDistance()
|
||||
double RealtimeData::getDistance() const
|
||||
{
|
||||
return distance;
|
||||
}
|
||||
long RealtimeData::getJoules()
|
||||
long RealtimeData::getJoules() const
|
||||
{
|
||||
return joules;
|
||||
}
|
||||
long RealtimeData::getBikeScore()
|
||||
long RealtimeData::getBikeScore() const
|
||||
{
|
||||
return bikeScore;
|
||||
}
|
||||
long RealtimeData::getXPower()
|
||||
long RealtimeData::getXPower() const
|
||||
{
|
||||
return xPower;
|
||||
}
|
||||
|
||||
@@ -57,20 +57,20 @@ public:
|
||||
void setJoules(long);
|
||||
void setXPower(long);
|
||||
|
||||
char *getName();
|
||||
double getWatts();
|
||||
double getHr();
|
||||
long getTime();
|
||||
double getSpeed();
|
||||
double getWheelRpm();
|
||||
double getCadence();
|
||||
double getLoad();
|
||||
long getMsecs();
|
||||
long getLapMsecs();
|
||||
double getDistance();
|
||||
long getBikeScore();
|
||||
long getJoules();
|
||||
long getXPower();
|
||||
const char *getName() const;
|
||||
double getWatts() const;
|
||||
double getHr() const;
|
||||
long getTime() const;
|
||||
double getSpeed() const;
|
||||
double getWheelRpm() const;
|
||||
double getCadence() const;
|
||||
double getLoad() const;
|
||||
long getMsecs() const;
|
||||
long getLapMsecs() const;
|
||||
double getDistance() const;
|
||||
long getBikeScore() const;
|
||||
long getJoules() const;
|
||||
long getXPower() const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
73
src/RideWindow.cpp
Normal file
73
src/RideWindow.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Greg Lonnon (greg.lonnon@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "RideWindow.h"
|
||||
#include "RealtimeData.h"
|
||||
#include "JsonRideFile.h"
|
||||
|
||||
// this is called on every page load in the web browser
|
||||
void RideWindow::addJSObjects()
|
||||
{
|
||||
view->page()->mainFrame()->addToJavaScriptWindowObject("GCRider",rider);
|
||||
}
|
||||
|
||||
void RideWindow::rideSelected()
|
||||
{
|
||||
// skip display if data drawn or invalid
|
||||
if (myRideItem == NULL || !amVisible()) return;
|
||||
RideItem * r = myRideItem;
|
||||
if (ride == r || !r || !r->ride()) return;
|
||||
else ride = r;
|
||||
|
||||
loadRide();
|
||||
}
|
||||
|
||||
void RideWindow::loadRide()
|
||||
{
|
||||
QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled, true);
|
||||
// uncommit these two lines to get the QWebInspector working.
|
||||
// QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true);
|
||||
// QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
|
||||
|
||||
QWebPage *page = view->page();
|
||||
QWebFrame *frame = page->mainFrame();
|
||||
|
||||
// Signal is emitted before frame loads any web content:
|
||||
QObject::connect(frame, SIGNAL(javaScriptWindowObjectCleared()),
|
||||
this, SLOT(addJSObjects()));
|
||||
view->setPage(page);
|
||||
// used for testing...
|
||||
RiderBridge* tr = new RealtimeRider(main);
|
||||
tr->setRide(ride);
|
||||
rider = tr;
|
||||
addJSObjects();
|
||||
}
|
||||
|
||||
RideWindow::RideWindow(MainWindow * _main) :
|
||||
GcWindow(_main),
|
||||
rideLoaded(false)
|
||||
{
|
||||
main = _main;
|
||||
setInstanceName("Ride Window");
|
||||
view = new QWebView();
|
||||
QVBoxLayout *layout = new QVBoxLayout();
|
||||
layout->addWidget(view);
|
||||
setLayout(layout);
|
||||
|
||||
connect(this, SIGNAL(rideItemChanged(RideItem*)), this, SLOT(rideSelected()));
|
||||
}
|
||||
390
src/RideWindow.h
Normal file
390
src/RideWindow.h
Normal file
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Greg Lonnon (greg.lonnon@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef RIDEWINDOW_H
|
||||
#define RIDEWINDOW_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QWebView>
|
||||
#include <QWebPage>
|
||||
#include <QWebFrame>
|
||||
#include <QWebInspector>
|
||||
#include <QDebug>
|
||||
#include <limits>
|
||||
#include "TrainTool.h"
|
||||
#include "RealtimeController.h"
|
||||
#include "RideFile.h"
|
||||
|
||||
class Route
|
||||
{
|
||||
QVector<RideFilePoint> route;
|
||||
public:
|
||||
Route(const QVector<RideFilePoint*> &r)
|
||||
{
|
||||
foreach(RideFilePoint *rfp, r)
|
||||
{
|
||||
route.push_back(*rfp);
|
||||
}
|
||||
}
|
||||
// look 50 meters down and find the local max
|
||||
double calcGrade(int position)
|
||||
{
|
||||
int i = position;
|
||||
double distance = 0.05; // 50 meters
|
||||
double endDistance = route[position].km + distance;
|
||||
while(route[i].km < endDistance)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
double grade = (route[i].alt - route[position].alt) / (route[i].km - route[position].km) * 100;
|
||||
return grade;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Bike
|
||||
{
|
||||
double ccr; // road resistance
|
||||
double speed; // speed
|
||||
public:
|
||||
double getCcr() { return ccr;}
|
||||
void setCcr(double c) { ccr = c; }
|
||||
double getSpeed() { return speed; }
|
||||
void setSpeed(double s) { speed = s; }
|
||||
};
|
||||
|
||||
class Rider
|
||||
{
|
||||
private:
|
||||
Bike bike;
|
||||
Route route;
|
||||
|
||||
};
|
||||
|
||||
class BikePhysicsEngine
|
||||
{
|
||||
// check out http://www.flacyclist.com/content/perf/science.html for the
|
||||
// math behind this...
|
||||
|
||||
double ccr; // roll resistance 0.001 track, 0.002 concrete, 0.004 asphalt, 0.008 rough road
|
||||
double weight; // kg rider + bike
|
||||
double wind; // head wind only
|
||||
double cda; // areo
|
||||
double alt;
|
||||
double temp; // C
|
||||
double air; // air pressure
|
||||
double speed;
|
||||
double grade;
|
||||
|
||||
// calcuated values
|
||||
double f_air;
|
||||
double f_roll;
|
||||
protected:
|
||||
|
||||
double calcFAir(double speed)
|
||||
{
|
||||
return 0.5 * cda * (air/((temp + 273.15) * 287.058) * pow((speed + wind), 2));
|
||||
}
|
||||
|
||||
double calcFGrade()
|
||||
{
|
||||
return 9.8 * weight * grade;
|
||||
}
|
||||
|
||||
double calcFRoll()
|
||||
{
|
||||
return 9.8 * weight * ccr;
|
||||
}
|
||||
|
||||
public:
|
||||
void setCcr(double c) { ccr = c; }
|
||||
void setWeight(double w) { weight = w; }
|
||||
void setWind(double w) { wind = w; }
|
||||
void setGrade(double g) { grade = g; }
|
||||
void setSpeed(double s) { speed = s; }
|
||||
|
||||
double SpeedGivenPower(double watts)
|
||||
{
|
||||
return watts/20;
|
||||
}
|
||||
double PowerGivenSpeed(double speed)
|
||||
{
|
||||
return calcFAir(speed) + calcFGrade() + calcFRoll();
|
||||
}
|
||||
};
|
||||
|
||||
/// The rider class holds all the information needed to display the rider
|
||||
/// on the web page
|
||||
class RiderBridge : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
protected:
|
||||
QString name;
|
||||
|
||||
QString markerColor;
|
||||
|
||||
// current ride item
|
||||
RideItem *ride;
|
||||
// current data
|
||||
RideFilePoint rfp;
|
||||
|
||||
// currnet position in the ride
|
||||
int curPosition;
|
||||
double curTime; // in seconds
|
||||
|
||||
int load; // load generator (computrainer only)
|
||||
|
||||
public:
|
||||
RiderBridge() {}
|
||||
void setRide(RideItem *ri) { ride = ri; }
|
||||
|
||||
// list of all properties that are visible
|
||||
// in js
|
||||
|
||||
Q_PROPERTY(QString name READ getName WRITE setName);
|
||||
QString getName() { return name; }
|
||||
void setName(QString s) { name = s; }
|
||||
|
||||
Q_PROPERTY(int time READ getSecs WRITE setSecs);
|
||||
double getSecs() { return rfp.secs; }
|
||||
void setSecs(double s) { rfp.secs = s; }
|
||||
|
||||
Q_PROPERTY(double hr READ getHr WRITE setHr);
|
||||
double getHr() { return rfp.hr; }
|
||||
void setHr(double h) { rfp.hr= h; }
|
||||
|
||||
Q_PROPERTY(double Watts READ getWatts WRITE setWatts);
|
||||
double getWatts() { return rfp.watts; }
|
||||
void setWatts(double w) { rfp.watts = w; }
|
||||
|
||||
Q_PROPERTY(double speed READ getSpeed WRITE setSpeed);
|
||||
double getSpeed() { return rfp.kph; }
|
||||
void setSpeed(double s) { rfp.kph = s; }
|
||||
|
||||
// Q_PROPERTY(double wheelRpm READ getWheelRpm WRITE setWheelRpm);
|
||||
// double getWheelRpm() { return rfp.cad; }
|
||||
// void setWheelRpm(double w) { rfp.cad = w; }
|
||||
|
||||
Q_PROPERTY(double load READ getLoad WRITE setLoad);
|
||||
double getLoad() { return load; }
|
||||
void setLoad(double l) { load = l; }
|
||||
|
||||
Q_PROPERTY(double cadence READ getCadence WRITE setCadence);
|
||||
double getCadence() { return rfp.cad; }
|
||||
void setCadence(double c) { rfp.cad = c; }
|
||||
|
||||
Q_PROPERTY(double distance READ getDistance WRITE setDistance);
|
||||
double getDistance() { return rfp.km; }
|
||||
void setDistance(double d) { rfp.km = d;}
|
||||
|
||||
Q_PROPERTY(double distance READ getDistance WRITE setDistance);
|
||||
double getLon() { return rfp.lon; }
|
||||
void setLon(double l) { rfp.lon = l;}
|
||||
|
||||
Q_PROPERTY(double lat READ getLat WRITE setLat);
|
||||
double getLat() { return rfp.lat; }
|
||||
void setLat(double l) { rfp.lat = l;}
|
||||
|
||||
Q_PROPERTY(QVariantList routeLon READ getRouteLon);
|
||||
QVariantList getRouteLon() {
|
||||
QVariantList route;
|
||||
foreach(RideFilePoint *rfp, ride->ride()->dataPoints())
|
||||
{
|
||||
route.push_back(QVariant(rfp->lon));
|
||||
}
|
||||
return route;
|
||||
}
|
||||
Q_PROPERTY(QVariantList routeLat READ getRouteLat);
|
||||
QVariantList getRouteLat() {
|
||||
QVariantList route;
|
||||
foreach(RideFilePoint *rfp, ride->ride()->dataPoints())
|
||||
{
|
||||
route.push_back(QVariant(rfp->lat));
|
||||
}
|
||||
return route;
|
||||
}
|
||||
|
||||
Q_PROPERTY(QVariantList profile READ getProfile);
|
||||
QVariantList getProfile() {
|
||||
QVariantList route;
|
||||
foreach(RideFilePoint *rfp, ride->ride()->dataPoints())
|
||||
{
|
||||
route.push_back(QVariant(rfp->alt));
|
||||
}
|
||||
return route;
|
||||
}
|
||||
|
||||
Q_PROPERTY(int position READ getPosition);
|
||||
int getPosition() {
|
||||
return curPosition;
|
||||
}
|
||||
|
||||
|
||||
public slots:
|
||||
// set the curTime and find the position in the array closest to the time
|
||||
Q_INVOKABLE void SetTime(double secs)
|
||||
{
|
||||
// find the curPosition
|
||||
QVector<RideFilePoint*> dataPoints = ride->ride()->dataPoints();
|
||||
curTime = secs;
|
||||
|
||||
if(dataPoints.count() < curPosition)
|
||||
{
|
||||
curPosition = 0;
|
||||
return;
|
||||
}
|
||||
// make sure the current position is less than the new time
|
||||
if (dataPoints[curPosition]->secs < secs)
|
||||
{
|
||||
for( ; curPosition < dataPoints.count(); curPosition++)
|
||||
{
|
||||
if(dataPoints[curPosition]->secs < secs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( ; curPosition > 0; curPosition--)
|
||||
{
|
||||
if(dataPoints[curPosition]->secs > secs)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// update the rfp
|
||||
rfp = *dataPoints[curPosition];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class RealtimeRider: public RiderBridge
|
||||
{
|
||||
Q_OBJECT;
|
||||
//Route route;
|
||||
BikePhysicsEngine engine;
|
||||
double prevMSecs;
|
||||
|
||||
protected:
|
||||
int findCurrentPosition()
|
||||
{
|
||||
QVector<RideFilePoint*> route = ride->ride()->dataPoints();
|
||||
// this is by distance
|
||||
for(int i = 0; i < route.count(); i++)
|
||||
{
|
||||
if(rfp.km < route[i]->km)
|
||||
return i;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
int findCurrentPositionByPower()
|
||||
{
|
||||
double speed = engine.SpeedGivenPower(rfp.watts);
|
||||
return (int) speed;
|
||||
|
||||
}
|
||||
int findCurrentPositionByTime()
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public slots:
|
||||
virtual void telemetryUpdate(const RealtimeData &data)
|
||||
{
|
||||
rfp.watts = data.getWatts();
|
||||
rfp.kph = data.getSpeed();
|
||||
rfp.cad = data.getCadence();
|
||||
rfp.km = data.getDistance();
|
||||
rfp.secs = data.getMsecs() / 1000;
|
||||
load = data.getLoad();
|
||||
curPosition = findCurrentPosition();
|
||||
}
|
||||
public:
|
||||
RealtimeRider(MainWindow *main)
|
||||
{
|
||||
curPosition = 1;
|
||||
connect(main,SIGNAL(telemetryUpdate(const RealtimeData &)), this,SLOT(telemetryUpdate(const RealtimeData &)));
|
||||
}
|
||||
};
|
||||
|
||||
class RideWindow : public GcWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
protected:
|
||||
RideItem *ride;
|
||||
QWebView *view;
|
||||
bool rideLoaded;
|
||||
MainWindow *main;
|
||||
|
||||
virtual void loadRide();
|
||||
RiderBridge *rider;
|
||||
|
||||
void EnableWebInspector(QWebPage *page)
|
||||
{
|
||||
// put the QWebInspector on the page...
|
||||
QWebInspector * qwi = new QWebInspector();
|
||||
qwi->setPage(page);
|
||||
qwi->setVisible(true);
|
||||
}
|
||||
public:
|
||||
explicit RideWindow(MainWindow *);
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
void addJSObjects();
|
||||
void rideSelected();
|
||||
};
|
||||
|
||||
|
||||
class MapWindow : public RideWindow
|
||||
{
|
||||
|
||||
protected:
|
||||
virtual void loadRide()
|
||||
{
|
||||
RideWindow::loadRide();
|
||||
view->page()->mainFrame()->load(QUrl("qrc:/ride/web/MapWindow.html"));
|
||||
//EnableWebInspector(view->page()); // turns on the javascript debugger
|
||||
}
|
||||
public:
|
||||
explicit MapWindow(MainWindow *main) : RideWindow(main) {}
|
||||
};
|
||||
|
||||
|
||||
class StreetViewWindow : public RideWindow
|
||||
{
|
||||
protected:
|
||||
virtual void loadRide()
|
||||
{
|
||||
RideWindow::loadRide();
|
||||
view->page()->mainFrame()->load(QUrl("qrc:/ride/web/StreetViewWindow.html"));
|
||||
// EnableWebInspector(view->page()); // turns on the javascript debugger
|
||||
}
|
||||
public:
|
||||
explicit StreetViewWindow(MainWindow *main) : RideWindow(main) {}
|
||||
|
||||
};
|
||||
|
||||
#endif // RIDEWINDOW_H
|
||||
10
src/RideWindow.qrc
Normal file
10
src/RideWindow.qrc
Normal file
@@ -0,0 +1,10 @@
|
||||
<RCC>
|
||||
<qresource prefix="/ride">
|
||||
<file>web/Rider.js</file>
|
||||
<file>web/ride.js</file>
|
||||
<file>web/jquery-1.6.4.min.js</file>
|
||||
<file>web/StreetViewWindow.html</file>
|
||||
<file>web/MapWindow.html</file>
|
||||
<file>web/Window.css</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -19,6 +19,7 @@
|
||||
#ifndef _GC_WorkoutPlotWindow_h
|
||||
#define _GC_WorkoutPlotWindow_h 1
|
||||
#include "GoldenCheetah.h"
|
||||
#include "RideWindow.h"
|
||||
|
||||
#include <QtGui>
|
||||
#include <QObject> // for Q_PROPERTY
|
||||
|
||||
14
src/src.pro
14
src/src.pro
@@ -263,6 +263,7 @@ HEADERS += \
|
||||
RideMetric.h \
|
||||
RideNavigator.h \
|
||||
RideNavigatorProxy.h \
|
||||
RideWindow.h \
|
||||
SaveDialogs.h \
|
||||
SmallPlot.h \
|
||||
RideSummaryWindow.h \
|
||||
@@ -429,6 +430,7 @@ SOURCES += \
|
||||
RideMetric.cpp \
|
||||
RideNavigator.cpp \
|
||||
RideSummaryWindow.cpp \
|
||||
RideWindow.cpp \
|
||||
SaveDialogs.cpp \
|
||||
ScatterPlot.cpp \
|
||||
ScatterWindow.cpp \
|
||||
@@ -471,7 +473,8 @@ SOURCES += \
|
||||
Zones.cpp \
|
||||
main.cpp \
|
||||
|
||||
RESOURCES = application.qrc
|
||||
RESOURCES = application.qrc \
|
||||
RideWindow.qrc
|
||||
|
||||
TRANSLATIONS = translations/gc_fr.ts \
|
||||
translations/gc_ja.ts \
|
||||
@@ -480,3 +483,12 @@ TRANSLATIONS = translations/gc_fr.ts \
|
||||
translations/gc_de.ts \
|
||||
translations/gc_cs.ts \
|
||||
translations/gc_ru.ts
|
||||
|
||||
OTHER_FILES += \
|
||||
web/Rider.js \
|
||||
web/ride.js \
|
||||
web/jquery-1.6.4.min.js \
|
||||
web/MapWindow.html \
|
||||
web/StreetViewWindow.html \
|
||||
web/Window.css
|
||||
|
||||
|
||||
46
src/web/MapWindow.html
Normal file
46
src/web/MapWindow.html
Normal file
@@ -0,0 +1,46 @@
|
||||
<html>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (c) 2011 Greg Lonnon (greg.lonnon@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
-->
|
||||
<head>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1'>
|
||||
<title>Map View</title>
|
||||
<link rel="stylesheet" type="text/css" href="qrc:///ride/web/Window.css"/>
|
||||
<script type="text/javascript" src="qrc:///ride/web/jquery-1.6.4.min.js"></script>
|
||||
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&libraries=geometry"></script>
|
||||
<script type="text/javascript" src="qrc:///ride/web/Rider.js"></script>
|
||||
<script type="text/javascript" src="qrc:///ride/web/ride.js"></script>
|
||||
<script type="text/javascript">
|
||||
var myArray = new Array();
|
||||
$(document).ready(function()
|
||||
{
|
||||
MapFactory("view");
|
||||
for(var i = 0; i < myArray.length; i++) {
|
||||
myArray[i].init();
|
||||
}
|
||||
animateLoop(0);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="view"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
105
src/web/Rider.js
Normal file
105
src/web/Rider.js
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Greg Lonnon (greg.lonnon@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
// This the rider class...
|
||||
// It can take a JSON file and turn it into a rider.
|
||||
// or (in the future...) take live input from the RealtimeWindow
|
||||
|
||||
|
||||
function Rider_createRoute()
|
||||
{
|
||||
var path = new Array();
|
||||
var bounds = new google.maps.LatLngBounds();
|
||||
var routeLon = this.riderBridge.routeLon;
|
||||
var routeLat = this.riderBridge.routeLat;
|
||||
var length = routeLon.length;
|
||||
|
||||
for(var i = 0; i < length ; i++)
|
||||
{
|
||||
var lon = routeLon[i];
|
||||
var lat = routeLat[i];
|
||||
if(lon == 0) continue;
|
||||
if(lat == 0) continue;
|
||||
var coord = new google.maps.LatLng(lat,lon);
|
||||
path.push(coord);
|
||||
bounds.extend(coord);
|
||||
}
|
||||
var polyline = new google.maps.Polyline();
|
||||
polyline.setPath(path);
|
||||
return [polyline,bounds,path];
|
||||
}
|
||||
|
||||
function Rider_validTime(time)
|
||||
{
|
||||
if((time > 0) && (time <= this.routeLength))
|
||||
{
|
||||
return time;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function Rider_setTime(time)
|
||||
{
|
||||
this.time = this.validTime(time);
|
||||
}
|
||||
|
||||
function Rider_isDone(time)
|
||||
{
|
||||
if(this.routeLength < time)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function Rider_computeHeading()
|
||||
{
|
||||
var pos1 = this.position();
|
||||
var pos0 = pos1 -1;
|
||||
var coord1 = this.route[2][pos1];
|
||||
var coord0 = this.route[2][pos0];
|
||||
return google.maps.geometry.spherical.computeHeading(coord0,coord1);
|
||||
}
|
||||
|
||||
function Rider_coord()
|
||||
{
|
||||
return this.route[2][this.position()];
|
||||
}
|
||||
|
||||
function Rider_position()
|
||||
{
|
||||
return this.riderBridge.position;
|
||||
}
|
||||
|
||||
function Rider(riderBridge)
|
||||
{
|
||||
this.riderBridge = riderBridge;
|
||||
this.setTime = Rider_setTime;
|
||||
this.createRoute = Rider_createRoute;
|
||||
this.route = this.createRoute();
|
||||
this.routeLength = this.route[2].length;
|
||||
this.isDone = Rider_isDone;
|
||||
this.computeHeading = Rider_computeHeading;
|
||||
this.validTime = Rider_validTime;
|
||||
this.coord = Rider_coord;
|
||||
this.position = Rider_position;
|
||||
}
|
||||
46
src/web/StreetViewWindow.html
Normal file
46
src/web/StreetViewWindow.html
Normal file
@@ -0,0 +1,46 @@
|
||||
<html>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (c) 2011 Greg Lonnon (greg.lonnon@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
-->
|
||||
<head>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1'>
|
||||
<title>StreetView View</title>
|
||||
<link rel="stylesheet" type="text/css" href="qrc:///ride/web/Window.css"/>
|
||||
<script type="text/javascript" src="qrc:///ride/web/jquery-1.6.4.min.js"></script>
|
||||
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&libraries=geometry"></script>
|
||||
<script type="text/javascript" src="qrc:///ride/web/Rider.js"></script>
|
||||
<script type="text/javascript" src="qrc:///ride/web/ride.js"></script>
|
||||
<script type="text/javascript">
|
||||
var myArray = new Array();
|
||||
$(document).ready(function()
|
||||
{
|
||||
StreetViewFactory("view");
|
||||
for(var i = 0; i < myArray.length; i++) {
|
||||
myArray[i].init();
|
||||
}
|
||||
animateLoop(0);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="view"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
31
src/web/Window.css
Normal file
31
src/web/Window.css
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Greg Lonnon (greg.lonnon@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#view {
|
||||
margin-top:0%;
|
||||
margin-bottom: 0%;
|
||||
margin-right: 0%;
|
||||
margin-left: 0%;
|
||||
padding: 0%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #9cf;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
4
src/web/jquery-1.6.4.min.js
vendored
Normal file
4
src/web/jquery-1.6.4.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
148
src/web/ride.js
Normal file
148
src/web/ride.js
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Greg Lonnon (greg.lonnon@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
// MAP
|
||||
|
||||
function Map_init()
|
||||
{
|
||||
var mapOptions = {
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP
|
||||
};
|
||||
this.map = new google.maps.Map(document.getElementById(this.id),mapOptions);
|
||||
var retArray = this.rider.route;
|
||||
var routePolyline = retArray[0];
|
||||
var mapBounds = retArray[1];
|
||||
routePolyline.setMap(this.map);
|
||||
this.map.fitBounds(mapBounds);
|
||||
this.marker = new google.maps.Marker();
|
||||
this.marker.setMap(this.map);
|
||||
}
|
||||
|
||||
function Map_update()
|
||||
{
|
||||
var curPosition = this.rider.position();
|
||||
if(curPosition == this.position){
|
||||
return;
|
||||
}
|
||||
var coord = this.rider.coord();
|
||||
if(coord.lat() == 0) return;
|
||||
if(coord.lng() == 0) return;
|
||||
this.map.panTo(coord);
|
||||
this.marker.setPosition(coord);
|
||||
}
|
||||
|
||||
function Map(rider)
|
||||
{
|
||||
this.rider = rider;
|
||||
this.map = null;
|
||||
this.marker = null;
|
||||
this.update = Map_update;
|
||||
this.init = Map_init;
|
||||
this.position = 0;
|
||||
}
|
||||
|
||||
function MapFactory(id)
|
||||
{
|
||||
if(typeof(GCRider) != "undefined")
|
||||
{
|
||||
// we are running inside GC
|
||||
GCRider.time = 1;
|
||||
var map = new Map(new Rider(GCRider));
|
||||
map.id = id;
|
||||
myArray.push(map);
|
||||
}
|
||||
}
|
||||
|
||||
// STREET VIEW
|
||||
function StreetView_init()
|
||||
{
|
||||
var streetOptions = {
|
||||
addressControl : false,
|
||||
panControl : false,
|
||||
linksControl : false,
|
||||
scrollwheel : false,
|
||||
zoomControl : false
|
||||
};
|
||||
this.street = new google.maps.StreetViewPanorama(document.getElementById(this.id),streetOptions);
|
||||
}
|
||||
|
||||
function StreetView_update()
|
||||
{
|
||||
var curPosition = this.rider.position();
|
||||
if(curPosition == this.position || curPosition == 0) {
|
||||
return;
|
||||
}
|
||||
this.position = curPosition;
|
||||
var h = this.rider.computeHeading();
|
||||
this.street.setPov({ heading: h, pitch: 10, zoom: 1 });
|
||||
this.street.setPosition(this.rider.coord());
|
||||
this.street.setVisible(true);
|
||||
}
|
||||
|
||||
function StreetView(rider)
|
||||
{
|
||||
this.rider = rider;
|
||||
this.update = StreetView_update;
|
||||
this.init = StreetView_init;
|
||||
this.position = 0;
|
||||
}
|
||||
|
||||
function StreetViewFactory(id)
|
||||
{
|
||||
if(typeof(GCRider) != "undefined")
|
||||
{
|
||||
// we are running inside GC
|
||||
GCRider.time = 1;
|
||||
var street = new StreetView(new Rider(GCRider));
|
||||
street.id = id;
|
||||
myArray.push(street);
|
||||
}
|
||||
}
|
||||
|
||||
function animateLoop(eventCount)
|
||||
{
|
||||
try
|
||||
{
|
||||
var done;
|
||||
for(var i = 0; i < myArray.length; i++) {
|
||||
myArray[i].update();
|
||||
if(done == false)
|
||||
{
|
||||
done = myArray[i].rider.isDone;
|
||||
}
|
||||
}
|
||||
eventCount = eventCount + 1;
|
||||
if(done != true)
|
||||
{
|
||||
setTimeout("animateLoop(" + eventCount+ ")",1000);
|
||||
}
|
||||
}
|
||||
catch(err) {
|
||||
// dump everything into a string
|
||||
var debugStr;
|
||||
for(var p in err) {
|
||||
debugStr += "property: " + p + " value: [" + err[p] + "]\n";
|
||||
}
|
||||
debugDebug += "toString(): " + " value: [" + err.toString() + "]";
|
||||
alert(debugStr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user