The OSM plugin has a different zoom tolerance than what we're hardcoding here. This fixes the map looking funky from being too zoomed while trying to fit multiple location points at once.
47 lines
1.4 KiB
C++
47 lines
1.4 KiB
C++
// SPDX-FileCopyrightText: 2023 Volker Krause <vkrause@kde.org>
|
|
// SPDX-License-Identifier: LGPL-2.0-or-later
|
|
|
|
#include "locationhelper.h"
|
|
|
|
#include <cmath>
|
|
|
|
QRectF LocationHelper::unite(const QRectF &r1, const QRectF &r2)
|
|
{
|
|
// this looks weird but is actually intentional as we need to handle point-like "rects" as well
|
|
if ((!r1.isEmpty() || r1.isNull()) && (!r2.isEmpty() || r2.isNull())) {
|
|
return r1 | r2;
|
|
}
|
|
return (!r1.isEmpty() || r1.isNull()) ? r1 : r2;
|
|
}
|
|
|
|
QPointF LocationHelper::center(const QRectF &r)
|
|
{
|
|
return r.center();
|
|
}
|
|
|
|
constexpr inline double degToRad(double deg)
|
|
{
|
|
return deg / 180.0 * M_PI;
|
|
}
|
|
|
|
static QPointF mercatorProject(double lat, double lon, double zoom)
|
|
{
|
|
const auto x = (256.0 / (2.0 * M_PI)) * std::pow(2.0, zoom) * (degToRad(lon) + M_PI);
|
|
const auto y = (256.0 / (2.0 * M_PI)) * std::pow(2.0, zoom) * (M_PI - std::log(std::tan(M_PI / 4.0 + degToRad(lat) / 2.0)));
|
|
return QPointF(x, y);
|
|
}
|
|
|
|
float LocationHelper::zoomToFit(const QRectF &r, float mapWidth, float mapHeight)
|
|
{
|
|
const auto p1 = mercatorProject(r.bottomLeft().y(), r.bottomLeft().x(), 1.0);
|
|
const auto p2 = mercatorProject(r.topRight().y(), r.topRight().x(), 1.0);
|
|
|
|
const auto zx = std::log2((mapWidth / (p2.x() - p1.x())));
|
|
const auto zy = std::log2((mapHeight / (p2.y() - p1.y())));
|
|
const auto z = std::min(zx, zy);
|
|
|
|
return z;
|
|
}
|
|
|
|
#include "moc_locationhelper.cpp"
|