From 2d6e62a111b8ac9d7ef9d55d92837aa8778efd39 Mon Sep 17 00:00:00 2001 From: Niels Date: Sat, 30 Oct 2010 21:35:33 +0200 Subject: [PATCH] add layer that displays points of interest from a .osm file TODO: draw different icons --- main.cpp | 2 +- mainwidget.cpp | 7 ++- mainwidget.h | 2 +- poilayer.cpp | 126 +++++++++++++++++++++++++++++++++++++++++++++++++ poilayer.h | 48 +++++++++++++++++++ 5 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 poilayer.cpp create mode 100644 poilayer.h diff --git a/main.cpp b/main.cpp index 7798cc1..da3d904 100644 --- a/main.cpp +++ b/main.cpp @@ -28,7 +28,7 @@ int main(int argc, char *argv[]) MainWidget w; if (QApplication::arguments().count() > 1) { - w.loadGpx(QApplication::arguments().at(1)); + w.loadFile(QApplication::arguments().at(1)); } QObject::connect(&w, SIGNAL(close()), &a, SLOT(quit())); diff --git a/mainwidget.cpp b/mainwidget.cpp index 1a891b0..0cd1458 100644 --- a/mainwidget.cpp +++ b/mainwidget.cpp @@ -28,6 +28,7 @@ #include "gpslayer.h" #include "gpxlayer.h" #include "markerlayer.h" +#include "poilayer.h" #include "timelayer.h" #include @@ -88,12 +89,16 @@ MainWidget::~MainWidget() { } -void MainWidget::loadGpx(const QString &fileName) +void MainWidget::loadFile(const QString &fileName) { if (fileName.endsWith(".gpx")) { AbstractLayer *l = new GpxLayer(m_map); l->load(fileName); m_map->addLayer(l, 2, "GPS-Track"); + } else if (fileName.endsWith(".osm")) { + AbstractLayer *l = new PoiLayer(m_map); + l->load(fileName); + m_map->addLayer(l, 3, "Points Of Interest"); } } diff --git a/mainwidget.h b/mainwidget.h index dc95d02..471c000 100644 --- a/mainwidget.h +++ b/mainwidget.h @@ -36,7 +36,7 @@ public: MainWidget(QWidget *parent = 0); ~MainWidget(); - void loadGpx(const QString &fileName); + void loadFile(const QString &fileName); signals: void close(); diff --git a/poilayer.cpp b/poilayer.cpp new file mode 100644 index 0000000..3193c85 --- /dev/null +++ b/poilayer.cpp @@ -0,0 +1,126 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * 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 "poilayer.h" + +#include "mapwidget.h" +#include "projection.h" + +#include +#include + +PoiLayer::PoiLayer(MapWidget *map) : + AbstractLayer(map), + m_points(), + m_pointsOnScreen(), + m_icons(), + m_pointsOffset(0, 0) +{ +} + +void PoiLayer::load(const QString &filename) +{ + QFile file(filename); + if (file.open(QIODevice::ReadOnly)) { + QXmlStreamReader xml(&file); + + QStringList categories; + categories << "highway"; + categories << "traffic_calming"; + categories << "barrier"; + categories << "waterway"; + categories << "railway"; + categories << "aeroway"; + categories << "aerialway"; + categories << "power"; + categories << "man_made"; + categories << "leisure"; + categories << "amenity"; + categories << "office"; + categories << "shop"; + categories << "craft"; + categories << "emergency"; + categories << "tourism"; + categories << "historic"; + categories << "landuse"; + categories << "military"; + categories << "natural"; + categories << "geological"; + categories << "sport"; + + QHash tags; + QPointF pos; + while (!xml.atEnd()) { + xml.readNext(); + if (xml.isStartElement()) { + if (xml.name() == "node") { + float lat = xml.attributes().value("lat").toString().toFloat(); + float lon = xml.attributes().value("lon").toString().toFloat(); + + pos = QPointF(Projection::lon2rawx(lon), Projection::lat2rawy(lat)); + } else if (xml.name() == "tag") { + tags.insert(xml.attributes().value("k").toString(), + xml.attributes().value("v").toString()); + } + } else if (xml.isEndElement()) { + if (xml.name() == "node") { + foreach (const QString &c, categories) { + QString t = tags.value(c, ""); + if (!t.isEmpty()) { + m_points << pos; + m_icons << t; + break; + } + } + tags.clear(); + } + } + } + zoom(0); + } +} + +void PoiLayer::zoom(int level) +{ + if (m_points.count() > 1) { + int scale = 1 << level; + m_pointsOnScreen.clear(); + m_pointsOffset = map()->raw2screen(m_points.first().x(), m_points.first().y(), scale); + m_pointsOnScreen << QPoint(0, 0); + for (int i = 1; i < m_points.count(); ++i) { + QPointF p = m_points.at(i); + m_pointsOnScreen << map()->raw2screen(p.x(), p.y(), scale) - m_pointsOffset; + } + } +} + +void PoiLayer::pan(const QPoint &move) +{ + m_pointsOffset += move; +} + +void PoiLayer::paint(QPainter *painter) +{ + QPoint p; + for (int i = 0; i < m_pointsOnScreen.count(); ++i) { + p = m_pointsOnScreen.at(i); + painter->drawEllipse(p + m_pointsOffset, 5, 5); + } +} + diff --git a/poilayer.h b/poilayer.h new file mode 100644 index 0000000..a3c76f0 --- /dev/null +++ b/poilayer.h @@ -0,0 +1,48 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * 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 POI_LAYER_H +#define POI_LAYER_H + +#include "abstractlayer.h" + +#include + +class PoiLayer : public AbstractLayer +{ + Q_OBJECT +public: + PoiLayer(MapWidget *map); + + virtual void load(const QString &filename); + virtual void zoom(int level); + virtual void pan(const QPoint &move); + +protected: + virtual void paint(QPainter *painter); + +private: + QList m_points; + QList m_pointsOnScreen; + QStringList m_icons; + QPoint m_pointsOffset; + +}; + +#endif // POI_LAYER_H