13 #include <QPainterPath>
16 #include "MarbleDebug.h"
17 #include "GeoDataLatLonAltBox.h"
21 #include "GnomonicProjection.h"
22 #include "LambertAzimuthalProjection.h"
23 #include "AzimuthalEquidistantProjection.h"
24 #include "StereographicProjection.h"
25 #include "VerticalPerspectiveProjection.h"
31 class ViewportParamsPrivate
35 qreal centerLongitude, qreal centerLatitude,
39 static const AbstractProjection *abstractProjection(
Projection projection );
44 const AbstractProjection *m_currentProjection;
47 qreal m_centerLongitude;
48 qreal m_centerLatitude;
50 Quaternion m_planetAxis;
51 matrix m_planetAxisMatrix;
53 qreal m_angularResolution;
59 GeoDataLatLonAltBox m_viewLatLonAltBox;
61 static const SphericalProjection s_sphericalProjection;
62 static const EquirectProjection s_equirectProjection;
63 static const MercatorProjection s_mercatorProjection;
64 static const GnomonicProjection s_gnomonicProjection;
65 static const StereographicProjection s_stereographicProjection;
66 static const LambertAzimuthalProjection s_lambertAzimuthalProjection;
67 static const AzimuthalEquidistantProjection s_azimuthalEquidistantProjection;
68 static const VerticalPerspectiveProjection s_verticalPerspectiveProjection;
70 GeoDataCoordinates m_focusPoint;
73 const SphericalProjection ViewportParamsPrivate::s_sphericalProjection;
74 const EquirectProjection ViewportParamsPrivate::s_equirectProjection;
75 const MercatorProjection ViewportParamsPrivate::s_mercatorProjection;
76 const GnomonicProjection ViewportParamsPrivate::s_gnomonicProjection;
77 const StereographicProjection ViewportParamsPrivate::s_stereographicProjection;
78 const LambertAzimuthalProjection ViewportParamsPrivate::s_lambertAzimuthalProjection;
79 const AzimuthalEquidistantProjection ViewportParamsPrivate::s_azimuthalEquidistantProjection;
80 const VerticalPerspectiveProjection ViewportParamsPrivate::s_verticalPerspectiveProjection;
82 ViewportParamsPrivate::ViewportParamsPrivate(
Projection projection,
83 qreal centerLongitude, qreal centerLatitude,
86 : m_projection( projection ),
87 m_currentProjection( abstractProjection( projection ) ),
88 m_centerLongitude( centerLongitude ),
89 m_centerLatitude( centerLatitude ),
94 m_angularResolution(4.0 / abs(m_radius)),
101 const AbstractProjection *ViewportParamsPrivate::abstractProjection(
Projection projection)
103 switch ( projection ) {
105 return &s_sphericalProjection;
107 return &s_equirectProjection;
109 return &s_mercatorProjection;
111 return &s_gnomonicProjection;
113 return &s_stereographicProjection;
115 return &s_lambertAzimuthalProjection;
117 return &s_azimuthalEquidistantProjection;
119 return &s_verticalPerspectiveProjection;
126 ViewportParams::ViewportParams()
127 : d( new ViewportParamsPrivate(
Spherical, 0, 0, 2000,
QSize( 100, 100 ) ) )
129 centerOn( d->m_centerLongitude, d->m_centerLatitude );
132 ViewportParams::ViewportParams(
Projection projection,
133 qreal centerLongitude, qreal centerLatitude,
136 : d( new ViewportParamsPrivate( projection, centerLongitude, centerLatitude, radius, size ) )
138 centerOn( d->m_centerLongitude, d->m_centerLatitude );
141 ViewportParams::~ViewportParams()
153 return d->m_projection;
156 const AbstractProjection *ViewportParams::currentProjection()
const
158 return d->m_currentProjection;
161 void ViewportParams::setProjection(
Projection newProjection)
163 d->m_projection = newProjection;
164 d->m_currentProjection = ViewportParamsPrivate::abstractProjection( newProjection );
169 centerOn( d->m_centerLongitude, d->m_centerLatitude );
172 int ViewportParams::polarity()
const
176 GeoDataCoordinates northPole( 0.0, +currentProjection()->maxLat() );
177 GeoDataCoordinates southPole( 0.0, -currentProjection()->maxLat() );
179 bool globeHidesN, globeHidesS;
184 x, yN, globeHidesN );
186 x, yS, globeHidesS );
191 if ( !globeHidesN && !globeHidesS ) {
200 if ( !globeHidesN && yN < height() / 2 ) {
203 if ( !globeHidesN && yN > height() / 2 ) {
206 if ( !globeHidesS && yS > height() / 2 ) {
209 if ( !globeHidesS && yS < height() / 2 ) {
217 int ViewportParams::radius()
const
224 if ( newRadius > 0 ) {
225 d->m_dirtyBox =
true;
227 d->m_radius = newRadius;
228 d->m_angularResolution = 4.0 / d->m_radius;
232 void ViewportParams::centerOn( qreal lon, qreal lat )
234 if ( !d->m_currentProjection->traversablePoles() ) {
235 if ( lat > d->m_currentProjection->maxLat() )
236 lat = d->m_currentProjection->maxLat();
238 if ( lat < d->m_currentProjection->minLat() )
239 lat = d->m_currentProjection->minLat();
243 while ( lat < -M_PI )
249 while ( lon < -M_PI )
252 d->m_centerLongitude = lon;
253 d->m_centerLatitude = lat;
255 const Quaternion
roll = Quaternion::fromEuler( 0, 0, d->m_heading );
256 const Quaternion quat = Quaternion::fromEuler( -lat, lon, 0.0 );
258 d->m_planetAxis = quat *
roll;
259 d->m_planetAxis.normalize();
261 d->m_dirtyBox =
true;
262 d->m_planetAxis.inverse().toMatrix( d->m_planetAxisMatrix );
263 d->m_planetAxis.normalize();
266 void ViewportParams::setHeading( qreal heading )
268 d->m_heading = heading;
270 const Quaternion
roll = Quaternion::fromEuler( 0, 0, heading );
272 const qreal centerLat = centerLatitude();
273 const qreal centerLon = centerLongitude();
275 const Quaternion quat = Quaternion::fromEuler( -centerLat, centerLon, 0 );
277 d->m_planetAxis = quat *
roll;
278 d->m_planetAxis.normalize();
280 d->m_dirtyBox =
true;
281 d->m_planetAxis.inverse().toMatrix( d->m_planetAxisMatrix );
282 d->m_planetAxis.normalize();
285 qreal ViewportParams::heading()
const
290 Quaternion ViewportParams::planetAxis()
const
292 return d->m_planetAxis;
295 const matrix &ViewportParams::planetAxisMatrix()
const
297 return d->m_planetAxisMatrix;
300 int ViewportParams::width()
const
302 return d->m_size.width();
305 int ViewportParams::height()
const
307 return d->m_size.height();
310 QSize ViewportParams::size()
const
316 void ViewportParams::setWidth(
int newWidth)
318 setSize(
QSize( newWidth, height() ) );
321 void ViewportParams::setHeight(
int newHeight)
323 setSize(
QSize( width(), newHeight ) );
326 void ViewportParams::setSize(
const QSize& newSize)
328 if ( newSize == d->m_size )
331 d->m_dirtyBox =
true;
339 qreal ViewportParams::centerLongitude()
const
341 return d->m_centerLongitude;
344 qreal ViewportParams::centerLatitude()
const
346 return d->m_centerLatitude;
349 const GeoDataLatLonAltBox& ViewportParams::viewLatLonAltBox()
const
352 d->m_viewLatLonAltBox = d->m_currentProjection->latLonAltBox(
QRect(
QPoint( 0, 0 ),
355 d->m_dirtyBox =
false;
358 return d->m_viewLatLonAltBox;
361 GeoDataLatLonAltBox ViewportParams::latLonAltBox(
const QRect &screenRect )
const
363 return d->m_currentProjection->latLonAltBox( screenRect,
this );
366 qreal ViewportParams::angularResolution()
const
371 return d->m_angularResolution;
374 bool ViewportParams::resolves (
const GeoDataLatLonBox &latLonBox, qreal pixel )
const
376 return latLonBox.width() + latLonBox.height() > pixel * d->m_angularResolution;
380 bool ViewportParams::resolves (
const GeoDataLatLonAltBox &latLonAltBox, qreal pixel, qreal altitude )
const
382 return latLonAltBox.width() + latLonAltBox.height() > pixel * d->m_angularResolution
383 || latLonAltBox.maxAltitude() - latLonAltBox.minAltitude() > altitude;
386 bool ViewportParams::resolves (
const GeoDataCoordinates &coord1,
387 const GeoDataCoordinates &coord2 )
const
390 coord1.geoCoordinates( lon1, lat1 );
393 coord2.geoCoordinates( lon2, lat2 );
396 return ( fabs( lon2 - lon1 ) + fabs( lat2 - lat1 ) > d->m_angularResolution );
401 qreal &x, qreal &y )
const
403 return d->m_currentProjection->screenCoordinates( lon, lat,
this, x, y );
408 bool &globeHidesPoint )
const
410 return d->m_currentProjection->screenCoordinates( geopoint,
this, x, y, globeHidesPoint );
414 qreal &x, qreal &y )
const
416 return d->m_currentProjection->screenCoordinates( geopoint,
this, x, y );
420 qreal *x, qreal &y,
int &pointRepeatNum,
422 bool &globeHidesPoint )
const
424 return d->m_currentProjection->screenCoordinates( coordinates,
this, x, y, pointRepeatNum, size, globeHidesPoint );
431 return d->m_currentProjection->screenCoordinates( lineString,
this, polygons );
435 qreal &lon, qreal &lat,
438 return d->m_currentProjection->geoCoordinates( x, y,
this, lon, lat, unit );
441 bool ViewportParams::mapCoversViewport()
const
443 return d->m_currentProjection->mapCoversViewport(
this );
448 return d->m_currentProjection->mapShape(
this );
451 QRegion ViewportParams::mapRegion()
const
453 return d->m_currentProjection->mapRegion(
this );
458 if (d->m_focusPoint.isValid()) {
459 return d->m_focusPoint;
462 const qreal lon = d->m_centerLongitude;
463 const qreal lat = d->m_centerLatitude;