最简单粗暴的加载方式,将每一层级的所有瓦片地图全部加载
注:该方式仅能够在瓦片地图层级较低时使用,否则卡顿!!!
瓦片地图数据来源:水经注-高德地图-卫星地图
瓦片地图瓦片大小:256 * 256像素
瓦片地图坐标投影:GCJ02 Web 墨卡托投影
1、动态演示效果:
2、静态展示图片:
核心代码
1、数据定义
#define PIXMAP_SIZE 256
// 瓦片坐标
struct TileCoord
{
double x;
double y;
};
// 经纬度坐标
struct GeoCoord
{
GeoCoord() = default;
GeoCoord(double _lon, double _lat) : lon(_lon), lat(_lat) {}
double lon; // 经度
double lat; // 纬度
};
2、MapUtility类
class MapUtility
{
public:
// 场景坐标转经纬度
static GeoCoord mapFromScene(QPointF scenePos, int level);
private:
// 场景坐标转瓦片坐标(瓦片坐标系)
static QPoint tileCoordFromScene(QPointF scenePos, int level);
// 场景坐标转所在瓦片像素点坐标
static QPointF tilePixelCoordFromScene(QPointF scenePos, int level);
};
#include "MapUtility.h"
#include "TileUtility.h"
GeoCoord MapUtility::mapFromScene(QPointF scenePos, int level)
{
QPoint tileCoord = tileCoordFromScene(scenePos, level);
QPointF tilePixelCoord = tilePixelCoordFromScene(scenePos, level);
return TileUtility::pixelToLonLat(tilePixelCoord.x(), tilePixelCoord.y(), tileCoord.x(), tileCoord.y(), level);
}
QPoint MapUtility::tileCoordFromScene(QPointF scenePos, int level)
{
int tileX = std::floor(scenePos.x() / PIXMAP_SIZE);
int tileY = std::floor(scenePos.y() / PIXMAP_SIZE);
return QPoint(tileX, tileY);
}
QPointF MapUtility::tilePixelCoordFromScene(QPointF scenePos, int level)
{
QPoint tileCoord = tileCoordFromScene(scenePos, level);
double left = tileCoord.x() * PIXMAP_SIZE; // scenePos所在瓦片的左侧位于场景中的坐标
double top = tileCoord.y() * PIXMAP_SIZE; // scenePos所在瓦片的上侧位于场景中的坐标
return QPointF(scenePos.x() - left, scenePos.y() - top);
}
3、TileUtility类
class TileUtility
{
friend class MapUtility;
private:
/**
* 将地图层级下瓦片的像素点转换到经纬度
* 瓦片地图左上角为(0, 0)点
* @param pixelX 瓦片像素点X
* @param pixelY 瓦片像素点Y
* @param tileX 瓦片坐标X
* @param tileY 瓦片坐标Y
* @param level 瓦片层级
*/
static GeoCoord pixelToLonLat(double pixelX, double pixelY, int tileX, int tileY, int level);
static double pixelXToLon(double pixelX, double tileX, int level);
static double pixelXToLat(double pixelY, double tileY, int level);
static double mathSinH(double value);
/**
* 获取地图层级下X/Y轴上的瓦片数量
* @param level 瓦片层级
* @return 瓦片数量
*/
static int mapSize(int level);
};
GeoCoord TileUtility::pixelToLonLat(double pixelX, double pixelY, int tileX, int tileY, int level)
{
double lon = pixelXToLon(pixelX, tileX, level);
double lat = pixelXToLat(pixelY, tileY, level);
return GeoCoord(lon, lat);
}
double TileUtility::pixelXToLon(double pixelX, double tileX, int level)
{
const double pixelXToTileAddition = pixelX / PIXMAP_SIZE;
const double lon = (tileX + pixelXToTileAddition) / mapSize(level) * 360 - 180;
return lon;
}
double TileUtility::pixelXToLat(double pixelY, double tileY, int level)
{
const double pixelYToTileAddition = pixelY / PIXMAP_SIZE;
const double lat = qAtan(mathSinH(M_PI * (1 - 2 * (tileY + pixelYToTileAddition) / mapSize(level)))) * 180.0 / M_PI;
return lat;
}
double TileUtility::mathSinH(double value)
{
return (qExp(value) - qExp(-value)) / 2;
}
int TileUtility::mapSize(int level)
{
return pow(2, level);
}
4、场景粗暴加载瓦片地图
void MapScene::updateScene()
{
QString dirPath = QString("F:/MapData/GaoDeMap/Map/MapPng/L0%1").arg(m_curLevel + 1);
int size = pow(2, m_curLevel);
for (int row = 0; row < size; ++row)
{
for (int col = 0; col < size; ++col)
{
QString fileName = QString("%1/Map_%2-%3.png").arg(dirPath)
.arg(QString::number(row + 1).rightJustified(2, '0')).arg(QString::number(col + 1).rightJustified(2, '0'));
QPixmap pixmap(fileName);
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
item->setPos(PIXMAP_SIZE * col, PIXMAP_SIZE * row);
addItem(item);
}
}
}