Offline Mapping
-
wrote on 20 Jan 2021, 13:48 last edited by deleted286
Hi everyone. Im trying to do offline map. There is an example called lightmaps. I did not understand one thing. There are too many tiles according to zoom level. Even we have zoom level 2, there were 16 tiles. How can we declare all of them ?
QString path = "http://tile.openstreetmap.org/%1/%2/%3.png";
In the example, it was doing in that way. What refers %1, %2 and %3 i didnt understand it.
Can anybody help me in this issue?https://doc.qt.io/archives/qt-4.8/qt-demos-embedded-lightmaps-example.html
-
Hi everyone. Im trying to do offline map. There is an example called lightmaps. I did not understand one thing. There are too many tiles according to zoom level. Even we have zoom level 2, there were 16 tiles. How can we declare all of them ?
QString path = "http://tile.openstreetmap.org/%1/%2/%3.png";
In the example, it was doing in that way. What refers %1, %2 and %3 i didnt understand it.
Can anybody help me in this issue?https://doc.qt.io/archives/qt-4.8/qt-demos-embedded-lightmaps-example.html
@suslucoder In another thread I told you what it does and gave you a link - did you check that?
I post the link once more: https://doc.qt.io/qt-5/qstring.html#arg -
Hi everyone. Im trying to do offline map. There is an example called lightmaps. I did not understand one thing. There are too many tiles according to zoom level. Even we have zoom level 2, there were 16 tiles. How can we declare all of them ?
QString path = "http://tile.openstreetmap.org/%1/%2/%3.png";
In the example, it was doing in that way. What refers %1, %2 and %3 i didnt understand it.
Can anybody help me in this issue?https://doc.qt.io/archives/qt-4.8/qt-demos-embedded-lightmaps-example.html
wrote on 20 Jan 2021, 14:16 last edited by JonB@suslucoder
And in addition to @jsulm, if you are taking this from that example code look at how they use the string in their code? -
@suslucoder In another thread I told you what it does and gave you a link - did you check that?
I post the link once more: https://doc.qt.io/qt-5/qstring.html#argwrote on 20 Jan 2021, 14:18 last edited by deleted286@jsulm I've checked. I couldnt find the same thing on that example.
It gives an osm link, I dont think they are used QString i which refers to %1, or anything like that.There is just one line which include QString. It is the one I asked.
-
@jsulm I've checked. I couldnt find the same thing on that example.
It gives an osm link, I dont think they are used QString i which refers to %1, or anything like that.There is just one line which include QString. It is the one I asked.
wrote on 20 Jan 2021, 14:29 last edited by@suslucoder
They are defining that string but never using it? You could always have told us in which file in the example code... -
@suslucoder
They are defining that string but never using it? You could always have told us in which file in the example code...wrote on 20 Jan 2021, 14:31 last edited by@JonB on slippymap.cpp
#include <QtWidgets> #include <QtNetwork> #include "slippymap.h" #include "qmath.h" uint qHash(const QPoint& p) { return p.x() * 17 ^ p.y(); } // tile size in pixels const int tdim = 256; QPointF tileForCoordinate(qreal lat, qreal lng, int zoom) { qreal radianLat = qDegreesToRadians(lat); qreal zn = static_cast<qreal>(1 << zoom); qreal tx = (lng + 180.0) / 360.0; qreal ty = 0.5 - log(tan(radianLat) + 1.0 / cos(radianLat)) / M_PI / 2.0; return QPointF(tx * zn, ty * zn); } qreal longitudeFromTile(qreal tx, int zoom) { qreal zn = static_cast<qreal>(1 << zoom); qreal lat = tx / zn * 360.0 - 180.0; return lat; } qreal latitudeFromTile(qreal ty, int zoom) { qreal zn = static_cast<qreal>(1 << zoom); qreal n = M_PI - 2 * M_PI * ty / zn; return qRadiansToDegrees(atan(sinh(n))); } SlippyMap::SlippyMap(QObject *parent) : QObject(parent), width(400), height(300), zoom(15), latitude(59.9138204), longitude(10.7387413) { m_emptyTile = QPixmap(tdim, tdim); m_emptyTile.fill(Qt::lightGray); QNetworkDiskCache *cache = new QNetworkDiskCache; cache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); m_manager.setCache(cache); connect(&m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(handleNetworkData(QNetworkReply*))); } void SlippyMap::invalidate() { if (width <= 0 || height <= 0) return; QPointF ct = tileForCoordinate(latitude, longitude, zoom); qreal tx = ct.x(); qreal ty = ct.y(); // top-left corner of the center tile int xp = width / 2 - (tx - floor(tx)) * tdim; int yp = height / 2 - (ty - floor(ty)) * tdim; // first tile vertical and horizontal int xa = (xp + tdim - 1) / tdim; int ya = (yp + tdim - 1) / tdim; int xs = static_cast<int>(tx) - xa; int ys = static_cast<int>(ty) - ya; // offset for top-left tile m_offset = QPoint(xp - xa * tdim, yp - ya * tdim); // last tile vertical and horizontal int xe = static_cast<int>(tx) + (width - xp - 1) / tdim; int ye = static_cast<int>(ty) + (height - yp - 1) / tdim; // build a rect m_tilesRect = QRect(xs, ys, xe - xs + 1, ye - ys + 1); if (m_url.isEmpty()) download(); emit updated(QRect(0, 0, width, height)); } void SlippyMap::render(QPainter *p, const QRect &rect) { for (int x = 0; x <= m_tilesRect.width(); ++x) for (int y = 0; y <= m_tilesRect.height(); ++y) { QPoint tp(x + m_tilesRect.left(), y + m_tilesRect.top()); QRect box = tileRect(tp); if (rect.intersects(box)) { if (m_tilePixmaps.contains(tp)) p->drawPixmap(box, m_tilePixmaps.value(tp)); else p->drawPixmap(box, m_emptyTile); } } } void SlippyMap::pan(const QPoint &delta) { QPointF dx = QPointF(delta) / qreal(tdim); QPointF center = tileForCoordinate(latitude, longitude, zoom) - dx; latitude = latitudeFromTile(center.y(), zoom); longitude = longitudeFromTile(center.x(), zoom); invalidate(); } void SlippyMap::handleNetworkData(QNetworkReply *reply) { QImage img; QPoint tp = reply->request().attribute(QNetworkRequest::User).toPoint(); if (!reply->error()) if (!img.load(reply, 0)) img = QImage(); reply->deleteLater(); m_tilePixmaps[tp] = QPixmap::fromImage(img); if (img.isNull()) m_tilePixmaps[tp] = m_emptyTile; emit updated(tileRect(tp)); // purge unused spaces const QRect bound = m_tilesRect.adjusted(-2, -2, 2, 2); for (auto it = m_tilePixmaps.keyBegin(); it != m_tilePixmaps.keyEnd(); ++it) { const QPoint &tp = *it; if (!bound.contains(tp)) m_tilePixmaps.remove(tp); } download(); } void SlippyMap::download() { QPoint grab(0, 0); for (int x = 0; x <= m_tilesRect.width(); ++x) for (int y = 0; y <= m_tilesRect.height(); ++y) { QPoint tp = m_tilesRect.topLeft() + QPoint(x, y); if (!m_tilePixmaps.contains(tp)) { grab = tp; break; } } if (grab == QPoint(0, 0)) { m_url = QUrl(); return; } QString path = "http://tile.openstreetmap.org/%1/%2/%3.png"; m_url = QUrl(path.arg(zoom).arg(grab.x()).arg(grab.y())); QNetworkRequest request; request.setUrl(m_url); request.setRawHeader("User-Agent", "The Qt Company (Qt) Graphics Dojo 1.0"); request.setAttribute(QNetworkRequest::User, QVariant(grab)); m_manager.get(request); } QRect SlippyMap::tileRect(const QPoint &tp) { QPoint t = tp - m_tilesRect.topLeft(); int x = t.x() * tdim + m_offset.x(); int y = t.y() * tdim + m_offset.y(); return QRect(x, y, tdim, tdim); }
-
@JonB on slippymap.cpp
#include <QtWidgets> #include <QtNetwork> #include "slippymap.h" #include "qmath.h" uint qHash(const QPoint& p) { return p.x() * 17 ^ p.y(); } // tile size in pixels const int tdim = 256; QPointF tileForCoordinate(qreal lat, qreal lng, int zoom) { qreal radianLat = qDegreesToRadians(lat); qreal zn = static_cast<qreal>(1 << zoom); qreal tx = (lng + 180.0) / 360.0; qreal ty = 0.5 - log(tan(radianLat) + 1.0 / cos(radianLat)) / M_PI / 2.0; return QPointF(tx * zn, ty * zn); } qreal longitudeFromTile(qreal tx, int zoom) { qreal zn = static_cast<qreal>(1 << zoom); qreal lat = tx / zn * 360.0 - 180.0; return lat; } qreal latitudeFromTile(qreal ty, int zoom) { qreal zn = static_cast<qreal>(1 << zoom); qreal n = M_PI - 2 * M_PI * ty / zn; return qRadiansToDegrees(atan(sinh(n))); } SlippyMap::SlippyMap(QObject *parent) : QObject(parent), width(400), height(300), zoom(15), latitude(59.9138204), longitude(10.7387413) { m_emptyTile = QPixmap(tdim, tdim); m_emptyTile.fill(Qt::lightGray); QNetworkDiskCache *cache = new QNetworkDiskCache; cache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); m_manager.setCache(cache); connect(&m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(handleNetworkData(QNetworkReply*))); } void SlippyMap::invalidate() { if (width <= 0 || height <= 0) return; QPointF ct = tileForCoordinate(latitude, longitude, zoom); qreal tx = ct.x(); qreal ty = ct.y(); // top-left corner of the center tile int xp = width / 2 - (tx - floor(tx)) * tdim; int yp = height / 2 - (ty - floor(ty)) * tdim; // first tile vertical and horizontal int xa = (xp + tdim - 1) / tdim; int ya = (yp + tdim - 1) / tdim; int xs = static_cast<int>(tx) - xa; int ys = static_cast<int>(ty) - ya; // offset for top-left tile m_offset = QPoint(xp - xa * tdim, yp - ya * tdim); // last tile vertical and horizontal int xe = static_cast<int>(tx) + (width - xp - 1) / tdim; int ye = static_cast<int>(ty) + (height - yp - 1) / tdim; // build a rect m_tilesRect = QRect(xs, ys, xe - xs + 1, ye - ys + 1); if (m_url.isEmpty()) download(); emit updated(QRect(0, 0, width, height)); } void SlippyMap::render(QPainter *p, const QRect &rect) { for (int x = 0; x <= m_tilesRect.width(); ++x) for (int y = 0; y <= m_tilesRect.height(); ++y) { QPoint tp(x + m_tilesRect.left(), y + m_tilesRect.top()); QRect box = tileRect(tp); if (rect.intersects(box)) { if (m_tilePixmaps.contains(tp)) p->drawPixmap(box, m_tilePixmaps.value(tp)); else p->drawPixmap(box, m_emptyTile); } } } void SlippyMap::pan(const QPoint &delta) { QPointF dx = QPointF(delta) / qreal(tdim); QPointF center = tileForCoordinate(latitude, longitude, zoom) - dx; latitude = latitudeFromTile(center.y(), zoom); longitude = longitudeFromTile(center.x(), zoom); invalidate(); } void SlippyMap::handleNetworkData(QNetworkReply *reply) { QImage img; QPoint tp = reply->request().attribute(QNetworkRequest::User).toPoint(); if (!reply->error()) if (!img.load(reply, 0)) img = QImage(); reply->deleteLater(); m_tilePixmaps[tp] = QPixmap::fromImage(img); if (img.isNull()) m_tilePixmaps[tp] = m_emptyTile; emit updated(tileRect(tp)); // purge unused spaces const QRect bound = m_tilesRect.adjusted(-2, -2, 2, 2); for (auto it = m_tilePixmaps.keyBegin(); it != m_tilePixmaps.keyEnd(); ++it) { const QPoint &tp = *it; if (!bound.contains(tp)) m_tilePixmaps.remove(tp); } download(); } void SlippyMap::download() { QPoint grab(0, 0); for (int x = 0; x <= m_tilesRect.width(); ++x) for (int y = 0; y <= m_tilesRect.height(); ++y) { QPoint tp = m_tilesRect.topLeft() + QPoint(x, y); if (!m_tilePixmaps.contains(tp)) { grab = tp; break; } } if (grab == QPoint(0, 0)) { m_url = QUrl(); return; } QString path = "http://tile.openstreetmap.org/%1/%2/%3.png"; m_url = QUrl(path.arg(zoom).arg(grab.x()).arg(grab.y())); QNetworkRequest request; request.setUrl(m_url); request.setRawHeader("User-Agent", "The Qt Company (Qt) Graphics Dojo 1.0"); request.setAttribute(QNetworkRequest::User, QVariant(grab)); m_manager.get(request); } QRect SlippyMap::tileRect(const QPoint &tp) { QPoint t = tp - m_tilesRect.topLeft(); int x = t.x() * tdim + m_offset.x(); int y = t.y() * tdim + m_offset.y(); return QRect(x, y, tdim, tdim); }
wrote on 20 Jan 2021, 14:51 last edited by JonB@suslucoder
So why do you say it does not use it, or it's doing something else??QString path = "http://tile.openstreetmap.org/%1/%2/%3.png"; m_url = QUrl(path.arg(zoom).arg(grab.x()).arg(grab.y()));
It's using it on the following line!
-
@suslucoder
So why do you say it does not use it, or it's doing something else??QString path = "http://tile.openstreetmap.org/%1/%2/%3.png"; m_url = QUrl(path.arg(zoom).arg(grab.x()).arg(grab.y()));
It's using it on the following line!
wrote on 20 Jan 2021, 14:54 last edited by deleted286@JonB you are so clear!
I wouldn't ask such a question if I understood what they were doing -
@JonB you are so clear!
I wouldn't ask such a question if I understood what they were doingwrote on 20 Jan 2021, 14:57 last edited by JonB@suslucoder
OK, forget theQUrl
part on that second line.path
is aQString
. And it's usingpath.arg().arg()...
. Look up exactly what @jsulm referred you to:I post the link once more: https://doc.qt.io/qt-5/qstring.html#arg
That explains exactly why there are
%1
,%2
s etc. in the string and whatQString::arg()
does with them. He & I don't know how to explain any better! -
@JonB you are so clear!
I wouldn't ask such a question if I understood what they were doing@suslucoder Maybe one example:
QString path = "http://tile.openstreetmap.org/%1/%2/%3.png"; qDebug() << path.arg("ONE").arg("TWO").arg("THREE");
Will output: http://tile.openstreetmap.org/ONE/TWO/THREE.png
-
@suslucoder Maybe one example:
QString path = "http://tile.openstreetmap.org/%1/%2/%3.png"; qDebug() << path.arg("ONE").arg("TWO").arg("THREE");
Will output: http://tile.openstreetmap.org/ONE/TWO/THREE.png
wrote on 20 Jan 2021, 15:13 last edited by@jsulm understand now. Thank you
-
@suslucoder Maybe one example:
QString path = "http://tile.openstreetmap.org/%1/%2/%3.png"; qDebug() << path.arg("ONE").arg("TWO").arg("THREE");
Will output: http://tile.openstreetmap.org/ONE/TWO/THREE.png
wrote on 21 Jan 2021, 06:49 last edited by@jsulm I understand it. You locked my question, but it was another question.
Im trying to find a way for tile a map. -
@jsulm I understand it. You locked my question, but it was another question.
Im trying to find a way for tile a map. -
3/14