summaryrefslogtreecommitdiffstats
path: root/kipi-plugins/gpssync/gpsdataparser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kipi-plugins/gpssync/gpsdataparser.cpp')
-rw-r--r--kipi-plugins/gpssync/gpsdataparser.cpp275
1 files changed, 275 insertions, 0 deletions
diff --git a/kipi-plugins/gpssync/gpsdataparser.cpp b/kipi-plugins/gpssync/gpsdataparser.cpp
new file mode 100644
index 0000000..2124f1d
--- /dev/null
+++ b/kipi-plugins/gpssync/gpsdataparser.cpp
@@ -0,0 +1,275 @@
+/* ============================================================
+ *
+ * This file is a part of kipi-plugins project
+ * http://www.kipi-plugins.org
+ *
+ * Date : 2006-09-19
+ * Description : GPS data file parser.
+ * (GPX format http://www.topografix.com/gpx.asp).
+ *
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, 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.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// Qt includes.
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qfile.h>
+#include <qdom.h>
+#include <qtextstream.h>
+
+// KDE includes.
+
+#include <kdebug.h>
+
+// Local includes.
+
+#include "gpsdataparser.h"
+
+namespace KIPIGPSSyncPlugin
+{
+
+GPSDataParser::GPSDataParser()
+{
+ clear();
+}
+
+void GPSDataParser::clear()
+{
+ m_GPSDataMap.clear();
+}
+
+int GPSDataParser::numPoints()
+{
+ return m_GPSDataMap.count();
+}
+
+bool GPSDataParser::matchDate(const QDateTime& photoDateTime, int maxGapTime, int timeZone,
+ bool interpolate, int interpolationDstTime,
+ GPSDataContainer& gpsData)
+{
+ // GPS device are sync in time by satelite using GMT time.
+ // If the camera time is different than GMT time, we need to convert it to GMT time
+ // Using the time zone.
+ QDateTime cameraGMTDateTime = photoDateTime.addSecs(timeZone*(-1));
+
+ kdDebug() << "cameraGMTDateTime: " << cameraGMTDateTime << endl;
+
+ // We trying to find the right date in the GPS points list.
+ bool findItem = false;
+ int nbSecItem = maxGapTime;
+ int nbSecs;
+
+ for (GPSDataMap::Iterator it = m_GPSDataMap.begin();
+ it != m_GPSDataMap.end(); ++it )
+ {
+ // Here we check a possible accuracy in seconds between the
+ // Camera GMT time and the GPS device GMT time.
+
+ nbSecs = abs(cameraGMTDateTime.secsTo( it.key() ));
+
+ // We tring to find the minimal accuracy.
+ if( nbSecs < maxGapTime && nbSecs < nbSecItem)
+ {
+ gpsData = m_GPSDataMap[it.key()];
+ findItem = true;
+ nbSecItem = nbSecs;
+ }
+ }
+
+ if (findItem) return true;
+
+ // If we can't find it, we will trying to interpolate the GPS point.
+
+ if (interpolate)
+ {
+ // The interpolate GPS point will be separate by at the maximum of 'interpolationDstTime'
+ // seconds before and after the next and previous real GPS point found.
+
+ QDateTime prevDateTime = findPrevDate(cameraGMTDateTime, interpolationDstTime);
+ QDateTime nextDateTime = findNextDate(cameraGMTDateTime, interpolationDstTime);
+
+ if (!nextDateTime.isNull() && !prevDateTime.isNull())
+ {
+ GPSDataContainer prevGPSPoint = m_GPSDataMap[prevDateTime];
+ GPSDataContainer nextGPSPoint = m_GPSDataMap[nextDateTime];
+
+ double alt1 = prevGPSPoint.altitude();
+ double lon1 = prevGPSPoint.longitude();
+ double lat1 = prevGPSPoint.latitude();
+ uint t1 = prevDateTime.toTime_t();
+ double alt2 = nextGPSPoint.altitude();
+ double lon2 = nextGPSPoint.longitude();
+ double lat2 = nextGPSPoint.latitude();
+ uint t2 = nextDateTime.toTime_t();
+ uint tCor = cameraGMTDateTime.toTime_t();
+
+ if (tCor-t1 != 0)
+ {
+ gpsData.setAltitude(alt1 + (alt2-alt1) * (tCor-t1)/(t2-t1));
+ gpsData.setLatitude(lat1 + (lat2-lat1) * (tCor-t1)/(t2-t1));
+ gpsData.setLongitude(lon1 + (lon2-lon1) * (tCor-t1)/(t2-t1));
+ gpsData.setInterpolated(true);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+QDateTime GPSDataParser::findNextDate(const QDateTime& dateTime, int secs)
+{
+ // We will find the item in GPS data list where the time is
+ // at the maximum bigger than 'secs' mn of the value to match.
+ QDateTime itemFound = dateTime.addSecs(secs);
+ bool found = false;
+
+ for (GPSDataMap::Iterator it = m_GPSDataMap.begin();
+ it != m_GPSDataMap.end(); ++it )
+ {
+ if (it.key() > dateTime)
+ {
+ if (it.key() < itemFound)
+ {
+ itemFound = it.key();
+ found = true;
+ }
+ }
+ }
+
+ if (found)
+ return itemFound;
+
+ return QDateTime();
+}
+
+QDateTime GPSDataParser::findPrevDate(const QDateTime& dateTime, int secs)
+{
+ // We will find the item in GPS data list where the time is
+ // at the maximum smaller than 'secs' mn of the value to match.
+ QDateTime itemFound = dateTime.addSecs((-1)*secs);
+ bool found = false;
+
+ for (GPSDataMap::Iterator it = m_GPSDataMap.begin();
+ it != m_GPSDataMap.end(); ++it )
+ {
+ if (it.key() < dateTime)
+ {
+ if (it.key() > itemFound)
+ {
+ itemFound = it.key();
+ found = true;
+ }
+ }
+ }
+
+ if (found)
+ return itemFound;
+
+ return QDateTime();
+}
+
+bool GPSDataParser::loadGPXFile(const KURL& url)
+{
+ QFile gpxfile(url.path());
+
+ if (!gpxfile.open(IO_ReadOnly))
+ return false;
+
+ QDomDocument gpxDoc("gpx");
+ if (!gpxDoc.setContent(&gpxfile))
+ return false;
+
+ QDomElement gpxDocElem = gpxDoc.documentElement();
+ if (gpxDocElem.tagName()!="gpx")
+ return false;
+
+ for (QDomNode nTrk = gpxDocElem.firstChild();
+ !nTrk.isNull(); nTrk = nTrk.nextSibling())
+ {
+ QDomElement trkElem = nTrk.toElement();
+ if (trkElem.isNull()) continue;
+ if (trkElem.tagName() != "trk") continue;
+
+ for (QDomNode nTrkseg = trkElem.firstChild();
+ !nTrkseg.isNull(); nTrkseg = nTrkseg.nextSibling())
+ {
+ QDomElement trksegElem = nTrkseg.toElement();
+ if (trksegElem.isNull()) continue;
+ if (trksegElem.tagName() != "trkseg") continue;
+
+ for (QDomNode nTrkpt = trksegElem.firstChild();
+ !nTrkpt.isNull(); nTrkpt = nTrkpt.nextSibling())
+ {
+ QDomElement trkptElem = nTrkpt.toElement();
+ if (trkptElem.isNull()) continue;
+ if (trkptElem.tagName() != "trkpt") continue;
+
+ QDateTime ptDateTime;
+ double ptAltitude = 0.0;
+ double ptLatitude = 0.0;
+ double ptLongitude = 0.0;
+
+ // Get GPS position. If not available continue to next point.
+ QString lat = trkptElem.attribute("lat");
+ QString lon = trkptElem.attribute("lon");
+ if (lat.isEmpty() || lon.isEmpty()) continue;
+
+ ptLatitude = lat.toDouble();
+ ptLongitude = lon.toDouble();
+
+ // Get metadata of track point (altitude and time stamp)
+ for (QDomNode nTrkptMeta = trkptElem.firstChild();
+ !nTrkptMeta.isNull(); nTrkptMeta = nTrkptMeta.nextSibling())
+ {
+ QDomElement trkptMetaElem = nTrkptMeta.toElement();
+ if (trkptMetaElem.isNull()) continue;
+ if (trkptMetaElem.tagName() == QString("time"))
+ {
+ // Get GPS point time stamp. If not available continue to next point.
+ QString time = trkptMetaElem.text();
+ if (time.isEmpty()) continue;
+ ptDateTime = QDateTime::fromString(time, Qt::ISODate);
+ }
+ if (trkptMetaElem.tagName() == QString("ele"))
+ {
+ // Get GPS point altitude. If not available continue to next point.
+ QString ele = trkptMetaElem.text();
+ if (!ele.isEmpty())
+ ptAltitude = ele.toDouble();
+ }
+ }
+
+ if (ptDateTime.isNull())
+ continue;
+
+ GPSDataContainer gpsData(ptAltitude, ptLatitude, ptLongitude, false);
+ m_GPSDataMap.insert( ptDateTime, gpsData );
+ }
+ }
+ }
+
+ kdDebug( 51001 ) << "GPX File " << url.fileName()
+ << " parsed with " << numPoints()
+ << " points extracted" << endl;
+ return true;
+}
+
+} // NameSpace KIPIGPSSyncPlugin