12#include <QPainterPath>
15#include "AzimuthalEquidistantProjection.h"
17#include "GeoDataLatLonAltBox.h"
18#include "GnomonicProjection.h"
19#include "LambertAzimuthalProjection.h"
20#include "MarbleDebug.h"
23#include "StereographicProjection.h"
24#include "VerticalPerspectiveProjection.h"
29class ViewportParamsPrivate
32 ViewportParamsPrivate(Projection projection, qreal centerLongitude, qreal centerLatitude,
int radius,
const QSize &size);
34 static const AbstractProjection *abstractProjection(Projection projection);
38 Projection m_projection;
39 const AbstractProjection *m_currentProjection;
42 qreal m_centerLongitude;
43 qreal m_centerLatitude;
45 Quaternion m_planetAxis;
46 matrix m_planetAxisMatrix;
48 qreal m_angularResolution;
53 GeoDataLatLonAltBox m_viewLatLonAltBox;
55 static const SphericalProjection s_sphericalProjection;
56 static const EquirectProjection s_equirectProjection;
57 static const MercatorProjection s_mercatorProjection;
58 static const GnomonicProjection s_gnomonicProjection;
59 static const StereographicProjection s_stereographicProjection;
60 static const LambertAzimuthalProjection s_lambertAzimuthalProjection;
61 static const AzimuthalEquidistantProjection s_azimuthalEquidistantProjection;
62 static const VerticalPerspectiveProjection s_verticalPerspectiveProjection;
64 GeoDataCoordinates m_focusPoint;
67const SphericalProjection ViewportParamsPrivate::s_sphericalProjection;
68const EquirectProjection ViewportParamsPrivate::s_equirectProjection;
69const MercatorProjection ViewportParamsPrivate::s_mercatorProjection;
70const GnomonicProjection ViewportParamsPrivate::s_gnomonicProjection;
71const StereographicProjection ViewportParamsPrivate::s_stereographicProjection;
72const LambertAzimuthalProjection ViewportParamsPrivate::s_lambertAzimuthalProjection;
73const AzimuthalEquidistantProjection ViewportParamsPrivate::s_azimuthalEquidistantProjection;
74const VerticalPerspectiveProjection ViewportParamsPrivate::s_verticalPerspectiveProjection;
76ViewportParamsPrivate::ViewportParamsPrivate(Projection projection, qreal centerLongitude, qreal centerLatitude,
int radius,
const QSize &size)
77 : m_projection(projection)
78 , m_currentProjection(abstractProjection(projection))
79 , m_centerLongitude(centerLongitude)
80 , m_centerLatitude(centerLatitude)
83 , m_planetAxisMatrix()
85 , m_angularResolution(4.0 / abs(m_radius))
88 , m_viewLatLonAltBox()
92const AbstractProjection *ViewportParamsPrivate::abstractProjection(Projection projection)
96 return &s_sphericalProjection;
98 return &s_equirectProjection;
100 return &s_mercatorProjection;
102 return &s_gnomonicProjection;
104 return &s_stereographicProjection;
106 return &s_lambertAzimuthalProjection;
108 return &s_azimuthalEquidistantProjection;
110 return &s_verticalPerspectiveProjection;
116ViewportParams::ViewportParams()
117 : d(new ViewportParamsPrivate(
Spherical, 0, 0, 2000,
QSize(100, 100)))
119 centerOn(d->m_centerLongitude, d->m_centerLatitude);
122ViewportParams::ViewportParams(Projection projection, qreal centerLongitude, qreal centerLatitude,
int radius,
const QSize &size)
123 : d(new ViewportParamsPrivate(projection, centerLongitude, centerLatitude, radius, size))
125 centerOn(d->m_centerLongitude, d->m_centerLatitude);
128ViewportParams::~ViewportParams()
136Projection ViewportParams::projection()
const
138 return d->m_projection;
141const AbstractProjection *ViewportParams::currentProjection()
const
143 return d->m_currentProjection;
146void ViewportParams::setProjection(Projection newProjection)
148 d->m_projection = newProjection;
149 d->m_currentProjection = ViewportParamsPrivate::abstractProjection(newProjection);
154 centerOn(d->m_centerLongitude, d->m_centerLatitude);
157int ViewportParams::polarity()
const
161 GeoDataCoordinates northPole(0.0, +currentProjection()->maxLat());
162 GeoDataCoordinates southPole(0.0, -currentProjection()->maxLat());
164 bool globeHidesN, globeHidesS;
168 currentProjection()->screenCoordinates(northPole,
this, x, yN, globeHidesN);
169 currentProjection()->screenCoordinates(southPole,
this, x, yS, globeHidesS);
174 if (!globeHidesN && !globeHidesS) {
182 if (!globeHidesN && yN < height() / 2) {
185 if (!globeHidesN && yN > height() / 2) {
188 if (!globeHidesS && yS > height() / 2) {
191 if (!globeHidesS && yS < height() / 2) {
199int ViewportParams::radius()
const
204void ViewportParams::setRadius(
int newRadius)
207 d->m_dirtyBox =
true;
209 d->m_radius = newRadius;
210 d->m_angularResolution = 4.0 / d->m_radius;
214void ViewportParams::centerOn(qreal lon, qreal lat)
216 if (!d->m_currentProjection->traversablePoles()) {
217 if (lat > d->m_currentProjection->maxLat())
218 lat = d->m_currentProjection->maxLat();
220 if (lat < d->m_currentProjection->minLat())
221 lat = d->m_currentProjection->minLat();
234 d->m_centerLongitude = lon;
235 d->m_centerLatitude = lat;
237 const Quaternion
roll = Quaternion::fromEuler(0, 0, d->m_heading);
238 const Quaternion quat = Quaternion::fromEuler(-lat, lon, 0.0);
240 d->m_planetAxis = quat *
roll;
241 d->m_planetAxis.normalize();
243 d->m_dirtyBox =
true;
244 d->m_planetAxis.inverse().toMatrix(d->m_planetAxisMatrix);
245 d->m_planetAxis.normalize();
248void ViewportParams::setHeading(qreal heading)
250 d->m_heading = heading;
252 const Quaternion
roll = Quaternion::fromEuler(0, 0, heading);
254 const qreal centerLat = centerLatitude();
255 const qreal centerLon = centerLongitude();
257 const Quaternion quat = Quaternion::fromEuler(-centerLat, centerLon, 0);
259 d->m_planetAxis = quat *
roll;
260 d->m_planetAxis.normalize();
262 d->m_dirtyBox =
true;
263 d->m_planetAxis.inverse().toMatrix(d->m_planetAxisMatrix);
264 d->m_planetAxis.normalize();
267qreal ViewportParams::heading()
const
272Quaternion ViewportParams::planetAxis()
const
274 return d->m_planetAxis;
277const matrix &ViewportParams::planetAxisMatrix()
const
279 return d->m_planetAxisMatrix;
282int ViewportParams::width()
const
284 return d->m_size.width();
287int ViewportParams::height()
const
289 return d->m_size.height();
292QSize ViewportParams::size()
const
297void ViewportParams::setWidth(
int newWidth)
299 setSize(
QSize(newWidth, height()));
302void ViewportParams::setHeight(
int newHeight)
304 setSize(
QSize(width(), newHeight));
307void ViewportParams::setSize(
const QSize &newSize)
309 if (newSize == d->m_size)
312 d->m_dirtyBox =
true;
320qreal ViewportParams::centerLongitude()
const
322 return d->m_centerLongitude;
325qreal ViewportParams::centerLatitude()
const
327 return d->m_centerLatitude;
330const GeoDataLatLonAltBox &ViewportParams::viewLatLonAltBox()
const
333 d->m_viewLatLonAltBox = d->m_currentProjection->latLonAltBox(
QRect(
QPoint(0, 0), d->m_size),
this);
334 d->m_dirtyBox =
false;
337 return d->m_viewLatLonAltBox;
340GeoDataLatLonAltBox ViewportParams::latLonAltBox(
const QRect &screenRect)
const
342 return d->m_currentProjection->latLonAltBox(screenRect,
this);
345qreal ViewportParams::angularResolution()
const
350 return d->m_angularResolution;
353bool ViewportParams::resolves(
const GeoDataLatLonBox &latLonBox, qreal pixel)
const
355 return latLonBox.
width() + latLonBox.height() > pixel * d->m_angularResolution;
358bool ViewportParams::resolves(
const GeoDataLatLonAltBox &latLonAltBox, qreal pixel, qreal altitude)
const
360 return latLonAltBox.width() + latLonAltBox.height() > pixel * d->m_angularResolution || latLonAltBox.maxAltitude() - latLonAltBox.minAltitude() > altitude;
363bool ViewportParams::resolves(
const GeoDataCoordinates &coord1,
const GeoDataCoordinates &coord2)
const
366 coord1.geoCoordinates(lon1, lat1);
369 coord2.geoCoordinates(lon2, lat2);
372 return (fabs(lon2 - lon1) + fabs(lat2 - lat1) > d->m_angularResolution);
375bool ViewportParams::screenCoordinates(
const qreal lon,
const qreal lat, qreal &x, qreal &y)
const
377 return d->m_currentProjection->screenCoordinates(lon, lat,
this, x, y);
380bool ViewportParams::screenCoordinates(
const GeoDataCoordinates &geopoint, qreal &x, qreal &y,
bool &globeHidesPoint)
const
382 return d->m_currentProjection->screenCoordinates(geopoint,
this, x, y, globeHidesPoint);
385bool ViewportParams::screenCoordinates(
const GeoDataCoordinates &geopoint, qreal &x, qreal &y)
const
387 return d->m_currentProjection->screenCoordinates(geopoint,
this, x, y);
395 bool &globeHidesPoint)
const
397 return d->m_currentProjection->screenCoordinates(coordinates,
this, x, y, pointRepeatNum, size, globeHidesPoint);
402 return d->m_currentProjection->screenCoordinates(lineString,
this, polygons);
407 return d->m_currentProjection->geoCoordinates(x, y,
this, lon, lat, unit);
410bool ViewportParams::mapCoversViewport()
const
412 return d->m_currentProjection->mapCoversViewport(
this);
417 return d->m_currentProjection->mapShape(
this);
420QRegion ViewportParams::mapRegion()
const
422 return d->m_currentProjection->mapRegion(
this);
427 if (d->m_focusPoint.isValid()) {
428 return d->m_focusPoint;
430 const qreal lon = d->m_centerLongitude;
431 const qreal lat = d->m_centerLatitude;
433 return {lon, lat, 0.0, GeoDataCoordinates::Radian};
439 d->m_focusPoint = focusPoint;
442void ViewportParams::resetFocusPoint()
This file contains the headers for EquirectProjection.
This file contains the headers for MercatorProjection.
This file contains the headers for SphericalProjection.
This file contains the headers for ViewportParams.
A 3d point representation.
Unit
enum used constructor to specify the units used
A LineString that allows to store a contiguous set of line segments.
QAction * roll(const QObject *recvr, const char *slot, QObject *parent)
Binds a QML item to a specific geodetic location in screen coordinates.
@ Mercator
Mercator projection.
@ VerticalPerspective
Vertical perspective projection.
@ AzimuthalEquidistant
Azimuthal Equidistant projection.
@ Gnomonic
Gnomonic projection.
@ LambertAzimuthal
Lambert Azimuthal Equal-Area projection.
@ Equirectangular
Flat projection ("plate carree")
@ Spherical
Spherical projection ("Orthographic")
@ Stereographic
Stereographic projection.