Marble

GnomonicProjection.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2013 Bernhard Beschow <[email protected]>
4 //
5 
6 // Local
7 #include "GnomonicProjection.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 GnomonicProjectionPrivate : public AzimuthalProjectionPrivate
29 {
30  public:
31  explicit GnomonicProjectionPrivate( GnomonicProjection * parent );
32 
33  Q_DECLARE_PUBLIC( GnomonicProjection )
34 };
35 
37  : AzimuthalProjection( new GnomonicProjectionPrivate( this ) )
38 {
39  setMinLat( minValidLat() );
40  setMaxLat( maxValidLat() );
41 }
42 
43 GnomonicProjection::GnomonicProjection( GnomonicProjectionPrivate *dd )
44  : AzimuthalProjection( dd )
45 {
46  setMinLat( minValidLat() );
47  setMaxLat( maxValidLat() );
48 }
49 
50 GnomonicProjection::~GnomonicProjection()
51 {
52 }
53 
54 
55 GnomonicProjectionPrivate::GnomonicProjectionPrivate( GnomonicProjection * parent )
56  : AzimuthalProjectionPrivate( parent )
57 {
58 }
59 
61 {
62  return QObject::tr( "Gnomonic" );
63 }
64 
66 {
67  return QObject::tr( "<p><b>Gnomonic Projection</b> (\"rectilinear\")</p><p>Applications: Used for displaying panorama photography. Also used for navigation, radio and seismic work.</p>" );
68 }
69 
71 {
72  return QIcon(QStringLiteral(":/icons/map-gnomonic.png"));
73 }
74 
75 qreal GnomonicProjection::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 
91  if ( cosC <= 0) {
92  globeHidesPoint = true;
93  return false;
94  }
95 
96  // Let (x, y) be the position on the screen of the placemark..
97  x = ( qCos( phi ) * qSin( lambda - lambdaPrime ) ) / cosC;
98  y = ( qCos( phi1 ) * qSin( phi ) - qSin( phi1 ) * qCos( phi ) * qCos( lambda - lambdaPrime ) ) / cosC;
99 
100  x *= viewport->radius() / 2;
101  y *= viewport->radius() / 2;
102 
103  const qint64 radius = clippingRadius() * viewport->radius();
104 
105  if (x*x + y*y > radius * radius) {
106  globeHidesPoint = true;
107  return false;
108  }
109 
110  globeHidesPoint = false;
111 
112  x += viewport->width() / 2;
113  y = viewport->height() / 2 - y;
114 
115  // Skip placemarks that are outside the screen area
116  return !(x < 0 || x >= viewport->width() || y < 0 || y >= viewport->height());
117 }
118 
120  const ViewportParams *viewport,
121  qreal *x, qreal &y,
122  int &pointRepeatNum,
123  const QSizeF& size,
124  bool &globeHidesPoint ) const
125 {
126  pointRepeatNum = 0;
127  globeHidesPoint = false;
128 
129  bool visible = screenCoordinates( coordinates, viewport, *x, y, globeHidesPoint );
130 
131  // Skip placemarks that are outside the screen area
132  if ( *x + size.width() / 2.0 < 0.0 || *x >= viewport->width() + size.width() / 2.0
133  || y + size.height() / 2.0 < 0.0 || y >= viewport->height() + size.height() / 2.0 )
134  {
135  return false;
136  }
137 
138  // This projection doesn't have any repetitions,
139  // so the number of screen points referring to the geopoint is one.
140  pointRepeatNum = 1;
141  return visible;
142 }
143 
144 
145 bool GnomonicProjection::geoCoordinates( const int x, const int y,
146  const ViewportParams *viewport,
147  qreal& lon, qreal& lat,
148  GeoDataCoordinates::Unit unit ) const
149 {
150  const qint64 radius = viewport->radius();
151  // Calculate how many degrees are being represented per pixel.
152  const qreal centerLon = viewport->centerLongitude();
153  const qreal centerLat = viewport->centerLatitude();
154  const qreal rx = ( - viewport->width() / 2 + x );
155  const qreal ry = ( viewport->height() / 2 - y );
156  const qreal p = qMax( qSqrt( rx*rx + ry*ry ), qreal(0.0001) ); // ensure we don't divide by zero
157  const qreal c = qAtan(2 * p / radius);
158  const qreal sinc = qSin(c);
159 
160  lon = centerLon + qAtan2( rx*sinc , ( p*qCos( centerLat )*qCos( c ) - ry*qSin( centerLat )*sinc ) );
161 
162  while ( lon < -M_PI ) lon += 2 * M_PI;
163  while ( lon > M_PI ) lon -= 2 * M_PI;
164 
165  lat = qAsin( qCos(c)*qSin(centerLat) + ry*sinc*qCos(centerLat)/p );
166 
167  if ( unit == GeoDataCoordinates::Degree ) {
168  lon *= RAD2DEG;
169  lat *= RAD2DEG;
170  }
171 
172  return true;
173 }
174 
175 }
A 3d point representation.
qreal height() const const
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.
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...
QIcon icon() const override
Returns an icon for the projection.
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...
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.
GnomonicProjection()
Construct a new GnomonicProjection.
QString name() const override
Returns the user-visible name of the projection.
Unit
enum used constructor to specify the units used
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.
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 Wed Nov 29 2023 04:12:19 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.