diff --git a/mapwidget.cpp b/mapwidget.cpp index 7fc367b..24eed61 100644 --- a/mapwidget.cpp +++ b/mapwidget.cpp @@ -21,6 +21,7 @@ #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include MapWidget::MapWidget(QWidget *parent) : QWidget(parent), @@ -69,15 +71,22 @@ MapWidget::MapWidget(QWidget *parent) m_copyright(), m_markerPos(), m_markerName(), - m_drawMarker(true) + m_drawMarker(true), + m_track(), + m_trackOnScreen(), + m_trackOffset() { for (int x = 0; x < 100; ++x) { for (int y = 0; y < 100; ++y) { m_pix[x][y] = 0; } } + QString fileName; if (QApplication::arguments().count() > 1) { - loadMapFile(QApplication::arguments().at(1)); + fileName = QApplication::arguments().at(1); + } + if (fileName.endsWith(".map")) { + loadMapFile(fileName); m_zoomable = m_zoomLevel.count() > 1 && m_zoomLevel.count() == m_minIndexXList.count() && @@ -88,18 +97,6 @@ MapWidget::MapWidget(QWidget *parent) m_indexX = (m_minIndexX + m_maxIndexX) / 2; m_indexY = (m_minIndexY + m_maxIndexY) / 2; - if (QApplication::arguments().count() > 3) { - bool ok; - int x = QApplication::arguments().at(2).toInt(&ok); - if (ok) { - m_indexX = x; - } - int y = QApplication::arguments().at(3).toInt(&ok); - if (ok) { - m_indexY = y; - } - } - m_cols = ceil(320.0 / (qreal) m_pixWidth) + 1; m_rows = ceil(240.0 / (qreal) m_pixHeight) + 1; @@ -114,9 +111,12 @@ MapWidget::MapWidget(QWidget *parent) for (int i = 0; i < 19; ++i) { m_zoomLevel << QString::number(i); m_minIndexXList << 0; - m_maxIndexXList << pow(2, i) - 1; + m_maxIndexXList << (1 << i) - 1; m_minIndexYList << 0; - m_maxIndexYList << pow(2, i) - 1; + m_maxIndexYList << (1 << i) - 1; + } + if (fileName.endsWith(".gpx")) { + loadGpx(fileName); } m_baseName = QDir::homePath()+"/Maps/OSM/%z/%x/%y.png"; QTimer::singleShot(100, this, SLOT(loadConfig())); @@ -134,7 +134,9 @@ MapWidget::MapWidget(QWidget *parent) MapWidget::~MapWidget() { - saveConfig(); + if (m_networkMode) { + saveConfig(); + } } void MapWidget::removeMarker(int index) @@ -188,6 +190,7 @@ void MapWidget::resizeEvent(QResizeEvent *event) void MapWidget::mouseMoveEvent(QMouseEvent *event) { if (m_isMoving) { + m_trackOffset += (event->pos() - m_startPos) - m_pos; m_pos = event->pos() - m_startPos; updatePos(); } @@ -197,11 +200,13 @@ void MapWidget::mousePressEvent(QMouseEvent *event) { if (QRect(9, 14, 13, 13).contains(event->pos())) { changeZoomLevel(1); + updateTrack(); reloadPixmaps(); updatePos(); m_isMoving = false; } else if (QRect(9, 214, 13, 13).contains(event->pos())) { changeZoomLevel(-1); + updateTrack(); reloadPixmaps(); updatePos(); m_isMoving = false; @@ -222,9 +227,11 @@ void MapWidget::wheelEvent(QWheelEvent *event) { if (event->delta() < 0) { changeZoomLevel(-1); + updateTrack(); reloadPixmaps(); } else { changeZoomLevel(1); + updateTrack(); reloadPixmaps(); } updatePos(); @@ -232,6 +239,7 @@ void MapWidget::wheelEvent(QWheelEvent *event) void MapWidget::keyPressEvent(QKeyEvent *event) { + QPoint move; int width = 10; if (event->modifiers() & Qt::AltModifier) { width = 100; @@ -252,30 +260,28 @@ void MapWidget::keyPressEvent(QKeyEvent *event) n = m_markerName.last().toInt(); } QString newName = QString::number(n+1); - m_markerPos << geoPos(); - m_markerName << newName; - emit markerAdded(newName); + addMarker(geoPos(), newName); } break; } case Qt::Key_Up: { - m_pos += QPoint(0, width); + move = QPoint(0, width); break; } case Qt::Key_Down: { - m_pos += QPoint(0, -width); + move = QPoint(0, -width); break; } case Qt::Key_Left: { - m_pos += QPoint(width, 0); + move = QPoint(width, 0); break; } case Qt::Key_Right: { - m_pos += QPoint(-width, 0); + move = QPoint(-width, 0); break; } case Qt::Key_C: @@ -290,12 +296,14 @@ void MapWidget::keyPressEvent(QKeyEvent *event) case Qt::Key_O: { changeZoomLevel(-1); + updateTrack(); reloadPixmaps(); break; } case Qt::Key_I: { changeZoomLevel(1); + updateTrack(); reloadPixmaps(); break; } @@ -322,6 +330,8 @@ void MapWidget::keyPressEvent(QKeyEvent *event) break; } } + m_pos += move; + m_trackOffset += move; updatePos(); } @@ -345,6 +355,16 @@ void MapWidget::paintEvent(QPaintEvent *event) if (empty) { painter.drawText(0, 0, width(), height(), Qt::AlignCenter, "No Map Loaded"); } + if (m_trackOnScreen.count() > 1) { + QPoint p1, p2 = m_trackOnScreen.first(); + for (int i = 1; i < m_trackOnScreen.count(); ++i) { + p1 = m_trackOnScreen.at(i); + if (!p1.isNull()) { + painter.drawLine(p1 + m_trackOffset, p2 + m_trackOffset); + p2 = p1; + } + } + } if (m_drawMarker) { int i = 0; painter.setBrush(QBrush(QColor(255, 237, 60))); @@ -557,6 +577,30 @@ void MapWidget::reloadPixmaps() } } +void MapWidget::updateTrack() +{ + if (m_track.count() > 1) { + m_trackOnScreen.clear(); + m_trackOffset = geo2screen(m_track.first().x(), m_track.first().y()); + m_trackOnScreen << QPoint(0, 0); + for (int i = 1; i < m_track.count(); ++i) { + QPointF p = m_track.at(i); + if (!p.isNull()) { + m_trackOnScreen << geo2screen(p.x(), p.y()) - m_trackOffset; + } else { + m_trackOnScreen << QPoint(); + } + } + } +} + +void MapWidget::addMarker(const QPointF &pos, const QString &name) +{ + m_markerPos << pos; + m_markerName << name; + emit markerAdded(name); +} + QString MapWidget::filename(int x, int y) { QString result; @@ -651,9 +695,81 @@ void MapWidget::loadMapFile(const QString &filename) } } +void MapWidget::loadGpx(const QString &filename) +{ + QFile file(filename); + if (file.open(QIODevice::ReadOnly)) { + QXmlStreamReader xml(&file); + + QPolygonF points; + QList elev; + QList time; + + QString tag, tag2; + QString name; + QPointF pos; + while (!xml.atEnd()) { + xml.readNext(); + if (xml.isStartElement()) { + if (xml.name() == "trkpt") { + tag = "trkpt"; + float lat = xml.attributes().value("lat").toString().toFloat(); + float lon = xml.attributes().value("lon").toString().toFloat(); + + points << QPointF(lon, lat); + } else if (xml.name() == "ele") { + tag2 = "ele"; + } else if (xml.name() == "time") { + tag2 = "time"; + } else if (xml.name() == "wpt") { + tag = "wpt"; + float lat = xml.attributes().value("lat").toString().toFloat(); + float lon = xml.attributes().value("lon").toString().toFloat(); + + pos = QPointF(lon, lat); + } else if (xml.name() == "name") { + tag2 = "name"; + } else if (xml.name() == "trk" || + xml.name() == "trkseg") { + } else { + tag2.clear(); + } + } else if (xml.isEndElement()) { + if (xml.name() == "trkseg") { + if (!points.isEmpty()) { + m_track << points; + m_track << QPointF(); + } + points.clear(); + elev.clear(); + time.clear(); + } else if (xml.name() == "wpt") { + //addMarker(pos, name); + name.clear(); + } + } else if (xml.isCharacters() && !xml.isWhitespace()) { + if (tag == "trkpt") { + if (tag2 == "ele") { + elev << xml.text().toString().toFloat(); + } else if (tag2 == "time") { + QDateTime dt = QDateTime::fromString(xml.text().toString(), Qt::ISODate); + time << dt.toTime_t(); + } + } else if (tag == "wpt") { + if (tag2 == "name") { + name = xml.text().toString(); + } + } + } + } + updateTrack(); + } +} + void MapWidget::loadConfig() { QSettings set(QDir::homePath()+"/.nanomap.conf", QSettings::NativeFormat); + set.beginGroup("map"); qreal lon = set.value("lon", 0).toReal(); qreal lat = set.value("lat", 0).toReal(); @@ -661,14 +777,14 @@ void MapWidget::loadConfig() m_usage = set.value("usage", true).toBool(); changeZoomLevel(level - m_level); centerOnGeoPos(lon, lat); + updateTrack(); set.endGroup(); + set.beginGroup("marker"); QStringList m = set.childKeys(); foreach (const QString &marker, m) { QPointF pos = set.value(marker).toPointF(); - m_markerPos << pos; - m_markerName << marker; - emit markerAdded(marker); + addMarker(pos, marker); } set.endGroup(); } @@ -676,6 +792,7 @@ void MapWidget::loadConfig() void MapWidget::saveConfig() { QSettings set(QDir::homePath()+"/.nanomap.conf", QSettings::NativeFormat); + set.beginGroup("map"); QPointF pos = geoPos(); set.setValue("lon", pos.x()); @@ -683,6 +800,7 @@ void MapWidget::saveConfig() set.setValue("level", m_level); set.setValue("usage", m_usage); set.endGroup(); + set.beginGroup("marker"); set.remove(""); for (int i = 0; i < m_markerPos.count(); ++i) { @@ -784,22 +902,22 @@ QPoint MapWidget::geo2screen(qreal lon, qreal lat) const qreal MapWidget::lon2tilex(qreal lon, int z) const { - return (lon + 180.0) / 360.0 * pow(2.0, z); + return (lon + 180.0) / 360.0 * (1 << z); } qreal MapWidget::lat2tiley(qreal lat, int z) const { - return (1.0 - log(tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * pow(2.0, z); + return (1.0 - log(tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * (1 << z); } qreal MapWidget::tilex2lon(qreal x, int z) const { - return x / pow(2.0, z) * 360.0 - 180; + return x / (1 << z) * 360.0 - 180; } qreal MapWidget::tiley2lat(qreal y, int z) const { - qreal n = M_PI - 2.0 * M_PI * y / pow(2.0, z); + qreal n = M_PI - 2.0 * M_PI * y / (1 << z); return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))); } diff --git a/mapwidget.h b/mapwidget.h index 05f7b33..5593414 100644 --- a/mapwidget.h +++ b/mapwidget.h @@ -58,9 +58,12 @@ private slots: private: void updatePos(); void reloadPixmaps(); + void updateTrack(); + void addMarker(const QPointF &pos, const QString &name); QString filename(int x, int y); QPixmap *loadPixmap(int x, int y); void loadMapFile(const QString &filename); + void loadGpx(const QString &filename); void saveConfig(); void downloadTile(int x, int y, int level); void changeZoomLevel(int diff); @@ -94,6 +97,9 @@ private: QList m_markerPos; QStringList m_markerName; bool m_drawMarker; + QPolygonF m_track; + QList m_trackOnScreen; + QPoint m_trackOffset; };