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
.contains(rx
)) {
276 QString
pattern(QString(tile
).replace(rx
, "_%1_%2."));
279 QByteArray
ba(_tar
->file(tile
));
281 _tile
.path
= pattern
;
282 _tile
.size
= QImageReader(&buffer
).size();
284 _tile
.path
= path
+ "/" + pattern
;
285 _tile
.size
= QImageReader(path
+ "/" + tile
).size();
288 if (_tile
.size
.isValid())
291 qWarning("%s: error reading tile image", qPrintable(tile
));
295 _errorString
= "Invalid/missing tile set";
299 void OziMap::load(const Projection
&in
, const Projection
&out
,
300 qreal deviceRatio
, bool hidpi
)
304 _mapRatio
= hidpi
? deviceRatio
: 1.0;
305 if (!_calibrationPoints
.isEmpty()) {
311 Q_ASSERT(!_tar
->isOpen());
313 qWarning("%s: %s", qPrintable(_tar
->fileName()),
314 qPrintable(_tar
->errorString()));
319 Q_ASSERT(!_ozf
->isOpen());
321 qWarning("%s: %s", qPrintable(_ozf
->fileName()),
322 qPrintable(_ozf
->errorString()));
326 if (!_tile
.isValid() && !_ozf
) {
328 _img
= new Image(_map
.path
);
329 _img
->setDevicePixelRatio(_mapRatio
);
333 void OziMap::unload()
338 if (_tar
&& _tar
->isOpen())
341 if (_ozf
&& _ozf
->isOpen())
345 void OziMap::drawTiled(QPainter
*painter
, const QRectF
&rect
) const
347 QSizeF
ts(_tile
.size
.width() / _mapRatio
, _tile
.size
.height() / _mapRatio
);
348 QPointF
tl(floor(rect
.left() / ts
.width()) * ts
.width(),
349 floor(rect
.top() / ts
.height()) * ts
.height());
351 QSizeF
s(rect
.right() - tl
.x(), rect
.bottom() - tl
.y());
352 for (int i
= 0; i
< ceil(s
.width() / ts
.width()); i
++) {
353 for (int j
= 0; j
< ceil(s
.height() / ts
.height()); j
++) {
354 int x
= round(tl
.x() * _mapRatio
+ i
* _tile
.size
.width());
355 int y
= round(tl
.y() * _mapRatio
+ j
* _tile
.size
.height());
357 QString
tileName(_tile
.path
.arg(QString::number(x
),
358 QString::number(y
)));
362 QString key
= _tar
->fileName() + "/" + tileName
;
363 if (!QPixmapCache::find(key
, &pixmap
)) {
364 QByteArray ba
= _tar
->file(tileName
);
365 pixmap
= QPixmap::fromImage(QImage::fromData(ba
));
366 if (!pixmap
.isNull())
367 QPixmapCache::insert(key
, pixmap
);
370 pixmap
= QPixmap(tileName
);
373 qWarning("%s: error loading tile image", qPrintable(tileName
));
375 pixmap
.setDevicePixelRatio(_mapRatio
);
376 QPointF
tp(tl
.x() + i
* ts
.width(), tl
.y() + j
* ts
.height());
377 painter
->drawPixmap(tp
, pixmap
);
383 void OziMap::drawOZF(QPainter
*painter
, const QRectF
&rect
) const
385 QSizeF
ts(_ozf
->tileSize().width() / _mapRatio
, _ozf
->tileSize().height()
387 QPointF
tl(floor(rect
.left() / ts
.width()) * ts
.width(),
388 floor(rect
.top() / ts
.height()) * ts
.height());
390 QSizeF
s(rect
.right() - tl
.x(), rect
.bottom() - tl
.y());
391 for (int i
= 0; i
< ceil(s
.width() / ts
.width()); i
++) {
392 for (int j
= 0; j
< ceil(s
.height() / ts
.height()); j
++) {
393 int x
= round(tl
.x() * _mapRatio
+ i
* _ozf
->tileSize().width());
394 int y
= round(tl
.y() * _mapRatio
+ j
* _ozf
->tileSize().height());
397 QString
key(_ozf
->fileName() + "/" + QString::number(_zoom
) + "_"
398 + QString::number(x
) + "_" + QString::number(y
));
400 if (!QPixmapCache::find(key
, &pixmap
)) {
401 pixmap
= _ozf
->tile(_zoom
, x
, y
);
402 if (!pixmap
.isNull())
403 QPixmapCache::insert(key
, pixmap
);
407 qWarning("%s: error loading tile image", qPrintable(key
));
409 pixmap
.setDevicePixelRatio(_mapRatio
);
410 QPointF
tp(tl
.x() + i
* ts
.width(), tl
.y() + j
* ts
.height());
411 painter
->drawPixmap(tp
, pixmap
);
417 void OziMap::draw(QPainter
*painter
, const QRectF
&rect
, Flags flags
)
422 drawOZF(painter
, rect
);
424 _img
->draw(painter
, rect
, flags
);
425 else if (_tile
.isValid())
426 drawTiled(painter
, rect
);
429 QPointF
OziMap::ll2xy(const Coordinates
&c
)
431 QPointF
p(_transform
.proj2img(_projection
.ll2xy(c
)));
433 ? QPointF(p
.x() * _scale
.x(), p
.y() * _scale
.y()) / _mapRatio
437 Coordinates
OziMap::xy2ll(const QPointF
&p
)
440 ? _projection
.xy2ll(_transform
.img2proj(QPointF(p
.x() / _scale
.x(),
441 p
.y() / _scale
.y()) * _mapRatio
))
442 : _projection
.xy2ll(_transform
.img2proj(p
* _mapRatio
));
445 QRectF
OziMap::bounds()
448 ? QRectF(QPointF(0, 0), _ozf
->size(_zoom
) / _mapRatio
)
449 : QRectF(QPointF(0, 0), _map
.size
/ _mapRatio
);
452 int OziMap::zoomFit(const QSize
&size
, const RectC
&rect
)
460 RectD
prect(rect
, _projection
);
461 QRectF
sbr(_transform
.proj2img(prect
.topLeft()),
462 _transform
.proj2img(prect
.bottomRight()));
464 for (int i
= 0; i
< _ozf
->zooms(); i
++) {
466 if (sbr
.size().width() * _scale
.x() <= size
.width()
467 && sbr
.size().height() * _scale
.y() <= size
.height())
478 rescale(qMax(_zoom
- 1, 0));
483 int OziMap::zoomOut()
486 rescale(qMin(_zoom
+ 1, _ozf
->zooms() - 1));
491 void OziMap::rescale(int zoom
)
494 _scale
= _ozf
->scale(zoom
);
497 void OziMap::computeTransform()
499 QList
<ReferencePoint
> rp
;
501 for (int i
= 0; i
< _calibrationPoints
.size(); i
++)
502 rp
.append(_calibrationPoints
.at(i
).rp(_projection
));
504 _transform
= Transform(rp
);
507 Map
*OziMap::createTAR(const QString
&path
, const Projection
&proj
, bool *isDir
)
512 return new OziMap(path
, Unknown
, proj
);
515 Map
*OziMap::createMAP(const QString
&path
, const Projection
&proj
, bool *isDir
)
520 return new OziMap(path
, MAP
, proj
);
523 Map
*OziMap::createGMI(const QString
&path
, const Projection
&proj
, bool *isDir
)
528 return new OziMap(path
, GMI
, proj
);