Marble

LambertAzimuthalProjection.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2014 Torsten Rahn <rahn@kde.org>
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
25namespace Marble
26{
27
28class 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
43LambertAzimuthalProjection::LambertAzimuthalProjection( LambertAzimuthalProjectionPrivate *dd )
45{
46 setMinLat( minValidLat() );
47 setMaxLat( maxValidLat() );
48}
49
50LambertAzimuthalProjection::~LambertAzimuthalProjection()
51{
52}
53
54
55LambertAzimuthalProjectionPrivate::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
75qreal 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
147bool 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}
This file contains the headers for ViewportParams.
virtual qreal maxValidLat() const
Returns the maximum (northern) latitude that is mathematically defined and reasonable.
virtual qreal minValidLat() const
Returns the minimum (southern) latitude that is mathematically defined and reasonable.
A base class for the Gnomonic and Orthographic (Globe) projections in Marble.
A 3d point representation.
qreal longitude(GeoDataCoordinates::Unit unit) const
retrieves the longitude of the GeoDataCoordinates object use the unit parameter to switch between Rad...
Unit
enum used constructor to specify the units used
qreal latitude(GeoDataCoordinates::Unit unit) const
retrieves the latitude of the GeoDataCoordinates object use the unit parameter to switch between Radi...
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.
QString description() const override
Returns a short user description of the projection that can be used in tooltips or dialogs.
QIcon icon() const override
Returns an icon for the projection.
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.
LambertAzimuthalProjection()
Construct a new LambertAzimuthalProjection.
A public class that controls what is visible in the viewport of a Marble map.
Binds a QML item to a specific geodetic location in screen coordinates.
QString tr(const char *sourceText, const char *disambiguation, int n)
qreal height() const const
qreal width() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Apr 27 2024 22:12:41 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.