Marble

LambertAzimuthalProjection.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 "LambertAzimuthalProjection.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 LambertAzimuthalProjectionPrivate : public AzimuthalProjectionPrivate
29 {
30  public:
31  explicit LambertAzimuthalProjectionPrivate( LambertAzimuthalProjection * parent );
32 
33  Q_DECLARE_PUBLIC( LambertAzimuthalProjection )
34 };
35 
37  : AzimuthalProjection( new LambertAzimuthalProjectionPrivate( this ) )
38 {
39  setMinLat( minValidLat() );
40  setMaxLat( maxValidLat() );
41 }
42 
43 LambertAzimuthalProjection::LambertAzimuthalProjection( LambertAzimuthalProjectionPrivate *dd )
44  : AzimuthalProjection( dd )
45 {
46  setMinLat( minValidLat() );
47  setMaxLat( maxValidLat() );
48 }
49 
50 LambertAzimuthalProjection::~LambertAzimuthalProjection()
51 {
52 }
53 
54 
55 LambertAzimuthalProjectionPrivate::LambertAzimuthalProjectionPrivate( LambertAzimuthalProjection * parent )
56  : AzimuthalProjectionPrivate( parent )
57 {
58 }
59 
61 {
62  return QObject::tr( "Lambert Azimuthal Equal-Area" );
63 }
64 
66 {
67  return QObject::tr( "<p><b>Lambert Azimuthal Equal-Area Projection</b></p><p>Applications: Used in structural geology to plot directional data.</p>" );
68 }
69 
71 {
72  return QIcon(QStringLiteral(":/icons/map-globe.png"));
73 }
74 
75 qreal LambertAzimuthalProjection::clippingRadius() const
76 {
77  return 1;
78 }
79 
81  const ViewportParams *viewport,
82  qreal &x, qreal &y, bool &globeHidesPoint ) const
83 {
84  const qreal lambda = coordinates.longitude();
85  const qreal phi = coordinates.latitude();
86  const qreal lambdaPrime = viewport->centerLongitude();
87  const qreal phi1 = viewport->centerLatitude();
88 
89  qreal cosC = qSin( phi1 ) * qSin( phi ) + qCos( phi1 ) * qCos( phi ) * qCos( lambda - lambdaPrime );
90  // Prevent division by zero
91  if (cosC <= 0) {
92  globeHidesPoint = true;
93  return false;
94  }
95 
96  qreal k = qSqrt(2 / (1 + cosC));
97 
98  // Let (x, y) be the position on the screen of the placemark..
99  x = ( qCos( phi ) * qSin( lambda - lambdaPrime ) ) * k;
100  y = ( qCos( phi1 ) * qSin( phi ) - qSin( phi1 ) * qCos( phi ) * qCos( lambda - lambdaPrime ) ) * k;
101 
102  x *= viewport->radius() / qSqrt(2);
103  y *= viewport->radius() / qSqrt(2);
104 
105  const qint64 radius = clippingRadius() * viewport->radius();
106 
107  if (x*x + y*y > radius * radius) {
108  globeHidesPoint = true;
109  return false;
110  }
111 
112  globeHidesPoint = false;
113 
114  x += viewport->width() / 2;
115  y = viewport->height() / 2 - y;
116 
117  // Skip placemarks that are outside the screen area
118  return !(x < 0 || x >= viewport->width() || y < 0 || y >= viewport->height());
119 }
120 
122  const ViewportParams *viewport,
123  qreal *x, qreal &y,
124  int &pointRepeatNum,
125  const QSizeF& size,
126  bool &globeHidesPoint ) const
127 {
128  pointRepeatNum = 0;
129  globeHidesPoint = false;
130 
131  bool visible = screenCoordinates( coordinates, viewport, *x, y, globeHidesPoint );
132 
133  // Skip placemarks that are outside the screen area
134  if ( *x + size.width() / 2.0 < 0.0 || *x >= viewport->width() + size.width() / 2.0
135  || y + size.height() / 2.0 < 0.0 || y >= viewport->height() + size.height() / 2.0 )
136  {
137  return false;
138  }
139 
140  // This projection doesn't have any repetitions,
141  // so the number of screen points referring to the geopoint is one.
142  pointRepeatNum = 1;
143  return visible;
144 }
145 
146 
147 bool LambertAzimuthalProjection::geoCoordinates( const int x, const int y,
148  const ViewportParams *viewport,
149  qreal& lon, qreal& lat,
150  GeoDataCoordinates::Unit unit ) const
151 {
152  const qint64 radius = viewport->radius();
153  // Calculate how many degrees are being represented per pixel.
154  const qreal centerLon = viewport->centerLongitude();
155  const qreal centerLat = viewport->centerLatitude();
156  const qreal rx = ( - viewport->width() / 2 + x );
157  const qreal ry = ( viewport->height() / 2 - y );
158  const qreal p = qMax( qSqrt( rx*rx + ry*ry ), qreal(0.0001) ); // ensure we don't divide by zero
159 
160  // exclude area too far away from map, as it may cause undefined arcsin result
161  if ( p > (qSqrt(2) * radius) ) {
162  return false;
163  }
164  const qreal c = 2 * qAsin( p / (qSqrt(2) * radius) );
165  const qreal sinc = qSin(c);
166 
167  lon = centerLon + qAtan2( rx*sinc , ( p*qCos( centerLat )*qCos( c ) - ry*qSin( centerLat )*sinc ) );
168 
169  while ( lon < -M_PI ) lon += 2 * M_PI;
170  while ( lon > M_PI ) lon -= 2 * M_PI;
171 
172  lat = qAsin( qCos(c)*qSin(centerLat) + (ry*sinc*qCos(centerLat))/p );
173 
174  if ( unit == GeoDataCoordinates::Degree ) {
175  lon *= RAD2DEG;
176  lat *= RAD2DEG;
177  }
178 
179  return true;
180 }
181 
182 }
A 3d point representation.
QString description() const override
Returns a short user description of the projection that can be used in tooltips or dialogs.
qreal height() const const
A base class for the Gnomonic and Orthographic (Globe) projections in Marble.
QString name() const override
Returns the user-visible name of the projection.
qreal longitude(GeoDataCoordinates::Unit unit) const
retrieves the longitude of the GeoDataCoordinates object use the unit parameter to switch between Rad...
LambertAzimuthalProjection()
Construct a new LambertAzimuthalProjection.
A public class that controls what is visible in the viewport of a Marble map.
qreal latitude(GeoDataCoordinates::Unit unit) const
retrieves the latitude of the GeoDataCoordinates object use the unit parameter to switch between Radi...
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.
QIcon icon() const override
Returns an icon for 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.
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.
Unit
enum used constructor to specify the units used
virtual qreal maxValidLat() const
Returns the maximum (northern) latitude that is mathematically defined and reasonable.
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 Dec 11 2023 04:09:40 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.