6 #include <QImageReader>
7 #include <QPixmapCache>
8 #include <QRegularExpression>
9 #include "common/coordinates.h"
10 #include "common/rectc.h"
20 static QString
tarFile(const QString
&path
)
23 QFileInfoList files
= dir
.entryInfoList(QDir::Files
);
25 for (int i
= 0; i
< files
.size(); i
++) {
26 const QFileInfo
&fi
= files
.at(i
);
28 if (fi
.suffix().toLower() == "tar")
29 return fi
.absoluteFilePath();
35 QString
OziMap::calibrationFile(const QStringList
&files
, const QString path
,
36 CalibrationType
&type
)
38 for (int i
= 0; i
< files
.size(); i
++) {
39 QFileInfo
fi(files
.at(i
));
40 QString
suffix(fi
.suffix().toLower());
42 if (path
.endsWith(fi
.path())) {
43 if (suffix
== "map") {
46 } else if (suffix
== "gmi") {
57 OziMap::OziMap(const QString
&fileName
, CalibrationType type
,
58 const Projection
&proj
, QObject
*parent
) : Map(fileName
, parent
), _img(0),
59 _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0), _valid(false)
62 if (type
== Unknown
) {
63 _tar
= new Tar(fileName
);
65 _errorString
= _tar
->errorString();
68 QStringList
files(_tar
->files());
69 QString
cf(calibrationFile(files
, ".", type
));
72 QByteArray
ba(_tar
->file(cf
));
76 _errorString
= gmi
.errorString();
79 _name
= Util::file2name(fileName
);
80 _map
.size
= gmi
.size();
81 _map
.path
= gmi
.image();
82 _calibrationPoints
= gmi
.calibrationPoints();
86 } else if (type
== MAP
) {
87 QByteArray
ba(_tar
->file(cf
));
91 _errorString
= mf
.errorString();
95 _map
.size
= mf
.size();
96 _map
.path
= mf
.image();
97 _projection
= mf
.projection();
98 _transform
= mf
.transform();
101 _errorString
= "No calibration file found";
105 if (!setTileInfo(files
))
110 // regular MAP or GMI maps
112 QFile
file(fileName
);
117 _errorString
= mf
.errorString();
121 _map
.size
= mf
.size();
122 _map
.path
= mf
.image();
123 _projection
= mf
.projection();
124 _transform
= mf
.transform();
126 } else if (type
== GMI
) {
128 if (!gmi
.isValid()) {
129 _errorString
= gmi
.errorString();
132 _name
= Util::file2name(fileName
);
133 _map
.size
= gmi
.size();
134 _map
.path
= gmi
.image();
135 _calibrationPoints
= gmi
.calibrationPoints();
141 QFileInfo
fi(fileName
);
142 QDir
set(fi
.absolutePath() + "/" + "set");
144 if (!setTileInfo(set
.entryList(), set
.absolutePath()))
147 if (!setImageInfo(fi
.absolutePath()))
155 OziMap::OziMap(const QString
&dirName
, Tar
&tar
, const Projection
&proj
,
156 QObject
*parent
) : Map(dirName
, parent
), _img(0), _tar(0), _ozf(0), _zoom(0),
157 _mapRatio(1.0), _valid(false)
159 CalibrationType type
;
160 QString
cf(calibrationFile(tar
.files(), dirName
, type
));
163 QByteArray ba
= tar
.file(cf
);
167 _errorString
= mf
.errorString();
172 _map
.size
= mf
.size();
173 _projection
= mf
.projection();
174 _transform
= mf
.transform();
175 } else if (type
== GMI
) {
176 QByteArray ba
= tar
.file(cf
);
179 if (!gmi
.isValid()) {
180 _errorString
= gmi
.errorString();
184 _name
= Util::file2name(cf
);
185 _map
.size
= gmi
.size();
186 _calibrationPoints
= gmi
.calibrationPoints();
190 _errorString
= "No calibration file found";
194 QString
tf(tarFile(dirName
));
196 _errorString
= "No map tar file found";
201 _errorString
= _tar
->fileName() + ": " + _tar
->errorString();
204 if (!setTileInfo(_tar
->files())) {
205 _errorString
= _tar
->fileName() + ": " + _errorString
;
220 bool OziMap::setImageInfo(const QString
&path
)
222 QFileInfo
ii(_map
.path
);
225 ii
.setFile(path
+ "/" + _map
.path
);
228 int last
= _map
.path
.lastIndexOf('\\');
229 if (last
>= 0 && last
< _map
.path
.length() - 1) {
230 QString
fn(_map
.path
.mid(last
+ 1, _map
.path
.length() - last
- 1));
231 ii
.setFile(path
+ "/" + fn
);
236 _map
.path
= ii
.absoluteFilePath();
238 _errorString
= QString("%1: No such image file").arg(_map
.path
);
242 if (OZF::isOZF(_map
.path
)) {
243 _ozf
= new OZF(_map
.path
);
245 _errorString
= QString("%1: %2").arg(_map
.path
, _ozf
->errorString());
248 _scale
= _ozf
->scale(_zoom
);
251 QImageReader
ir(_map
.path
);
253 _errorString
= QString("%1: Unsupported/invalid image file")
257 _map
.size
= ir
.size();
263 bool OziMap::setTileInfo(const QStringList
&tiles
, const QString
&path
)
265 static const QRegularExpression
rx("_[0-9]+_[0-9]+\\.");
267 if (!_map
.size
.isValid()) {
268 _errorString
= "Missing total image size (IWH)";
272 for (int i
= 0; i
< tiles
.size(); i
++) {
273 const QString
&tile
= tiles
.at(i
);
275 if (tile
.startsWith("set/") && tile
.contains(rx
)) {
276 _tile
.path
= QString(tile
).replace(rx
, "_%1_%2.");
279 QByteArray
ba(_tar
->file(tile
));
281 _tile
.size
= QImageReader(&buffer
).size();
283 _tile
.path
= path
+ "/" + _tile
.path
;
284 _tile
.size
= QImageReader(path
+ "/" + tile
).size();
286 if (!_tile
.size
.isValid()) {
287 _errorString
= QString("Error retrieving tile size: "
288 "%1: Invalid image").arg(QFileInfo(tile
).fileName());
292 _map
.path
= QString();
297 _errorString
= "Invalid/missing tile set";
301 void OziMap::load(const Projection
&in
, const Projection
&out
,
302 qreal deviceRatio
, bool hidpi
)
306 _mapRatio
= hidpi
? deviceRatio
: 1.0;
307 if (!_calibrationPoints
.isEmpty()) {
313 Q_ASSERT(!_tar
->isOpen());
315 qWarning("%s: %s", qPrintable(_tar
->fileName()),
316 qPrintable(_tar
->errorString()));
321 Q_ASSERT(!_ozf
->isOpen());
323 qWarning("%s: %s", qPrintable(_ozf
->fileName()),
324 qPrintable(_ozf
->errorString()));
328 if (!_tile
.isValid() && !_ozf
) {
330 _img
= new Image(_map
.path
);
331 _img
->setDevicePixelRatio(_mapRatio
);
335 void OziMap::unload()
340 if (_tar
&& _tar
->isOpen())
343 if (_ozf
&& _ozf
->isOpen())
347 void OziMap::drawTiled(QPainter
*painter
, const QRectF
&rect
) const
349 QSizeF
ts(_tile
.size
.width() / _mapRatio
, _tile
.size
.height() / _mapRatio
);
350 QPointF
tl(floor(rect
.left() / ts
.width()) * ts
.width(),
351 floor(rect
.top() / ts
.height()) * ts
.height());
353 QSizeF
s(rect
.right() - tl
.x(), rect
.bottom() - tl
.y());
354 for (int i
= 0; i
< ceil(s
.width() / ts
.width()); i
++) {
355 for (int j
= 0; j
< ceil(s
.height() / ts
.height()); j
++) {
356 int x
= round(tl
.x() * _mapRatio
+ i
* _tile
.size
.width());
357 int y
= round(tl
.y() * _mapRatio
+ j
* _tile
.size
.height());
359 QString
tileName(_tile
.path
.arg(QString::number(x
),
360 QString::number(y
)));
364 QString key
= _tar
->fileName() + "/" + tileName
;
365 if (!QPixmapCache::find(key
, &pixmap
)) {
366 QByteArray ba
= _tar
->file(tileName
);
367 pixmap
= QPixmap::fromImage(QImage::fromData(ba
));
368 if (!pixmap
.isNull())
369 QPixmapCache::insert(key
, pixmap
);
372 pixmap
= QPixmap(tileName
);
375 qWarning("%s: error loading tile image", qPrintable(tileName
));
377 pixmap
.setDevicePixelRatio(_mapRatio
);
378 QPointF
tp(tl
.x() + i
* ts
.width(), tl
.y() + j
* ts
.height());
379 painter
->drawPixmap(tp
, pixmap
);
385 void OziMap::drawOZF(QPainter
*painter
, const QRectF
&rect
) const
387 QSizeF
ts(_ozf
->tileSize().width() / _mapRatio
, _ozf
->tileSize().height()
389 QPointF
tl(floor(rect
.left() / ts
.width()) * ts
.width(),
390 floor(rect
.top() / ts
.height()) * ts
.height());
392 QSizeF
s(rect
.right() - tl
.x(), rect
.bottom() - tl
.y());
393 for (int i
= 0; i
< ceil(s
.width() / ts
.width()); i
++) {
394 for (int j
= 0; j
< ceil(s
.height() / ts
.height()); j
++) {
395 int x
= round(tl
.x() * _mapRatio
+ i
* _ozf
->tileSize().width());
396 int y
= round(tl
.y() * _mapRatio
+ j
* _ozf
->tileSize().height());
399 QString
key(_ozf
->fileName() + "/" + QString::number(_zoom
) + "_"
400 + QString::number(x
) + "_" + QString::number(y
));
402 if (!QPixmapCache::find(key
, &pixmap
)) {
403 pixmap
= _ozf
->tile(_zoom
, x
, y
);
404 if (!pixmap
.isNull())
405 QPixmapCache::insert(key
, pixmap
);
409 qWarning("%s: error loading tile image", qPrintable(key
));
411 pixmap
.setDevicePixelRatio(_mapRatio
);
412 QPointF
tp(tl
.x() + i
* ts
.width(), tl
.y() + j
* ts
.height());
413 painter
->drawPixmap(tp
, pixmap
);
419 void OziMap::draw(QPainter
*painter
, const QRectF
&rect
, Flags flags
)
424 drawOZF(painter
, rect
);
426 _img
->draw(painter
, rect
, flags
);
427 else if (_tile
.isValid())
428 drawTiled(painter
, rect
);
431 QPointF
OziMap::ll2xy(const Coordinates
&c
)
433 QPointF
p(_transform
.proj2img(_projection
.ll2xy(c
)));
435 ? QPointF(p
.x() * _scale
.x(), p
.y() * _scale
.y()) / _mapRatio
439 Coordinates
OziMap::xy2ll(const QPointF
&p
)
442 ? _projection
.xy2ll(_transform
.img2proj(QPointF(p
.x() / _scale
.x(),
443 p
.y() / _scale
.y()) * _mapRatio
))
444 : _projection
.xy2ll(_transform
.img2proj(p
* _mapRatio
));
447 QRectF
OziMap::bounds()
450 ? QRectF(QPointF(0, 0), _ozf
->size(_zoom
) / _mapRatio
)
451 : QRectF(QPointF(0, 0), _map
.size
/ _mapRatio
);
454 int OziMap::zoomFit(const QSize
&size
, const RectC
&rect
)
462 RectD
prect(rect
, _projection
);
463 QRectF
sbr(_transform
.proj2img(prect
.topLeft()),
464 _transform
.proj2img(prect
.bottomRight()));
466 for (int i
= 0; i
< _ozf
->zooms(); i
++) {
468 if (sbr
.size().width() * _scale
.x() <= size
.width()
469 && sbr
.size().height() * _scale
.y() <= size
.height())
480 rescale(qMax(_zoom
- 1, 0));
485 int OziMap::zoomOut()
488 rescale(qMin(_zoom
+ 1, _ozf
->zooms() - 1));
493 void OziMap::rescale(int zoom
)
496 _scale
= _ozf
->scale(zoom
);
499 void OziMap::computeTransform()
501 QList
<ReferencePoint
> rp
;
503 for (int i
= 0; i
< _calibrationPoints
.size(); i
++)
504 rp
.append(_calibrationPoints
.at(i
).rp(_projection
));
506 _transform
= Transform(rp
);
509 Map
*OziMap::createTAR(const QString
&path
, const Projection
&proj
, bool *isDir
)
514 return new OziMap(path
, Unknown
, proj
);
517 Map
*OziMap::createMAP(const QString
&path
, const Projection
&proj
, bool *isDir
)
522 return new OziMap(path
, MAP
, proj
);
525 Map
*OziMap::createGMI(const QString
&path
, const Projection
&proj
, bool *isDir
)
530 return new OziMap(path
, GMI
, proj
);