9#include <osm/geomath.h>
15static constexpr const double SceneWorldSize = 256.0;
16static constexpr const double LatitudeLimit = 85.05112879806592;
17static constexpr const auto MaxZoomFactor = 21;
25View::~View() =
default;
29 const auto lat = qBound(-LatitudeLimit, coord.latF(), LatitudeLimit);
31 (coord.lonF() + 180.0) / 360.0 * SceneWorldSize,
32 SceneWorldSize / (2.0 * M_PI) * (M_PI - std::log(std::tan((M_PI / 4.0) + ((
OSM::degToRad(lat) / 2.0)))))
38 const auto p1 = mapGeoToScene(box.min);
39 const auto p2 = mapGeoToScene(box.max);
46 OSM::radToDeg(std::atan(std::sinh(M_PI * (1 - 2 * (p.
y() / SceneWorldSize))))),
47 (p.
x() / SceneWorldSize) * 360.0 - 180.0
53 const auto c1 = mapSceneToGeo(box.
bottomLeft());
54 const auto c2 = mapSceneToGeo(box.
topRight());
58int View::screenHeight()
const
60 return m_screenSize.height();
63int View::screenWidth()
const
65 return m_screenSize.width();
68void View::setScreenSize(
QSize size)
70 if (size.
width() <= 0.0 || size.
height() <= 0.0 || size == m_screenSize) {
74 const auto dx = (double)size.
width() / (double)screenWidth();
75 const auto dy = (double)size.
height() / (double)screenHeight();
78 m_viewport.
setWidth(m_viewport.width() * dx);
79 m_viewport.setHeight(m_viewport.height() * dy);
80 constrainViewToScene();
84int View::level()
const
89void View::setLevel(
int level)
91 if (m_level == level) {
96 Q_EMIT floorLevelChanged();
99double View::zoomLevel()
const
101 const auto dx = m_viewport.width() / (screenWidth() / SceneWorldSize) / 360.0;
102 return - std::log2(dx);
105void View::setZoomLevel(
double zoom,
QPointF screenCenter)
107 m_viewport = viewportForZoom(zoom, screenCenter);
116void View::setViewport(
const QRectF &viewport)
118 m_viewport = viewport;
119 constrainViewToScene();
125 auto z = std::pow(2.0, - std::min(zoom, (
double)MaxZoomFactor));
126 const auto dx = ((screenWidth() / SceneWorldSize) * 360.0 * z) - m_viewport.width();
127 const auto dy = ((screenHeight() / SceneWorldSize) * 360.0 * z) - m_viewport.height();
129 const auto centerScene = mapScreenToScene(screenCenter);
130 if (!m_viewport.contains(centerScene)) {
134 const auto xr = (centerScene.x() - m_viewport.x()) / m_viewport.width();
135 const auto yr = (centerScene.y() - m_viewport.y()) / m_viewport.height();
137 QRectF viewport(m_viewport);
138 viewport.
adjust(-xr * dx, -yr * dy, (1-xr) * dx, (1-yr) * dy);
139 return constrainedViewport(viewport);
149 setSceneBoundingBox(mapGeoToScene(bbox));
152void View::setSceneBoundingBox(
const QRectF &bbox)
154 if (m_bbox == bbox) {
161 const auto screenAspectRatio = (double)screenWidth() / (double)screenHeight();
162 m_viewport.
setHeight(m_viewport.width() / screenAspectRatio);
165 if (m_viewport.height() > m_bbox.height()) {
166 const auto dy = (double)m_bbox.height() / (double)m_viewport.height();
167 m_viewport.setHeight(m_viewport.height() * dy);
168 m_viewport.setWidth(m_viewport.width() * dy);
177 return m_sceneToScreenTransform.map(scenePos);
188 return m_screenToSceneTransform.map(screenPos);
191double View::mapScreenDistanceToSceneDistance(
double distance)
const
193 const auto p1 = mapScreenToScene(m_viewport.center());
194 const auto p2 = mapScreenToScene(m_viewport.center() +
QPointF(1.0, 0));
196 return std::abs(p2.x() - p1.x()) * distance;
199void View::panScreenSpace(
QPoint offset)
201 auto dx = offset.
x() * (m_viewport.width() / screenWidth());
202 auto dy = offset.
y() * (m_viewport.height() / screenHeight());
203 m_viewport.adjust(dx, dy, dx, dy);
204 constrainViewToScene();
210 return m_sceneToScreenTransform;
215 setZoomLevel(zoomLevel() + 1, screenCenter);
220 setZoomLevel(zoomLevel() - 1, screenCenter);
223void View::constrainViewToScene()
225 m_viewport = constrainedViewport(m_viewport);
231 const auto s = std::min(viewport.
width() / m_bbox.width(), viewport.
height() / m_bbox.height());
238 if (m_bbox.left() < viewport.
left() && m_bbox.right() < viewport.
right()) {
239 const auto dx = std::min(viewport.
left() - m_bbox.left(), viewport.
right() - m_bbox.right());
240 viewport.
adjust(-dx, 0, -dx, 0);
241 }
else if (m_bbox.right() > viewport.
right() && m_bbox.left() > viewport.
left()) {
242 const auto dx = std::min(m_bbox.right() - viewport.
right(), m_bbox.left() - viewport.
left());
243 viewport.
adjust(dx, 0, dx, 0);
246 if (m_bbox.top() < viewport.
top() && m_bbox.bottom() < viewport.
bottom()) {
247 const auto dy = std::min(viewport.
top() - m_bbox.top(), viewport.
bottom() - m_bbox.bottom());
248 viewport.
adjust(0, -dy, 0, -dy);
249 }
else if (m_bbox.bottom() > viewport.
bottom() && m_bbox.top() > viewport.
top()) {
250 const auto dy = std::min(m_bbox.bottom() - viewport.
bottom(), m_bbox.top() - viewport.
top());
251 viewport.
adjust(0, dy, 0, dy);
257double View::mapMetersToScene(
double meters)
const
259 const auto scale = m_viewport.
width() / m_screenWidthInMeters;
260 return meters * scale;
263double View::mapMetersToScreen(
double meters)
const
265 const auto r = meters / m_screenWidthInMeters;
266 return r * m_screenSize.width();
269double View::mapScreenToMeters(
int pixels)
const
271 const auto r = (double)pixels / (
double)m_screenSize.width();
272 return r * m_screenWidthInMeters;
275double View::panX()
const
277 const auto r = (m_viewport.left() - m_bbox.left()) / m_bbox.width();
278 return panWidth() * r;
281double View::panY()
const
283 const auto r = (m_viewport.top() - m_bbox.top()) / m_bbox.height();
284 return panHeight() * r;
287double View::panWidth()
const
289 const auto r = m_bbox.width() / m_viewport.width();
290 return screenWidth() * r;
293double View::panHeight()
const
295 const auto r = m_bbox.height() / m_viewport.height();
296 return screenHeight() * r;
299void View::panTopLeft(
double x,
double y)
301 m_viewport.moveLeft(m_bbox.x() + m_bbox.width() * (x / panWidth()));
302 m_viewport.moveTop(m_bbox.y() + m_bbox.height() * (y / panHeight()));
303 constrainViewToScene();
309 return m_deviceTransform;
312void View::setDeviceTransform(
const QTransform &t)
314 m_deviceTransform = t;
317void View::centerOnGeoCoordinate(
QPointF geoCoord)
319 const auto sceneCenter = mapGeoToScene(
OSM::Coordinate(geoCoord.
y(), geoCoord.
x()));
320 m_viewport.moveCenter(sceneCenter);
321 constrainViewToScene();
325void View::updateViewport()
329 m_screenWidthInMeters =
OSM::distance(mapSceneToGeo(
QPointF(m_viewport.left(), m_viewport.center().y())), mapSceneToGeo(
QPointF(m_viewport.right(), m_viewport.center().y())));
330 if (m_screenWidthInMeters == 0.0) {
331 m_screenWidthInMeters = 1.0;
334 m_sceneToScreenTransform = {};
335 m_sceneToScreenTransform.scale(screenWidth() / (m_viewport.width()), screenHeight() / (m_viewport.height()));
336 m_sceneToScreenTransform.translate(-m_viewport.x(), -m_viewport.y());
338 m_screenToSceneTransform = m_sceneToScreenTransform.inverted();
340 Q_EMIT transformationChanged();
348void View::setBeginTime(
const QDateTime &beginTime)
350 const auto alignedTime =
QDateTime(beginTime.
date(), {beginTime.time().hour(), beginTime.time().minute()});
351 if (m_beginTime == alignedTime) {
354 m_beginTime = alignedTime;
363void View::setEndTime(
const QDateTime& endTime)
365 const auto alignedTime =
QDateTime(endTime.
date(), {endTime.time().hour(), endTime.time().minute()});
366 if (m_endTime == alignedTime) {
369 m_endTime = alignedTime;
375 const auto c = mapSceneToGeo(p);
376 return {c.lonF(), c.latF()};
379#include "moc_view.cpp"
Coordinate, stored as 1e7 * degree to avoid floating point precision issues, and offset to unsigned v...
OSM-based multi-floor indoor maps for buildings.
KOSM_EXPORT double distance(double lat1, double lon1, double lat2, double lon2)
Distance between two coordinates.
constexpr double radToDeg(double rad)
Radian to degree conversion.
constexpr double degToRad(double deg)
Degree to radian conversion.
QDateTime currentDateTime()
void adjust(qreal dx1, qreal dy1, qreal dx2, qreal dy2)
qreal bottom() const const
QPointF bottomLeft() const const
QPointF bottomRight() const const
qreal height() const const
qreal right() const const
void setHeight(qreal height)
void setWidth(qreal width)
QPointF topLeft() const const
QPointF topRight() const const
qreal width() const const