1 /****************************************************************************
3 ** Copyright (C) 2011 Tito Eritja Real <jtitoo@gmail.com>
5 ** This program is free software: you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation, either version 3 of the License, or
8 ** (at your option) any later version.
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program. If not, see <http://www.gnu.org/licenses/>.
18 ****************************************************************************/
22 #include <QXmlStreamWriter>
25 #include <QtCore/qmath.h>
29 Summarized::Summarized(){
31 startTime=QDateTime::currentDateTime();
47 QString Summarized::toSumString(){
48 return QString("Summarized={numPoints: %1, startTime: %2, duration: %3, distance: %4, avgSpeed: %5, maxSpeed: %6, elevationGain: %7, elevationLoss: %8, minElevation: %9, maxElevation: %10, avgPace: %11, minPace: %12}")
49 .arg(numPoints).arg(startTime.toString(CLEAN_DATE_FORMAT)).arg(duration).arg(distance)
50 .arg(avgSpeed).arg(maxSpeed).arg(elevationGain).arg(elevationLoss).arg(minElevation).arg(maxElevation).arg(avgPace).arg(bestPace);
52 void Summarized::addSummary(Summarized summary){
54 duration+=summary.getDuration();
55 distance=distance+summary.getDistance();
56 // avgSpeed of summary is not Avg, is speed of last point!
57 if(summary.getAvgPace()!=-1)
58 avgSpeed=((avgSpeed*numPoints)+summary.getAvgSpeed())/(numPoints+1);
60 elevationGain+=summary.getElevationGain();
61 elevationLoss+=summary.getElevationLoss();
63 if(minElevation!=0 && summary.minElevation!=0){
64 minElevation=min(minElevation,summary.minElevation);
65 }else if(minElevation==0 && summary.minElevation!=0){
66 minElevation=summary.minElevation;
69 maxElevation=max(maxElevation,summary.maxElevation);
70 maxSpeed=max(maxSpeed,summary.maxSpeed);
72 if(bestPace!=0 && summary.avgPace!=0){
73 bestPace=min(bestPace,summary.avgPace);
74 }else if(bestPace==0 && summary.avgPace!=0){
75 bestPace=summary.avgPace;
78 avgPace=(1000*duration)/(60*distance);
82 Summarized& Summarized::account(GpsPoint point){
84 // this just is usefull for accounting the diference
85 // between two points. The summary MUST be new!!!
86 // data in here is not secure and not controlled.
89 startTime=point.getTime();
90 endTime=point.getTime();
91 maxSpeed=point.getSpeed();
92 avgSpeed=point.getSpeed();
93 minElevation=point.getElevation();
94 maxElevation=point.getElevation();
99 Summarized& Summarized::account(GpsPoint first, GpsPoint last){
101 // this just is usefull for accounting the diference
102 // between two points. The summary MUST be new!!!
103 // data in here is not secure and not controlled.
106 distance=first.distance(last);
107 duration=first.getTime().secsTo(last.getTime());
108 startTime=first.getTime();
109 endTime=last.getTime();
110 double lastEle=last.getElevation();
111 double firstEle=first.getElevation();
112 if(lastEle>=firstEle)
113 elevationGain=lastEle-firstEle;
115 elevationLoss=firstEle-lastEle;
117 maxSpeed=max(first.getSpeed(),last.getSpeed());
118 // keep speed of last point, will be usefull
120 avgSpeed=last.getSpeed();
121 minElevation=min(first.getElevation(),last.getElevation());
122 maxElevation=max(first.getElevation(),last.getElevation());
123 avgPace=(1000*duration)/(60*distance);
129 GpsPoint::GpsPoint(double latitude, double longitude, int elevation)
131 longitude(longitude),
132 elevation(elevation),speed(0),direction(0),magneticVariation(0),horizontalAccuracy(0),verticalAccuracy(0){
135 GpsPoint::GpsPoint(double latitude, double longitude, int elevation,QDateTime time,
136 qreal speed, qreal direction, qreal magneticVariation, qreal horizontalAccuracy, qreal verticalAccuracy)
137 :latitude(latitude),longitude(longitude),elevation(elevation),time(time),
138 speed(speed), direction(direction), magneticVariation(magneticVariation),
139 horizontalAccuracy(horizontalAccuracy),verticalAccuracy(verticalAccuracy){
143 GpsPoint::GpsPoint(double latitude, double longitude, int elevation,QDateTime time,
144 qreal speed, qreal direction, qreal magneticVariation, qreal horizontalAccuracy, qreal verticalAccuracy,
145 qreal distancePrev, QTime timeToPrev)
146 :latitude(latitude),longitude(longitude),elevation(elevation),time(time),
147 speed(speed), direction(direction), magneticVariation(magneticVariation),
148 horizontalAccuracy(horizontalAccuracy),verticalAccuracy(verticalAccuracy),distancePrev(distancePrev), timeToPrev(timeToPrev){
152 QString GpsPoint::toString(){
153 QString point = QString("GpsPoint{latitude: %1, longitude: %2, elevation: %3, time: %4, speed: %5, direction: %6, magneticVariation: %7, horizontalAccuracy: %8, verticalAccuracy: %9:, distancePrev: %10}")
154 .arg(latitude).arg(longitude).arg(elevation).arg(time.toString("dd-MM-yyyy hh:mm:ss")).arg(speed).arg(direction).arg(magneticVariation)
155 .arg(horizontalAccuracy).arg(verticalAccuracy).arg(QString::number(distancePrev,'f',10));
159 GpsPoint& GpsPoint::operator= (const GpsPoint &p){
163 longitude=p.longitude;
164 elevation=p.elevation;
166 direction=p.direction;
167 magneticVariation=p.magneticVariation;
169 distancePrev=p.distancePrev;
170 timeToPrev=p.timeToPrev;
171 horizontalAccuracy=p.horizontalAccuracy;
172 verticalAccuracy=p.verticalAccuracy;
179 double GpsPoint::distance(GpsPoint p){
181 double latitude1 = toRad(latitude);
182 double longitude1 = toRad(longitude);
184 double latitude2 = toRad(p.latitude);
185 double longitude2 = toRad(p.longitude);
187 double temp = sin(latitude1)*sin(latitude2)+cos(latitude1)*cos(latitude2)*cos(longitude2-longitude1);
189 double dist= acos(temp)*EARTH_RADIUS*1000;
190 //qDebug() << "distance between points: " << QString::number(dist,'f',10);
194 int operator== (const GpsPoint& a, const GpsPoint& b)
196 if (a.latitude==b.latitude&&a.longitude==b.longitude&&a.elevation==b.elevation&&a.speed==b.speed
197 &&a.direction==b.direction &&a.magneticVariation==b.magneticVariation&&a.time==b.time
198 &&a.horizontalAccuracy==b.horizontalAccuracy&&a.verticalAccuracy==b.verticalAccuracy
199 &&a.distancePrev==b.distancePrev&&a.timeToPrev==b.timeToPrev)
205 int operator!= (const GpsPoint& a, const GpsPoint& b)
207 if (a.latitude!=b.latitude||a.longitude!=b.longitude||a.elevation!=b.elevation||a.speed!=b.speed
208 ||a.direction!=b.direction || a.magneticVariation!=b.magneticVariation||a.time!=b.time
209 ||a.horizontalAccuracy!=b.horizontalAccuracy||a.verticalAccuracy!=b.verticalAccuracy
210 ||a.distancePrev!=b.distancePrev||a.timeToPrev!=b.timeToPrev)
225 for (int i = 0; i < points.size(); ++i) {
231 Summarized* Lap::addPoint(GpsPoint *point){
232 //qDebug() <<"--- Lap::addPoint ---";
233 Summarized *summary = new Summarized();
235 GpsPoint* last = points.last();
236 point->setDistancePrev(point->distance(*last));
237 //qDebug() << "DistancePrev:" << QString::number(point->getDistancePrev(),'f',10);
238 summary->account(*last,*point);
240 //qDebug() << "First lap point!";
241 summary->account(*point);
243 addSummary(*summary);
244 //qDebug() << "Track summary:" << toSumString();
246 points.append(point);
250 QString Lap::toString(){
251 QString lap = QString("Lap={number:").append(QString::number(number)).append(", numPoints:").append(QString::number(numPoints));
253 QListIterator<GpsPoint*> i(points);
254 while (i.hasNext()) {
255 GpsPoint* p = i.next();
256 lap.append(QString(", %1").arg(p->toString()));
258 lap.append(QString("}"));
262 Activity::Activity(QString sport)
264 id=QDateTime::currentDateTime();
269 Activity::~Activity(){
270 for (int i = 0; i < laps.size(); ++i) {
275 QString Activity::toString(){
276 QString activity = QString("Activity={sport:%1, id:%2, numLaps:%3").arg(sport).arg(id.toString(CLEAN_DATE_FORMAT)).arg(numLaps);
278 QListIterator<Lap*> i(laps);
281 activity.append(QString(", %1").arg(l->toString()));
283 activity.append(QString("}"));
287 void Activity::addLap(){
289 Lap* newLap = new Lap(numLaps);
293 Summarized* Activity::addPoint(GpsPoint* point){
295 //qDebug() <<"--- Activity::addPoint ---";
296 Lap* lastLap = laps.last();
297 Summarized* summary = lastLap->addPoint(point);
298 addSummary(*summary);
299 //qDebug() << "Track summary:" << toSumString();
306 Track::Track(QString file,QString nameTrack)
307 :fileName(file),name(nameTrack){
309 addActivity(nameTrack);
312 Track::Track(QString fname)
313 :fileName(fname),name(fname){
319 :fileName("noname"),name("noname"){
326 for (int i = 0; i < activities.size(); ++i) {
327 delete activities.at(i);
331 void Track::addLap(){
333 if(activities.size()>0){
334 Activity* activity = activities.last();
340 void Track::addActivity(QString sport){
343 Activity* activity = new Activity(sport);
344 activities.append(activity);
348 Summarized* Track::addPoint(GpsPoint* point){
350 //qDebug() <<"--- Track::addPoint ---";
351 //qDebug() << "Adding point: " << point->toString();
353 Activity* actualActivity = activities.last();
354 Summarized* summary = actualActivity->addPoint(point);
355 addSummary(*summary);
356 //qDebug() << "Track summary:" << toSumString();
361 QString Track::toString(){
363 QString track = QString("Track={fileName:%2, numActivities:%3").arg(fileName).arg(numActivities);
365 QListIterator<Activity*> i(activities);
367 Activity* a = i.next();
368 track.append(QString(", %1").arg(a->toString()));
370 track.append(QString("}"));
374 QList<GpsPoint*> Track::getGpsPoints(){
376 QList<GpsPoint*> points=QList<GpsPoint*>();
381 QListIterator<Activity*> iAct(activities);
382 while (iAct.hasNext()) {
383 Activity* act = iAct.next();
385 QListIterator<Lap*> iLap(act->getLaps());
386 while (iLap.hasNext()) {
387 Lap* lap = iLap.next();
389 QListIterator<GpsPoint*> iPts(lap->getPoints());
390 while (iPts.hasNext()) {
391 GpsPoint* point = iPts.next();
392 points.append(point);
399 bool Track::saveToXML(){
401 XMLFileType fileType;
402 QFile file(fileName);
407 if (!file.open(QIODevice::WriteOnly|QIODevice::Truncate)) {
408 qDebug() << "Error: Cannot write file "
409 << qPrintable(fileName) << ": "
410 << qPrintable(file.errorString());
414 if(fileName.endsWith(".tcx",Qt::CaseInsensitive)){
415 fileType=XMLFile_TCX;
416 }else if(fileName.endsWith(".gpx",Qt::CaseInsensitive)){
417 fileType=XMLFile_GPX;
419 qDebug()<<"Error: XML not recognized. " << "nameFile:" << fileName;
422 QXmlStreamWriter xmlWriter(&file);
424 xmlWriter.setAutoFormatting(true);
426 xmlWriter.writeStartDocument();
428 if(fileType==XMLFile_TCX){
429 xmlWriter.writeStartElement("TrainingCenterDatabase");
430 xmlWriter.writeAttribute("xmlns", TCX_XMLNS);
431 xmlWriter.writeAttribute("xmlns:xsi", TCX_XMLNS_XSI);
432 xmlWriter.writeAttribute("xsi:schemaLocation", TCX_XSI_SCHEMALOCATION);
434 writeTCXCourses(&xmlWriter);
437 xmlWriter.writeStartElement("gpx");
438 xmlWriter.writeAttribute("version",GPX_VERSION);
439 xmlWriter.writeAttribute("creator",GPX_CREATOR);
440 xmlWriter.writeAttribute("xmlns",GPX_XMLNS);
442 writeGPXTracks(&xmlWriter);
448 //xmlWriter->writeEndElement();
449 xmlWriter.writeEndDocument();
451 qDebug() << "file closed";
453 qDebug() << "Error on close: Cannot write file "
454 << qPrintable(fileName) << ": "
455 << qPrintable(file.errorString());
461 void Track::writeGPXTracks(QXmlStreamWriter* xmlWriter){
463 QListIterator<Activity*> i(activities);
465 while (i.hasNext()) {
466 Activity* act = i.next();
467 //xmlWriter->writeStartElement("NextSport");
468 writeGPXTrack(xmlWriter, act);
469 xmlWriter->writeEndElement();
471 xmlWriter->writeEndElement();
472 xmlWriter->writeEndElement();
476 void Track::writeTCXCourses(QXmlStreamWriter* xmlWriter){
478 xmlWriter->writeStartElement("Courses");
479 //xmlWriter->writeStartElement("MultiSportSession");
481 //xmlWriter->writeTextElement("Id",startTime.toString(XML_DATE_FORMAT));
483 QListIterator<Activity*> i(activities);
485 while (i.hasNext()) {
486 Activity* act = i.next();
487 //xmlWriter->writeStartElement("NextSport");
488 writeTCXCourse(xmlWriter, act);
489 xmlWriter->writeEndElement();
491 xmlWriter->writeEndElement();
492 xmlWriter->writeEndElement();
495 void Track::writeGPXTrack(QXmlStreamWriter* xmlWriter, Activity* act){
497 xmlWriter->writeStartElement("trk");
499 xmlWriter->writeTextElement("Name",act->getSport());
501 QListIterator<Lap*> i(act->getLaps());
502 while (i.hasNext()) {
504 writeGPXTrkseg(xmlWriter, lap);
506 xmlWriter->writeEndElement();
511 void Track::writeTCXCourse(QXmlStreamWriter* xmlWriter, Activity* act){
514 xmlWriter->writeStartElement("Course");
515 //xmlWriter->writeAttribute("Sport", act->getSport());
516 xmlWriter->writeTextElement("Name",act->getSport());
518 QListIterator<Lap*> i(act->getLaps());
519 while (i.hasNext()) {
521 writeTCXLap(xmlWriter, lap);
523 xmlWriter->writeEndElement();
526 void Track::writeGPXTrkseg(QXmlStreamWriter* xmlWriter, Lap* lap){
528 xmlWriter->writeStartElement("trkseg");
530 QListIterator<GpsPoint*> i(lap->getPoints());
531 while (i.hasNext()) {
532 GpsPoint* point = i.next();
533 writeGPXPoint(xmlWriter,point);
535 xmlWriter->writeEndElement();
538 void Track::writeTCXLap(QXmlStreamWriter* xmlWriter, Lap* lap){
540 xmlWriter->writeStartElement("Lap");
541 xmlWriter->writeAttribute("StartTime", lap->getStartTime().toString(XML_DATE_FORMAT));
542 xmlWriter->writeTextElement("TotalTimeSeconds",QString::number(lap->getDuration()));
543 xmlWriter->writeTextElement("DistanceMeters",QString::number(lap->getDistance(),'f',10));
544 xmlWriter->writeTextElement("MaximumSpeed",QString::number(lap->getMaxSpeed()));
546 QListIterator<GpsPoint*> i(lap->getPoints());
547 xmlWriter->writeStartElement("Track");
548 while (i.hasNext()) {
549 GpsPoint* point = i.next();
550 writeTCXPoint(xmlWriter,point);
552 xmlWriter->writeEndElement();
553 xmlWriter->writeEndElement();
556 void Track::writeGPXPoint(QXmlStreamWriter* xmlWriter, GpsPoint* point){
558 xmlWriter->writeStartElement("trkpt");
559 xmlWriter->writeAttribute("lat",QString::number(point->getLatitude(),'f',20));
560 xmlWriter->writeAttribute("lon",QString::number(point->getLatitude(),'f',20));
563 xmlWriter->writeTextElement("ele",QString::number(point->getElevation(),'f',20));
564 xmlWriter->writeTextElement("time",point->getTime().toString(XML_DATE_FORMAT));
566 xmlWriter->writeEndElement();
569 void Track::writeTCXPoint(QXmlStreamWriter* xmlWriter, GpsPoint* point){
571 xmlWriter->writeStartElement("Trackpoint");
572 xmlWriter->writeTextElement("Time",point->getTime().toString(XML_DATE_FORMAT));
573 xmlWriter->writeStartElement("Position");
574 xmlWriter->writeTextElement("LatitudeDegrees",QString::number(point->getLatitude(),'f',20));
575 xmlWriter->writeTextElement("LongitudeDegrees",QString::number(point->getLongitude(),'f',20));
576 xmlWriter->writeEndElement();
577 xmlWriter->writeTextElement("AltitudeMeters",QString::number(point->getElevation(),'f',20));
578 xmlWriter->writeTextElement("DistanceMeters",QString::number(point->getDistancePrev(),'f',20));
579 xmlWriter->writeEndElement();