Marble

AzimuthalEquidistantProjection.cpp
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 2014 Torsten Rahn <[email protected]>
9 //
10 
11 // Local
12 #include "AzimuthalEquidistantProjection.h"
13 #include "AbstractProjection_p.h"
14 
15 #include "MarbleDebug.h"
16 
17 // Marble
18 #include "ViewportParams.h"
19 #include "GeoDataPoint.h"
20 #include "GeoDataLineString.h"
21 #include "GeoDataCoordinates.h"
22 #include "MarbleGlobal.h"
23 #include "AzimuthalProjection_p.h"
24 
25 #include <QIcon>
26 #include <qmath.h>
27 
28 #define SAFE_DISTANCE
29 
30 namespace Marble
31 {
32 
33 class AzimuthalEquidistantProjectionPrivate : public AzimuthalProjectionPrivate
34 {
35  public:
36  explicit AzimuthalEquidistantProjectionPrivate( AzimuthalEquidistantProjection * parent );
37 
38  Q_DECLARE_PUBLIC( AzimuthalEquidistantProjection )
39 };
40 
42  : AzimuthalProjection( new AzimuthalEquidistantProjectionPrivate( this ) )
43 {
44  setMinLat( minValidLat() );
45  setMaxLat( maxValidLat() );
46 }
47 
48 AzimuthalEquidistantProjection::AzimuthalEquidistantProjection( AzimuthalEquidistantProjectionPrivate *dd )
49  : AzimuthalProjection( dd )
50 {
51  setMinLat( minValidLat() );
52  setMaxLat( maxValidLat() );
53 }
54 
55 AzimuthalEquidistantProjection::~AzimuthalEquidistantProjection()
56 {
57 }
58 
60 {
61  return QObject::tr( "Azimuthal Equidistant" );
62 }
63 
65 {
66  return QObject::tr( "<p><b>Azimuthal Equidistant Projection</b> (\"fish eye\")</p><p>Applications: Display of seismic and radio data and for use in digital planetariums.</p>" );
67 }
68 
70 {
71  return QIcon(QStringLiteral(":/icons/map-globe.png"));
72 }
73 
74 AzimuthalEquidistantProjectionPrivate::AzimuthalEquidistantProjectionPrivate( AzimuthalEquidistantProjection * parent )
75  : AzimuthalProjectionPrivate( parent )
76 {
77 }
78 
79 qreal AzimuthalEquidistantProjection::clippingRadius() const
80 {
81  return 1;
82 }
83 
85  const ViewportParams *viewport,
86  qreal &x, qreal &y, bool &globeHidesPoint ) const
87 {
88  const qreal lambda = coordinates.longitude();
89  const qreal phi = coordinates.latitude();
90  const qreal lambdaPrime = viewport->centerLongitude();
91  const qreal phi1 = viewport->centerLatitude();
92 
93  qreal cosC = qSin( phi1 ) * qSin( phi ) + qCos( phi1 ) * qCos( phi ) * qCos( lambda - lambdaPrime );
94  // Prevent division by zero
95  if (cosC <= 0) {
96  globeHidesPoint = true;
97  return false;
98  }
99 
100  qreal c = qAcos(cosC);
101 
102  qreal k = cosC == 1 ? 1 : c / qSin( c );
103 
104  // Let (x, y) be the position on the screen of the placemark..
105  x = ( qCos( phi ) * qSin( lambda - lambdaPrime ) ) * k;
106  y = ( qCos( phi1 ) * qSin( phi ) - qSin( phi1 ) * qCos( phi ) * qCos( lambda - lambdaPrime ) ) * k;
107 
108  x *= 2 * viewport->radius() / M_PI;
109  y *= 2 * viewport->radius() / M_PI;
110 
111  const qint64 radius = clippingRadius() * viewport->radius();
112 
113  if (x*x + y*y > radius * radius) {
114  globeHidesPoint = true;
115  return false;
116  }
117 
118  globeHidesPoint = false;
119 
120  x += viewport->width() / 2;
121  y = viewport->height() / 2 - y;
122 
123  // Skip placemarks that are outside the screen area
124  return !(x < 0 || x >= viewport->width() || y < 0 || y >= viewport->height());
125 }
126 
128  const ViewportParams *viewport,
129  qreal *x, qreal &y,
130  int &pointRepeatNum,
131  const QSizeF& size,
132  bool &globeHidesPoint ) const
133 {
134  pointRepeatNum = 0;
135  globeHidesPoint = false;
136 
137  bool visible = screenCoordinates( coordinates, viewport, *x, y, globeHidesPoint );
138 
139  // Skip placemarks that are outside the screen area
140  if ( *x + size.width() / 2.0 < 0.0 || *x >= viewport->width() + size.width() / 2.0
141  || y + size.height() / 2.0 < 0.0 || y >= viewport->height() + size.height() / 2.0 )
142  {
143  return false;
144  }
145 
146  // This projection doesn't have any repetitions,
147  // so the number of screen points referring to the geopoint is one.
148  pointRepeatNum = 1;
149  return visible;
150 }
151 
152 
153 bool AzimuthalEquidistantProjection::geoCoordinates( const int x, const int y,
154  const ViewportParams *viewport,
155  qreal& lon, qreal& lat,
156  GeoDataCoordinates::Unit unit ) const
157 {
158  const qint64 radius = viewport->radius();
159  // Calculate how many degrees are being represented per pixel.
160  const qreal rad2Pixel = ( 2 * radius ) / M_PI;
161  const qreal centerLon = viewport->centerLongitude();
162  const qreal centerLat = viewport->centerLatitude();
163  const qreal rx = ( - viewport->width() / 2 + x ) / rad2Pixel;
164  const qreal ry = ( viewport->height() / 2 - y ) / rad2Pixel;
165  const qreal c = qMax( qSqrt( rx*rx + ry*ry ), qreal(0.0001) ); // ensure we don't divide by zero
166  const qreal sinc = qSin(c);
167 
168  lon = centerLon + qAtan2( rx*sinc , ( c*qCos( centerLat )*qCos( c ) - ry*qSin( centerLat )*sinc ) );
169 
170  while ( lon < -M_PI ) lon += 2 * M_PI;
171  while ( lon > M_PI ) lon -= 2 * M_PI;
172 
173  lat = qAsin( qCos(c)*qSin(centerLat) + (ry*sinc*qCos(centerLat))/c );
174 
175  if ( unit == GeoDataCoordinates::Degree ) {
176  lon *= RAD2DEG;
177  lat *= RAD2DEG;
178  }
179 
180  return true;
181 }
182 
183 }
Unit
enum used constructor to specify the units used
bool geoCoordinates(const int x, const int y, const ViewportParams *params, qreal &lon, qreal &lat, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Degree) const override
Get the earth coordinates corresponding to a pixel in the map.
A 3d point representation.
QString name() const override
Returns the user-visible name of the projection.
Binds a QML item to a specific geodetic location in screen coordinates.
virtual qreal minValidLat() const
Returns the minimum (southern) latitude that is mathematically defined and reasonable.
QString description() const override
Returns a short user description of the projection that can be used in tooltips or dialogs...
A base class for the Gnomonic and Orthographic (Globe) projections in Marble.
QString tr(const char *sourceText, const char *disambiguation, int n)
QIcon icon() const override
Returns an icon for the projection.
virtual qreal maxValidLat() const
Returns the maximum (northern) latitude that is mathematically defined and reasonable.
bool screenCoordinates(const GeoDataCoordinates &coordinates, const ViewportParams *params, qreal &x, qreal &y, bool &globeHidesPoint) const override
Get the screen coordinates corresponding to geographical coordinates in the map.
A public class that controls what is visible in the viewport of a Marble map.
AzimuthalEquidistantProjection()
Construct a new AzimuthalEquidistantProjection.
A class to implement the spherical projection used by the "Globe" view.
This file contains the headers for ViewportParams.
qreal longitude(GeoDataCoordinates::Unit unit) const
retrieves the longitude of the GeoDataCoordinates object use the unit parameter to switch between Rad...
qreal latitude(GeoDataCoordinates::Unit unit) const
retrieves the latitude of the GeoDataCoordinates object use the unit parameter to switch between Radi...
qreal height() const const
qreal width() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Nov 30 2020 23:21:12 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.