Advertisement
Guest User

ViewportParams.cpp

a guest
May 15th, 2012
37
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.01 KB | None | 0 0
  1. //
  2. // This file is part of the Marble Virtual Globe.
  3. //
  4. // This program is free software licensed under the GNU LGPL. You can
  5. // find a copy of this license in LICENSE.txt in the top directory of
  6. // the source code.
  7. //
  8. // Copyright 2007      Inge Wallin  <ingwa@kde.org>
  9. // Copyright 2008      Jens-Michael Hoffmann <jensmh@gmx.de>
  10. //
  11.  
  12.  
  13. #include "ViewportParams.h"
  14.  
  15. #include <QtCore/QRect>
  16.  
  17. #include <QtGui/QPainterPath>
  18. #include <QtGui/QPainterPathStroker>
  19. #include <QtGui/QRegion>
  20.  
  21. #include "MarbleDebug.h"
  22. #include "SphericalProjection.h"
  23. #include "EquirectProjection.h"
  24. #include "MercatorProjection.h"
  25. #include "MarbleClock.h"
  26.  
  27. #define earthAngularSpeed 0.004167
  28.  
  29. namespace Marble
  30. {
  31.  
  32. class ViewportParamsPrivate
  33. {
  34. public:
  35.     ViewportParamsPrivate();
  36.  
  37.     void setPlanetAxis( const Quaternion &newAxis);
  38.  
  39.     // These two go together.  m_currentProjection points to one of
  40.     // the static Projection classes at the bottom.
  41.     Projection           m_projection;
  42.     const AbstractProjection *m_currentProjection;
  43.  
  44.     // Parameters that determine the painting
  45.     qreal                m_centerLongitude;
  46.     qreal                m_centerLatitude;
  47.     Quaternion           m_planetAxis;   // Position, coded in a quaternion
  48.     Quaternion           m_planetInertialAxis;   // Position, coded in a quaternion
  49.     mutable matrix       m_planetAxisMatrix;
  50.     mutable matrix       m_planetInertialAxisMatrix;
  51.     int                  m_radius;       // Zoom level (pixels / globe radius)
  52.     qreal                m_angularResolution;
  53.  
  54.     QSize                m_size;         // width, height
  55.  
  56.  
  57.     bool                 m_dirtyBox;
  58.     GeoDataLatLonAltBox  m_viewLatLonAltBox;
  59.  
  60.     static const SphericalProjection  s_sphericalProjection;
  61.     static const EquirectProjection   s_equirectProjection;
  62.     static const MercatorProjection   s_mercatorProjection;
  63.  
  64.     GeoDataCoordinates   m_focusPoint;
  65.     bool                 m_hasFocusPoint;
  66.     mutable const MarbleClock*   m_clock;
  67.  
  68. };
  69.  
  70. ViewportParamsPrivate::ViewportParamsPrivate()
  71.     : m_projection( Spherical ),
  72.       m_currentProjection( &s_sphericalProjection ),
  73.       m_centerLongitude( 0 ),
  74.       m_centerLatitude( 0 ),
  75.       m_planetAxis( 1.0, 0.0, 0.0, 0.0 ), // Default view
  76.       m_planetInertialAxis( 1.0, 0.0, 0.0, 0.0 ),
  77.       m_planetAxisMatrix(),
  78.       m_planetInertialAxisMatrix(),
  79.       m_radius( 2000 ),
  80.       m_angularResolution( 0.25 * M_PI / fabs( (qreal)( m_radius ) ) ),
  81.       m_size( 100, 100 ),
  82.       m_dirtyBox( true ),
  83.       m_viewLatLonAltBox(),
  84.       m_hasFocusPoint(false),
  85.       m_clock( 0 )
  86. {
  87.     m_planetAxis.inverse().toMatrix( m_planetAxisMatrix );
  88.     m_planetInertialAxis.inverse().toMatrix( m_planetInertialAxisMatrix );
  89. }
  90.  
  91.  
  92. const SphericalProjection  ViewportParamsPrivate::s_sphericalProjection;
  93. const EquirectProjection   ViewportParamsPrivate::s_equirectProjection;
  94. const MercatorProjection   ViewportParamsPrivate::s_mercatorProjection;
  95.  
  96.  
  97. ViewportParams::ViewportParams()
  98.     : d( new ViewportParamsPrivate )
  99. {
  100. }
  101.  
  102. ViewportParams::~ViewportParams()
  103. {
  104.     delete d;
  105. }
  106.  
  107.  
  108. // ================================================================
  109. //                    Getters and setters
  110.  
  111.  
  112. Projection ViewportParams::projection() const
  113. {
  114.     return d->m_projection;
  115. }
  116.  
  117. const AbstractProjection *ViewportParams::currentProjection() const
  118. {
  119.     return d->m_currentProjection;
  120. }
  121.  
  122. void ViewportParams::setProjection(Projection newProjection)
  123. {
  124.     d->m_dirtyBox = true;
  125.  
  126.     d->m_projection = newProjection;
  127.  
  128.     // Set the pointer to the current projection class.
  129.     switch ( newProjection ) {
  130.     case Spherical:
  131.         d->m_currentProjection = &d->s_sphericalProjection;
  132.         break;
  133.     case Equirectangular:
  134.         d->m_currentProjection = &d->s_equirectProjection;
  135.         break;
  136.     case Mercator:
  137.         d->m_currentProjection = &d->s_mercatorProjection;
  138.         break;
  139.     }
  140.  
  141.     // We now need to reset the planetAxis to make sure
  142.     // that it's a valid axis orientation!
  143.     // So this line is important (although it might look odd) ! :
  144.     centerOn( d->m_centerLongitude, d->m_centerLatitude );
  145. }
  146.  
  147. int ViewportParams::polarity() const
  148. {
  149.     // For mercator this just gives the extreme latitudes
  150.     // instead of the actual poles but it works fine as well:
  151.     GeoDataCoordinates northPole( 0.0, +currentProjection()->maxLat() );
  152.     GeoDataCoordinates southPole( 0.0, -currentProjection()->maxLat() );
  153.  
  154.     bool globeHidesN, globeHidesS;
  155.     qreal x;
  156.     qreal yN, yS;
  157.  
  158.     currentProjection()->screenCoordinates( northPole, this,
  159.                                           x, yN, globeHidesN );
  160.     currentProjection()->screenCoordinates( southPole, this,
  161.                                           x, yS, globeHidesS );
  162.  
  163.     int polarity = 0;
  164.  
  165.     // case of the flat map:
  166.     if ( !globeHidesN && !globeHidesS ) {
  167.         if ( yN < yS ) {
  168.             polarity = +1;
  169.         }
  170.         if ( yS < yN ) {
  171.             polarity = -1;
  172.         }
  173.     }
  174.     else {
  175.         if ( !globeHidesN && yN < height() / 2 ) {
  176.             polarity = +1;
  177.         }
  178.         if ( !globeHidesN && yN > height() / 2 ) {
  179.             polarity = -1;
  180.         }
  181.         if ( !globeHidesS && yS > height() / 2 ) {
  182.             polarity = +1;
  183.         }
  184.         if ( !globeHidesS && yS < height() / 2 ) {
  185.             polarity = -1;
  186.         }
  187.     }
  188.  
  189.     return polarity;
  190. }
  191.  
  192. int ViewportParams::radius() const
  193. {
  194.     return d->m_radius;
  195. }
  196.  
  197. void ViewportParams::setRadius(int newRadius)
  198. {
  199.     d->m_dirtyBox = true;
  200.  
  201.     d->m_radius = newRadius;
  202.     d->m_angularResolution = 0.25 * M_PI / fabs( (qreal)(d->m_radius) );
  203. }
  204.  
  205. bool ViewportParams::globeCoversViewport() const
  206. {
  207.     // This first test is a quick one that will catch all really big
  208.     // radii and prevent overflow in the real test.
  209.     if ( d->m_radius > d->m_size.width() + d->m_size.height() )
  210.         return true;
  211.  
  212.     // This is the real test.  The 4 is because we are really
  213.     // comparing to width/2 and height/2.
  214.     if ( 4 * d->m_radius * d->m_radius >= d->m_size.width() * d->m_size.width()
  215.                                           + d->m_size.height() * d->m_size.height() )
  216.         return true;
  217.  
  218.     return false;
  219. }
  220.  
  221. void ViewportParams::centerOn( qreal lon, qreal lat )
  222. {
  223.     if ( !d->m_currentProjection->traversablePoles() ) {
  224.         if ( lat > d->m_currentProjection->maxLat() )
  225.             lat = d->m_currentProjection->maxLat();
  226.  
  227.         if ( lat < d->m_currentProjection->minLat() )
  228.             lat = d->m_currentProjection->minLat();
  229.     } else {
  230.         while ( lat > M_PI )
  231.             lat -= 2 * M_PI;
  232.         while ( lat < -M_PI )
  233.             lat += 2 * M_PI;
  234.     }
  235.  
  236.     while ( lon > M_PI )
  237.         lon -= 2 * M_PI;
  238.     while ( lon < -M_PI )
  239.         lon += 2 * M_PI;
  240.  
  241.     d->m_centerLongitude = lon;
  242.     d->m_centerLatitude = lat;
  243.  
  244.     Quaternion axis = Quaternion::fromEuler( -lat, lon, 0.0 );
  245.     axis.normalize();
  246.  
  247.     d->setPlanetAxis( axis );
  248. }
  249.  
  250. Quaternion ViewportParams::planetAxis() const
  251. {
  252.     return d->m_planetAxis;
  253. }
  254.  
  255. void ViewportParamsPrivate::setPlanetAxis(const Quaternion &newAxis)
  256. {
  257.     m_dirtyBox = true;
  258.     m_planetAxis = newAxis;
  259.     m_planetAxis.inverse().toMatrix( m_planetAxisMatrix );
  260.     qreal lon;
  261.     qreal lat;
  262.     m_planetInertialAxis.getSpherical(lon, lat); //  takes the normal axis and retrieve lon and lat from it
  263.     // Enter your lat-lon-Fixed-To-Inertial coordinate conversion code here and apply the new values to lat and lon
  264.     if (m_clock){
  265.         Qt::DateFormat format = Qt::ISODate;
  266.         QString dateString("2000-01-01T00:00:00");
  267.         QDateTime someFixedTimeBack = QDateTime::fromString(dateString, format);
  268.         double timeDelta = m_clock->dateTime().toTime_t() - someFixedTimeBack.toTime_t();
  269.         lon = lon - (earthAngularSpeed * timeDelta);
  270.     }
  271.     Quaternion axis = Quaternion::fromEuler( -lat, lon, 0.0 );
  272.     axis.normalize();
  273.     m_planetInertialAxis = axis;
  274. }
  275.  
  276. void ViewportParams::setClock(const MarbleClock* clock) const
  277. {
  278.         d->m_clock = clock;
  279. }
  280.  
  281. const matrix * ViewportParams::planetAxisMatrix(int type) const
  282. {
  283.     if (!type)
  284.         return &d->m_planetAxisMatrix;
  285.     return &d->m_planetInertialAxisMatrix;
  286. }
  287.  
  288. const matrix * ViewportParams::planetInertialAxisMatrix() const
  289. {
  290.     return &d->m_planetInertialAxisMatrix;
  291. }
  292.  
  293. int ViewportParams::width()  const
  294. {
  295.     return d->m_size.width();
  296. }
  297.  
  298. int ViewportParams::height() const
  299. {
  300.     return d->m_size.height();
  301. }
  302.  
  303. QSize ViewportParams::size() const
  304. {
  305.     return d->m_size;
  306. }
  307.  
  308.  
  309. void ViewportParams::setWidth(int newWidth)
  310. {
  311.     d->m_dirtyBox = true;
  312.  
  313.     d->m_size.setWidth( newWidth );
  314. }
  315.  
  316. void ViewportParams::setHeight(int newHeight)
  317. {
  318.     d->m_dirtyBox = true;
  319.  
  320.     d->m_size.setHeight( newHeight );
  321. }
  322.  
  323. void ViewportParams::setSize(QSize newSize)
  324. {
  325.     if ( newSize == d->m_size )
  326.         return;
  327.  
  328.     d->m_dirtyBox = true;
  329.  
  330.     d->m_size = newSize;
  331. }
  332.  
  333. // ================================================================
  334. //                        Other functions
  335.  
  336. qreal ViewportParams::centerLongitude() const
  337. {
  338.     return d->m_centerLongitude;
  339. }
  340.  
  341. qreal ViewportParams::centerLatitude() const
  342. {
  343.     return d->m_centerLatitude;
  344. }
  345.  
  346. void ViewportParams::centerCoordinates( qreal &centerLon, qreal &centerLat ) const
  347. {
  348.     centerLon = d->m_centerLongitude;
  349.     centerLat = d->m_centerLatitude;
  350. }
  351.  
  352. GeoDataLatLonAltBox ViewportParams::viewLatLonAltBox() const
  353. {
  354.     if (d->m_dirtyBox) {
  355.         d->m_viewLatLonAltBox = d->m_currentProjection->latLonAltBox( QRect( QPoint( 0, 0 ),
  356.                         d->m_size ),
  357.                         this );
  358.         d->m_dirtyBox = false;
  359.     }
  360.  
  361.     return d->m_viewLatLonAltBox;
  362. }
  363.  
  364. GeoDataLatLonAltBox ViewportParams::latLonAltBox( const QRect &screenRect ) const
  365. {
  366.     return d->m_currentProjection->latLonAltBox( screenRect, this );
  367. }
  368.  
  369. qreal ViewportParams::angularResolution() const
  370. {
  371.     // We essentially divide the diameter by 180 deg and
  372.     // take half of the result as a guess for the angle per pixel resolution.
  373.     // d->m_angularResolution = 0.25 * M_PI / fabs( (qreal)(d->m_radius);
  374.     return d->m_angularResolution;
  375. }
  376.  
  377. bool ViewportParams::resolves ( const GeoDataLatLonBox &latLonBox ) const
  378. {
  379.     return latLonBox.width() + latLonBox.height() > 2.0 * angularResolution();
  380. }
  381.  
  382.  
  383. bool ViewportParams::resolves ( const GeoDataLatLonAltBox &latLonAltBox ) const
  384. {
  385.     return    latLonAltBox.width() + latLonAltBox.height() > 2.0 * angularResolution()
  386.            || latLonAltBox.maxAltitude() - latLonAltBox.minAltitude() > 10000;
  387.            
  388. }
  389.  
  390. bool ViewportParams::resolves ( const GeoDataCoordinates &coord1,
  391.                                 const GeoDataCoordinates &coord2 ) const
  392. {
  393.     qreal lon1, lat1;
  394.     coord1.geoCoordinates( lon1, lat1 );
  395.  
  396.     qreal lon2, lat2;
  397.     coord2.geoCoordinates( lon2, lat2 );
  398.  
  399.     // We take the manhattan length as an approximation for the distance
  400.     return ( fabs( lon2 - lon1 ) + fabs( lat2 - lat1 ) < angularResolution() );
  401. }
  402.  
  403.  
  404. bool ViewportParams::screenCoordinates( const qreal lon, const qreal lat,
  405.                         qreal &x, qreal &y ) const
  406. {
  407.     return d->m_currentProjection->screenCoordinates( lon, lat, this, x, y );
  408. }
  409.  
  410. bool ViewportParams::screenCoordinates( const GeoDataCoordinates &geopoint,
  411.                         qreal &x, qreal &y,
  412.                         bool &globeHidesPoint ) const
  413. {
  414.     return d->m_currentProjection->screenCoordinates( geopoint, this, x, y, globeHidesPoint );
  415. }
  416.  
  417. bool ViewportParams::screenCoordinates( const GeoDataCoordinates &geopoint,
  418.                         qreal &x, qreal &y ) const
  419. {
  420.     return d->m_currentProjection->screenCoordinates( geopoint, this, x, y );
  421. }
  422.  
  423. bool ViewportParams::screenCoordinates( const GeoDataCoordinates &geopoint,
  424.                         QPointF &screenpoint ) const
  425. {
  426.     return d->m_currentProjection->screenCoordinates( geopoint, this, screenpoint );
  427. }
  428.  
  429. bool ViewportParams::screenCoordinates( const GeoDataCoordinates &coordinates,
  430.                         qreal *x, qreal &y, int &pointRepeatNum,
  431.                         bool &globeHidesPoint ) const
  432. {
  433.     return d->m_currentProjection->screenCoordinates( coordinates, this, x, y, pointRepeatNum, globeHidesPoint );
  434. }
  435.  
  436. bool ViewportParams::screenCoordinates( const GeoDataCoordinates &coordinates,
  437.                         qreal *x, qreal &y, int &pointRepeatNum,
  438.                         const QSizeF& size,
  439.                         bool &globeHidesPoint ) const
  440. {
  441.     return d->m_currentProjection->screenCoordinates( coordinates, this, x, y, pointRepeatNum, size, globeHidesPoint );
  442. }
  443.  
  444.  
  445. bool ViewportParams::screenCoordinates( const GeoDataLineString &lineString,
  446.                         QVector<QPolygonF*> &polygons ) const
  447. {
  448.     return d->m_currentProjection->screenCoordinates( lineString, this, polygons );
  449. }
  450.  
  451. bool ViewportParams::geoCoordinates( const int x, const int y,
  452.                      qreal &lon, qreal &lat,
  453.                      GeoDataCoordinates::Unit unit ) const
  454. {
  455.     return d->m_currentProjection->geoCoordinates( x, y, this, lon, lat, unit );
  456. }
  457.  
  458. bool  ViewportParams::mapCoversViewport() const
  459. {
  460.     return d->m_currentProjection->mapCoversViewport( this );
  461. }
  462.  
  463. QPainterPath ViewportParams::mapShape() const
  464. {
  465.     return d->m_currentProjection->mapShape( this );
  466. }
  467.  
  468. QRegion ViewportParams::mapRegion() const
  469. {
  470.     return d->m_currentProjection->mapRegion( this );
  471. }
  472.  
  473. GeoDataCoordinates ViewportParams::focusPoint() const
  474. {
  475.     if (d->m_hasFocusPoint) {
  476.         return d->m_focusPoint;
  477.     }
  478.     else {
  479.        const qreal lon = d->m_centerLongitude;
  480.        const qreal lat = d->m_centerLatitude;
  481.  
  482.        return GeoDataCoordinates(lon, lat, 0.0, GeoDataCoordinates::Radian);
  483.     }
  484.  
  485. }
  486.  
  487. void ViewportParams::setFocusPoint(const GeoDataCoordinates &focusPoint)
  488. {
  489.     d->m_focusPoint = focusPoint;
  490.     d->m_hasFocusPoint = true;
  491. }
  492.  
  493. void ViewportParams::resetFocusPoint()
  494. {
  495.     d->m_hasFocusPoint = false;
  496. }
  497.  
  498. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement