File indexing completed on 2024-10-06 12:54:05

0001 // SPDX-FileCopyrightText: 2023 Volker Krause <vkrause@kde.org>
0002 // SPDX-License-Identifier: LGPL-2.0-or-later
0003 
0004 #include "locationhelper.h"
0005 
0006 #include <cmath>
0007 
0008 QRectF LocationHelper::unite(const QRectF &r1, const QRectF &r2)
0009 {
0010     // this looks weird but is actually intentional as we need to handle point-like "rects" as well
0011     if ((!r1.isEmpty() || r1.isNull()) && (!r2.isEmpty() || r2.isNull())) {
0012         return r1 | r2;
0013     }
0014     return (!r1.isEmpty() || r1.isNull()) ? r1 : r2;
0015 }
0016 
0017 QPointF LocationHelper::center(const QRectF &r)
0018 {
0019     return r.center();
0020 }
0021 
0022 constexpr inline double degToRad(double deg)
0023 {
0024     return deg / 180.0 * M_PI;
0025 }
0026 
0027 static QPointF mercatorProject(double lat, double lon, double zoom)
0028 {
0029     const auto x = (256.0 / (2.0 * M_PI)) * std::pow(2.0, zoom) * (degToRad(lon) + M_PI);
0030     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)));
0031     return QPointF(x, y);
0032 }
0033 
0034 float LocationHelper::zoomToFit(const QRectF &r, float mapWidth, float mapHeight)
0035 {
0036     const auto p1 = mercatorProject(r.bottomLeft().y(), r.bottomLeft().x(), 1.0);
0037     const auto p2 = mercatorProject(r.topRight().y(), r.topRight().x(), 1.0);
0038 
0039     const auto zx = std::log2((mapWidth / (p2.x() - p1.x())));
0040     const auto zy = std::log2((mapHeight / (p2.y() - p1.y())));
0041     const auto z = std::min(zx, zy);
0042 
0043     return std::clamp(z, 5.0, 18.0);
0044 }
0045 
0046 #include "moc_locationhelper.cpp"