1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-03-13 10:37:45 +01:00

Overlay two consecutive layers when drawing ENC atlases

This commit is contained in:
Martin Tůma 2025-03-06 07:55:01 +01:00
parent 66693cd5c9
commit 2595926b7f
12 changed files with 198 additions and 189 deletions

View File

@ -118,6 +118,7 @@ HEADERS += src/common/config.h \
src/data/style.h \
src/data/twonavparser.h \
src/data/txtparser.h \
src/map/ENC/data.h \
src/map/IMG/light.h \
src/map/downloader.h \
src/map/demloader.h \

View File

@ -39,15 +39,12 @@ bool AtlasData::polyCb(MapEntry *map, void *context)
ctx->cacheLock.unlock();
MapData *data = new MapData(map->path);
data->polygons(ctx->rect, ctx->polygons);
data->lines(ctx->rect, ctx->lines);
data->polys(ctx->rect, ctx->polygons, ctx->lines);
ctx->cacheLock.lock();
ctx->cache.insert(map->path, data);
} else {
cached->polygons(ctx->rect, ctx->polygons);
cached->lines(ctx->rect, ctx->lines);
}
} else
cached->polys(ctx->rect, ctx->polygons, ctx->lines);
ctx->cacheLock.unlock();
map->lock.unlock();

View File

@ -10,18 +10,18 @@ namespace ENC {
typedef QCache<QString, MapData> MapCache;
class AtlasData
class AtlasData : public Data
{
public:
AtlasData(MapCache &cache, QMutex &cacheLock)
: _cache(cache), _cacheLock(cacheLock) {}
~AtlasData();
virtual ~AtlasData();
void addMap(const RectC &bounds, const QString &path);
void polys(const RectC &rect, QList<MapData::Poly> *polygons,
virtual void polys(const RectC &rect, QList<MapData::Poly> *polygons,
QList<MapData::Line> *lines);
void points(const RectC &rect, QList<MapData::Point> *points);
virtual void points(const RectC &rect, QList<MapData::Point> *points);
private:
struct MapEntry {

79
src/map/ENC/data.h Normal file
View File

@ -0,0 +1,79 @@
#ifndef ENC_DATA_H
#define ENC_DATA_H
#include "common/rectc.h"
#include "common/polygon.h"
namespace ENC {
class Data
{
public:
typedef QMap<uint, QByteArray> Attributes;
class Poly {
public:
Poly(uint type, const Polygon &path, const Attributes &attr, uint HUNI);
RectC bounds() const {return _path.boundingRect();}
const Polygon &path() const {return _path;}
uint type() const {return _type;}
const Attributes &attributes() const {return _attr;}
uint HUNI() const {return _HUNI;}
private:
uint _type;
Polygon _path;
Attributes _attr;
uint _HUNI;
};
class Line {
public:
Line(uint type, const QVector<Coordinates> &path, const Attributes &attr);
RectC bounds() const;
const QVector<Coordinates> &path() const {return _path;}
uint type() const {return _type;}
const QString &label() const {return _label;}
const Attributes &attributes() const {return _attr;}
private:
uint _type;
QVector<Coordinates> _path;
QString _label;
Attributes _attr;
};
class Point {
public:
Point(uint type, const Coordinates &c, const Attributes &attr,
uint HUNI, bool polygon = false);
Point(uint type, const Coordinates &s, const QString &label);
const Coordinates &pos() const {return _pos;}
uint type() const {return _type;}
const QString &label() const {return _label;}
const Attributes &attributes() const {return _attr;}
bool polygon() const {return _polygon;}
bool operator<(const Point &other) const
{return _id < other._id;}
private:
uint _type;
Coordinates _pos;
QString _label;
quint64 _id;
Attributes _attr;
bool _polygon;
};
virtual void polys(const RectC &rect, QList<Data::Poly> *polygons,
QList<Data::Line> *lines) = 0;
virtual void points(const RectC &rect, QList<Data::Point> *points) = 0;
};
}
#endif // ENC_DATA_H

View File

@ -866,7 +866,7 @@ MapData::~MapData()
delete _points.GetAt(pit);
}
void MapData::points(const RectC &rect, QList<Point> *points) const
void MapData::points(const RectC &rect, QList<Point> *points)
{
double min[2], max[2];
@ -876,18 +876,12 @@ void MapData::points(const RectC &rect, QList<Point> *points) const
_lines.Search(min, max, linePointCb, points);
}
void MapData::lines(const RectC &rect, QList<Line> *lines) const
void MapData::polys(const RectC &rect, QList<Poly> *polygons,
QList<Line> *lines)
{
double min[2], max[2];
rectcBounds(rect, min, max);
_lines.Search(min, max, lineCb, lines);
}
void MapData::polygons(const RectC &rect, QList<Poly> *polygons) const
{
double min[2], max[2];
rectcBounds(rect, min, max);
_areas.Search(min, max, polygonCb, polygons);
}

View File

@ -1,82 +1,21 @@
#ifndef ENC_MAPDATA_H
#define ENC_MAPDATA_H
#include "common/rectc.h"
#include "common/rtree.h"
#include "common/polygon.h"
#include "iso8211.h"
#include "data.h"
namespace ENC {
class MapData
class MapData : public Data
{
public:
typedef QMap<uint, QByteArray> Attributes;
class Poly {
public:
Poly(uint type, const Polygon &path, const Attributes &attr, uint HUNI);
RectC bounds() const {return _path.boundingRect();}
const Polygon &path() const {return _path;}
uint type() const {return _type;}
const Attributes &attributes() const {return _attr;}
uint HUNI() const {return _HUNI;}
private:
uint _type;
Polygon _path;
Attributes _attr;
uint _HUNI;
};
class Line {
public:
Line(uint type, const QVector<Coordinates> &path, const Attributes &attr);
RectC bounds() const;
const QVector<Coordinates> &path() const {return _path;}
uint type() const {return _type;}
const QString &label() const {return _label;}
const Attributes &attributes() const {return _attr;}
private:
uint _type;
QVector<Coordinates> _path;
QString _label;
Attributes _attr;
};
class Point {
public:
Point(uint type, const Coordinates &c, const Attributes &attr,
uint HUNI, bool polygon = false);
Point(uint type, const Coordinates &s, const QString &label);
const Coordinates &pos() const {return _pos;}
uint type() const {return _type;}
const QString &label() const {return _label;}
const Attributes &attributes() const {return _attr;}
bool polygon() const {return _polygon;}
bool operator<(const Point &other) const
{return _id < other._id;}
private:
uint _type;
Coordinates _pos;
QString _label;
quint64 _id;
Attributes _attr;
bool _polygon;
};
MapData(const QString &path);
~MapData();
virtual ~MapData();
void polygons(const RectC &rect, QList<Poly> *polygons) const;
void lines(const RectC &rect, QList<Line> *lines) const;
void points(const RectC &rect, QList<Point> *points) const;
virtual void polys(const RectC &rect, QList<Poly> *polygons,
QList<Line> *lines);
virtual void points(const RectC &rect, QList<Point> *points);
private:
struct Sounding {

View File

@ -28,14 +28,14 @@ static double angle(uint type, const QVariant &param)
? 90 + param.toDouble() : NAN;
}
static bool showLabel(const QImage *img, const Range &range, int zoom, int type)
bool RasterTile::showLabel(const QImage *img, int type) const
{
if (type>>16 == I_DISMAR)
return true;
int limit = (!range.size())
? range.min() : range.min() + (range.size() + 1) / 2;
if ((img || (type>>16 == SOUNDG)) && (zoom < limit))
int limit = (!_zoomRange.size())
? _zoomRange.min() : _zoomRange.min() + (_zoomRange.size() + 1) / 2;
if ((img || (type>>16 == SOUNDG)) && (_zoom < limit))
return false;
return true;
@ -139,10 +139,10 @@ static void drawArrow(QPainter *painter, const QPolygonF &polygon, uint type)
}
void RasterTile::drawArrows(QPainter *painter,
const QList<MapData::Point> &points) const
const QList<Data::Point> &points) const
{
for (int i = 0; i < points.size(); i++) {
const MapData::Point &point = points.at(i);
const Data::Point &point = points.at(i);
if (point.type()>>16 == TSSLPT || point.type()>>16 == RCTLPT) {
QPolygonF polygon(tsslptArrow(ll2xy(point.pos()),
@ -153,11 +153,11 @@ void RasterTile::drawArrows(QPainter *painter,
}
void RasterTile::drawPolygons(QPainter *painter,
const QList<MapData::Poly> &polygons) const
const QList<Data::Poly> &polygons) const
{
for (int n = 0; n < _style->drawOrder().size(); n++) {
for (int i = 0; i < polygons.size(); i++) {
const MapData::Poly &poly = polygons.at(i);
const Data::Poly &poly = polygons.at(i);
if (poly.type() != _style->drawOrder().at(n))
continue;
const Style::Polygon &style = _style->polygon(poly.type());
@ -185,12 +185,12 @@ void RasterTile::drawPolygons(QPainter *painter,
}
}
void RasterTile::drawLines(QPainter *painter, const QList<MapData::Line> &lines) const
void RasterTile::drawLines(QPainter *painter, const QList<Data::Line> &lines) const
{
painter->setBrush(Qt::NoBrush);
for (int i = 0; i < lines.size(); i++) {
const MapData::Line &line = lines.at(i);
const Data::Line &line = lines.at(i);
const Style::Line &style = _style->line(line.type());
if (!style.img().isNull()) {
@ -257,9 +257,9 @@ void RasterTile::drawSectorLights(QPainter *painter,
}
}
void RasterTile::processPoints(QList<MapData::Point> &points,
void RasterTile::processPoints(QList<Data::Point> &points,
QList<TextItem*> &textItems, QList<TextItem*> &lights,
QList<SectorLight> &sectorLights)
QList<SectorLight> &sectorLights, bool overZoom)
{
LightMap lightsMap;
SignalSet signalsSet;
@ -270,10 +270,10 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
/* Lights & Signals */
for (i = 0; i < points.size(); i++) {
const MapData::Point &point = points.at(i);
const Data::Point &point = points.at(i);
if (point.type()>>16 == LIGHTS) {
const MapData::Attributes &attr = point.attributes();
const Data::Attributes &attr = point.attributes();
Style::Color color = (Style::Color)(attr.value(COLOUR).toUInt());
double range = attr.value(VALNMR).toDouble();
@ -293,13 +293,13 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
/* Everything else */
for ( ; i < points.size(); i++) {
const MapData::Point &point = points.at(i);
const Data::Point &point = points.at(i);
QPoint pos(ll2xy(point.pos()).toPoint());
const Style::Point &style = _style->point(point.type());
const QString *label = point.label().isEmpty() ? 0 : &(point.label());
const QImage *img = style.img().isNull() ? 0 : &style.img();
const QFont *fnt = showLabel(img, _zoomRange, _zoom, point.type())
const QFont *fnt = (overZoom || showLabel(img, point.type()))
? _style->font(style.textFontSize()) : 0;
const QColor *color = &style.textColor();
const QColor *hColor = style.haloColor().isValid()
@ -327,11 +327,11 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
}
}
void RasterTile::processLines(const QList<MapData::Line> &lines,
void RasterTile::processLines(const QList<Data::Line> &lines,
QList<TextItem*> &textItems)
{
for (int i = 0; i < lines.size(); i++) {
const MapData::Line &line = lines.at(i);
const Data::Line &line = lines.at(i);
const Style::Line &style = _style->line(line.type());
if (style.img().isNull() && style.pen() == Qt::NoPen)
@ -351,11 +351,20 @@ void RasterTile::processLines(const QList<MapData::Line> &lines,
}
}
void RasterTile::fetchData(QList<MapData::Poly> &polygons,
QList<MapData::Line> &lines, QList<MapData::Point> &points)
void RasterTile::render()
{
QPoint ttl(_rect.topLeft());
QImage img(_rect.width() * _ratio, _rect.height() * _ratio,
QImage::Format_ARGB32_Premultiplied);
img.setDevicePixelRatio(_ratio);
img.fill(Qt::transparent);
QPainter painter(&img);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(-_rect.x(), -_rect.y());
QPoint ttl(_rect.topLeft());
QRectF polyRect(ttl, QPointF(ttl.x() + _rect.width(), ttl.y()
+ _rect.height()));
RectD polyRectD(_transform.img2proj(polyRect.topLeft()),
@ -368,50 +377,31 @@ void RasterTile::fetchData(QList<MapData::Poly> &polygons,
_transform.img2proj(pointRect.bottomRight()));
RectC pointRectC(pointRectD.toRectC(_proj, 20));
if (_map) {
_map->lines(polyRectC, &lines);
_map->polygons(polyRectC, &polygons);
_map->points(pointRectC, &points);
} else {
_atlas->polys(polyRectC, &polygons, &lines);
_atlas->points(pointRectC, &points);
for (int i = 0; i < _data.size(); i++) {
QList<Data::Line> lines;
QList<Data::Poly> polygons;
QList<Data::Point> points;
QList<TextItem*> textItems, lights;
QList<SectorLight> sectorLights;
_data.at(i)->polys(polyRectC, &polygons, &lines);
_data.at(i)->points(pointRectC, &points);
processPoints(points, textItems, lights, sectorLights,
_data.size() > 1 && i == 0);
processLines(lines, textItems);
drawPolygons(&painter, polygons);
drawLines(&painter, lines);
drawArrows(&painter, points);
drawTextItems(&painter, lights);
drawSectorLights(&painter, sectorLights);
drawTextItems(&painter, textItems);
qDeleteAll(textItems);
qDeleteAll(lights);
}
}
void RasterTile::render()
{
QImage img(_rect.width() * _ratio, _rect.height() * _ratio,
QImage::Format_ARGB32_Premultiplied);
QList<MapData::Line> lines;
QList<MapData::Poly> polygons;
QList<MapData::Point> points;
QList<TextItem*> textItems, lights;
QList<SectorLight> sectorLights;
img.setDevicePixelRatio(_ratio);
img.fill(Qt::transparent);
fetchData(polygons, lines, points);
processPoints(points, textItems, lights, sectorLights);
processLines(lines, textItems);
QPainter painter(&img);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(-_rect.x(), -_rect.y());
drawPolygons(&painter, polygons);
drawLines(&painter, lines);
drawArrows(&painter, points);
drawTextItems(&painter, lights);
drawSectorLights(&painter, sectorLights);
drawTextItems(&painter, textItems);
qDeleteAll(textItems);
qDeleteAll(lights);
//painter.setPen(Qt::red);
//painter.setBrush(Qt::NoBrush);

View File

@ -5,7 +5,7 @@
#include "common/range.h"
#include "map/projection.h"
#include "map/transform.h"
#include "mapdata.h"
#include "data.h"
#include "style.h"
#include "atlasdata.h"
@ -17,14 +17,17 @@ class RasterTile
{
public:
RasterTile(const Projection &proj, const Transform &transform,
const Style *style, const MapData *data, int zoom, const Range &zoomRange,
const QRect &rect, qreal ratio) :
_proj(proj), _transform(transform), _style(style), _map(data), _atlas(0),
_zoom(zoom), _zoomRange(zoomRange), _rect(rect), _ratio(ratio) {}
const Style *style, Data *data, int zoom,
const Range &zoomRange, const QRect &rect, qreal ratio) :
_proj(proj), _transform(transform), _style(style),
_zoom(zoom), _zoomRange(zoomRange), _rect(rect), _ratio(ratio)
{
_data.append(data);
}
RasterTile(const Projection &proj, const Transform &transform,
const Style *style, AtlasData *data, int zoom, const Range &zoomRange,
const QRect &rect, qreal ratio) :
_proj(proj), _transform(transform), _style(style), _map(0), _atlas(data),
const Style *style, const QList<Data*> &data, int zoom,
const Range &zoomRange, const QRect &rect, qreal ratio) :
_proj(proj), _transform(transform), _style(style), _data(data),
_zoom(zoom), _zoomRange(zoomRange), _rect(rect), _ratio(ratio) {}
int zoom() const {return _zoom;}
@ -51,8 +54,6 @@ private:
typedef QMap<Coordinates, Style::Color> LightMap;
typedef QSet<Coordinates> SignalSet;
void fetchData(QList<MapData::Poly> &polygons, QList<MapData::Line> &lines,
QList<MapData::Point> &points);
QPointF ll2xy(const Coordinates &c) const
{return _transform.proj2img(_proj.ll2xy(c));}
QPainterPath painterPath(const Polygon &polygon) const;
@ -60,25 +61,21 @@ private:
QVector<QPolygonF> polylineM(const QVector<Coordinates> &path) const;
QPolygonF tsslptArrow(const QPointF &p, qreal angle) const;
QPointF centroid(const QVector<Coordinates> &polygon) const;
void processPoints(QList<MapData::Point> &points,
void processPoints(QList<Data::Point> &points,
QList<TextItem*> &textItems, QList<TextItem *> &lights,
QList<SectorLight> &sectorLights);
void processLines(const QList<MapData::Line> &lines,
QList<TextItem*> &textItems);
void drawArrows(QPainter *painter, const QList<MapData::Point> &points) const;
void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons) const;
void drawLines(QPainter *painter, const QList<MapData::Line> &lines) const;
QList<SectorLight> &sectorLights, bool overZoom);
void processLines(const QList<Data::Line> &lines, QList<TextItem*> &textItems);
void drawArrows(QPainter *painter, const QList<Data::Point> &points) const;
void drawPolygons(QPainter *painter, const QList<Data::Poly> &polygons) const;
void drawLines(QPainter *painter, const QList<Data::Line> &lines) const;
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems) const;
void drawSectorLights(QPainter *painter, const QList<SectorLight> &lights) const;
static bool polyCb(MapData *data, void *context);
static bool pointCb(MapData *data, void *context);
bool showLabel(const QImage *img, int type) const;
Projection _proj;
Transform _transform;
const Style *_style;
const MapData *_map;
AtlasData *_atlas;
QList<Data *> _data;
int _zoom;
Range _zoomRange;
QRect _rect;

View File

@ -27,7 +27,6 @@ static QFont pixelSizeFont(int pixelSize)
void Style::polygonStyle()
{
_polygons[TYPE(M_COVR)] = Polygon(QBrush(QColor(0xff, 0xff, 0xff)));
_polygons[TYPE(LNDARE)] = Polygon(QBrush(QColor(0xe8, 0xe0, 0x64)));
_polygons[TYPE(BUAARE)] = Polygon(QBrush(QColor(0xd9, 0x8b, 0x21)));
_polygons[TYPE(BUISGL)] = Polygon(QBrush(QColor(0xd9, 0x8b, 0x21)),
@ -153,19 +152,19 @@ void Style::polygonStyle()
1, Qt::DashDotLine));
_drawOrder
<< TYPE(M_COVR) << TYPE(LNDARE) << SUBTYPE(DEPARE, 0)
<< SUBTYPE(DEPARE, 1) << SUBTYPE(DEPARE, 2) << SUBTYPE(DEPARE, 3)
<< TYPE(UNSARE) << SUBTYPE(DEPARE, 4) << SUBTYPE(DEPARE, 5)
<< SUBTYPE(DEPARE, 6) << TYPE(LAKARE) << TYPE(CANALS) << TYPE(DYKCON)
<< TYPE(RIVERS) << TYPE(DRGARE) << TYPE(FAIRWY) << TYPE(LOKBSN)
<< TYPE(I_LOKBSN) << TYPE(BUAARE) << TYPE(BUISGL) << TYPE(SILTNK)
<< TYPE(AIRARE) << TYPE(BRIDGE) << TYPE(I_BRIDGE) << TYPE(TUNNEL)
<< TYPE(I_TERMNL) << TYPE(SLCONS) << TYPE(I_SLCONS) << TYPE(PONTON)
<< TYPE(I_PONTON) << TYPE(HULKES) << TYPE(I_HULKES) << TYPE(FLODOC)
<< TYPE(I_FLODOC) << TYPE(DRYDOC) << TYPE(DAMCON) << TYPE(PYLONS)
<< TYPE(MORFAC) << TYPE(GATCON) << TYPE(I_GATCON) << TYPE(BERTHS)
<< TYPE(I_BERTHS) << SUBTYPE(I_BERTHS, 6) << TYPE(DMPGRD) << TYPE(TSEZNE)
<< TYPE(OBSTRN) << TYPE(UWTROC) << TYPE(DWRTPT) << SUBTYPE(ACHARE, 1)
<< TYPE(LNDARE) << SUBTYPE(DEPARE, 0) << SUBTYPE(DEPARE, 1)
<< SUBTYPE(DEPARE, 2) << SUBTYPE(DEPARE, 3) << TYPE(UNSARE)
<< SUBTYPE(DEPARE, 4) << SUBTYPE(DEPARE, 5) << SUBTYPE(DEPARE, 6)
<< TYPE(LAKARE) << TYPE(CANALS) << TYPE(DYKCON) << TYPE(RIVERS)
<< TYPE(DRGARE) << TYPE(FAIRWY) << TYPE(LOKBSN) << TYPE(I_LOKBSN)
<< TYPE(BUAARE) << TYPE(BUISGL) << TYPE(SILTNK) << TYPE(AIRARE)
<< TYPE(BRIDGE) << TYPE(I_BRIDGE) << TYPE(TUNNEL) << TYPE(I_TERMNL)
<< TYPE(SLCONS) << TYPE(I_SLCONS) << TYPE(PONTON) << TYPE(I_PONTON)
<< TYPE(HULKES) << TYPE(I_HULKES) << TYPE(FLODOC) << TYPE(I_FLODOC)
<< TYPE(DRYDOC) << TYPE(DAMCON) << TYPE(PYLONS) << TYPE(MORFAC)
<< TYPE(GATCON) << TYPE(I_GATCON) << TYPE(BERTHS) << TYPE(I_BERTHS)
<< SUBTYPE(I_BERTHS, 6) << TYPE(DMPGRD) << TYPE(TSEZNE) << TYPE(OBSTRN)
<< TYPE(UWTROC) << TYPE(DWRTPT) << SUBTYPE(ACHARE, 1)
<< SUBTYPE(ACHARE, 2) << SUBTYPE(ACHARE, 3) << SUBTYPE(ACHARE, 4)
<< SUBTYPE(ACHARE, 5) << SUBTYPE(ACHARE, 6) << SUBTYPE(ACHARE, 7)
<< SUBTYPE(ACHARE, 8) << SUBTYPE(ACHARE, 9) << SUBTYPE(I_ACHARE, 1)

View File

@ -154,7 +154,7 @@ ENCAtlas::ENCAtlas(const QString &fileName, QObject *parent)
_zoom = zooms(_usage).min();
updateTransform();
_cache.setMaxCost(10);
_cache.setMaxCost(16);
_valid = true;
}
@ -345,9 +345,21 @@ QString ENCAtlas::key(int zoom, const QPoint &xy) const
+ QString::number(xy.x()) + "_" + QString::number(xy.y());
}
QList<Data*> ENCAtlas::levels() const
{
QList<Data*> list;
QMap<IntendedUsage, ENC::AtlasData*>::const_iterator it = _data.find(_usage);
list.append(it.value());
if (it != _data.cbegin())
list.prepend((--it).value());
return list;
}
void ENCAtlas::draw(QPainter *painter, const QRectF &rect, Flags flags)
{
AtlasData *data = _data.value(_usage);
QList<Data*> data(levels());
Range zr(zooms(_usage));
QPointF tl(floor(rect.left() / TILE_SIZE) * TILE_SIZE,
floor(rect.top() / TILE_SIZE) * TILE_SIZE);

View File

@ -74,6 +74,7 @@ private:
void cancelJobs(bool wait);
QString key(int zoom, const QPoint &xy) const;
void addMap(const QDir &dir, const QByteArray &file, const RectC &bounds);
QList<ENC::Data*> levels() const;
static bool processRecord(const ENC::ISO8211::Record &record,
QByteArray &file, RectC &bounds);

View File

@ -338,7 +338,7 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
if (QPixmapCache::find(key(_zoom, ttl), &pm))
painter->drawPixmap(ttl, pm);
else
tiles.append(RasterTile(_projection, _transform, _style, _data,
tiles.append(RasterTile(_projection, _transform, _style, _data,
_zoom, _zooms, QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)),
_tileRatio));
}