2 #include <QPixmapCache>
3 #include "common/range.h"
4 #include "common/wgs84.h"
10 #define TEXT_EXTENT 160
15 ENCMap::ENCMap(const QString
&fileName
, QObject
*parent
)
16 : Map(fileName
, parent
), _data(fileName
), _projection(PCS::pcs(3857)),
17 _tileRatio(1.0), _zoom(0)
19 if (_data
.isValid()) {
20 _llBounds
= _data
.bounds();
25 void ENCMap::load(const Projection
&in
, const Projection
&out
,
26 qreal deviceRatio
, bool hidpi
)
31 _tileRatio
= deviceRatio
;
34 QPixmapCache::clear();
43 int ENCMap::zoomFit(const QSize
&size
, const RectC
&rect
)
46 RectD
pr(rect
, _projection
, 10);
48 _zoom
= _data
.zooms().min();
49 for (int i
= _data
.zooms().min() + 1; i
<= _data
.zooms().max(); i
++) {
50 Transform
t(transform(i
));
51 QRectF
r(t
.proj2img(pr
.topLeft()), t
.proj2img(pr
.bottomRight()));
52 if (size
.width() < r
.width() || size
.height() < r
.height())
57 _zoom
= _data
.zooms().max();
68 _zoom
= qMin(_zoom
+ 1, _data
.zooms().max());
77 _zoom
= qMax(_zoom
- 1, _data
.zooms().min());
82 void ENCMap::setZoom(int zoom
)
88 Transform
ENCMap::transform(int zoom
) const
90 int z
= zoom
+ Util::log2i(TILE_SIZE
);
92 double scale
= _projection
.isGeographic()
93 ? 360.0 / (1<<z
) : (2.0 * M_PI
* WGS84_RADIUS
) / (1<<z
);
94 PointD
topLeft(_projection
.ll2xy(_llBounds
.topLeft()));
95 return Transform(ReferencePoint(PointD(0, 0), topLeft
),
96 PointD(scale
, scale
));
99 void ENCMap::updateTransform()
101 _transform
= transform(_zoom
);
103 RectD
prect(_llBounds
, _projection
);
104 _bounds
= QRectF(_transform
.proj2img(prect
.topLeft()),
105 _transform
.proj2img(prect
.bottomRight()));
108 bool ENCMap::isRunning(int zoom
, const QPoint
&xy
) const
110 for (int i
= 0; i
< _jobs
.size(); i
++) {
111 const QList
<ENC::RasterTile
> &tiles
= _jobs
.at(i
)->tiles();
112 for (int j
= 0; j
< tiles
.size(); j
++) {
113 const ENC::RasterTile
&mt
= tiles
.at(j
);
114 if (mt
.zoom() == zoom
&& mt
.xy() == xy
)
122 void ENCMap::runJob(ENCMapJob
*job
)
126 connect(job
, &ENCMapJob::finished
, this, &ENCMap::jobFinished
);
130 void ENCMap::removeJob(ENCMapJob
*job
)
132 _jobs
.removeOne(job
);
136 void ENCMap::jobFinished(ENCMapJob
*job
)
138 const QList
<ENC::RasterTile
> &tiles
= job
->tiles();
140 for (int i
= 0; i
< tiles
.size(); i
++) {
141 const ENC::RasterTile
&mt
= tiles
.at(i
);
143 QPixmapCache::insert(key(mt
.zoom(), mt
.xy()), mt
.pixmap());
151 void ENCMap::cancelJobs(bool wait
)
153 for (int i
= 0; i
< _jobs
.size(); i
++)
154 _jobs
.at(i
)->cancel(wait
);
157 QString
ENCMap::key(int zoom
, const QPoint
&xy
) const
159 return path() + "-" + QString::number(zoom
) + "_"
160 + QString::number(xy
.x()) + "_" + QString::number(xy
.y());
163 void ENCMap::draw(QPainter
*painter
, const QRectF
&rect
, Flags flags
)
166 QPointF
tl(floor(rect
.left() / TILE_SIZE
) * TILE_SIZE
,
167 floor(rect
.top() / TILE_SIZE
) * TILE_SIZE
);
168 QSizeF
s(rect
.right() - tl
.x(), rect
.bottom() - tl
.y());
169 int width
= ceil(s
.width() / TILE_SIZE
);
170 int height
= ceil(s
.height() / TILE_SIZE
);
172 QList
<RasterTile
> tiles
;
174 for (int i
= 0; i
< width
; i
++) {
175 for (int j
= 0; j
< height
; j
++) {
176 QPoint
ttl(tl
.x() + i
* TILE_SIZE
, tl
.y() + j
* TILE_SIZE
);
177 if (isRunning(_zoom
, ttl
))
181 if (QPixmapCache::find(key(_zoom
, ttl
), &pm
))
182 painter
->drawPixmap(ttl
, pm
);
184 QList
<MapData::Poly
*> polygons
;
185 QList
<MapData::Line
*> lines
;
186 QList
<MapData::Point
*> points
;
188 QRectF
polyRect(ttl
, QPointF(ttl
.x() + TILE_SIZE
,
189 ttl
.y() + TILE_SIZE
));
191 RectD
polyRectD(_transform
.img2proj(polyRect
.topLeft()),
192 _transform
.img2proj(polyRect
.bottomRight()));
193 RectC
polyRectC(polyRectD
.toRectC(_projection
, 20));
194 _data
.lines(polyRectC
, &lines
);
195 _data
.polygons(polyRectC
, &polygons
);
197 QRectF
pointRect(QPointF(ttl
.x() - TEXT_EXTENT
,
198 ttl
.y() - TEXT_EXTENT
), QPointF(ttl
.x() + TILE_SIZE
199 + TEXT_EXTENT
, ttl
.y() + TILE_SIZE
+ TEXT_EXTENT
));
200 pointRect
&= _bounds
;
201 RectD
pointRectD(_transform
.img2proj(pointRect
.topLeft()),
202 _transform
.img2proj(pointRect
.bottomRight()));
203 _data
.points(pointRectD
.toRectC(_projection
, 20), &points
);
205 tiles
.append(RasterTile(_projection
, _transform
, _data
.zooms(),
206 _zoom
, QRect(ttl
, QSize(TILE_SIZE
, TILE_SIZE
)), _tileRatio
,
207 lines
, polygons
, points
));
212 if (!tiles
.isEmpty()) {
213 if (flags
& Map::Block
) {
214 QFuture
<void> future
= QtConcurrent::map(tiles
, &RasterTile::render
);
215 future
.waitForFinished();
217 for (int i
= 0; i
< tiles
.size(); i
++) {
218 const RasterTile
&mt
= tiles
.at(i
);
219 const QPixmap
&pm
= mt
.pixmap();
220 painter
->drawPixmap(mt
.xy(), pm
);
221 QPixmapCache::insert(key(mt
.zoom(), mt
.xy()), pm
);
224 runJob(new ENCMapJob(tiles
));
228 Map
*ENCMap::create(const QString
&path
, bool *isMap
)
233 return new ENCMap(path
);