Marble

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

KDE's Doxygen guidelines are available online.