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:
Greg Lonnon
2011-09-20 20:29:31 -06:00
parent b7fdac990b
commit d5769b480d
19 changed files with 911 additions and 38 deletions

View File

@@ -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>

View File

@@ -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();

View File

@@ -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));

View File

@@ -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;

View File

@@ -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); }

View File

@@ -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 &) {

View File

@@ -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;
}

View File

@@ -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
View 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
View 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
View 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>

View File

@@ -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

View File

@@ -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
View 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
View 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;
}

View 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
View 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

File diff suppressed because one or more lines are too long

148
src/web/ride.js Normal file
View 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);
}
}