Marble

StereographicProjection.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 "StereographicProjection.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 StereographicProjectionPrivate : public AzimuthalProjectionPrivate
29 {
30  public:
31  explicit StereographicProjectionPrivate( StereographicProjection * parent );
32 
33  Q_DECLARE_PUBLIC( StereographicProjection )
34 };
35 
37  : AzimuthalProjection( new StereographicProjectionPrivate( this ) )
38 {
39  setMinLat( minValidLat() );
40  setMaxLat( maxValidLat() );
41 }
42 
43 StereographicProjection::StereographicProjection( StereographicProjectionPrivate *dd )
44  : AzimuthalProjection( dd )
45 {
46  setMinLat( minValidLat() );
47  setMaxLat( maxValidLat() );
48 }
49 
50 StereographicProjection::~StereographicProjection()
51 {
52 }
53 
54 
55 StereographicProjectionPrivate::StereographicProjectionPrivate( StereographicProjection * parent )
56  : AzimuthalProjectionPrivate( parent )
57 {
58 }
59 
61 {
62  return QObject::tr( "Stereographic" );
63 }
64 
66 {
67  return QObject::tr( "<p><b>Stereographic Projection</b> (\"orthogonal\")</p><p>Applications: Used for planetary cartography, geology and panorama photography.</p>" );
68 }
69 
71 {
72  return QIcon(QStringLiteral(":/icons/map-globe.png"));
73 }
74 
75 qreal StereographicProjection::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 = 1 / (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();
103  y *= viewport->radius();
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 StereographicProjection::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  const qreal c = 2 * qAtan2( p , radius );
160  const qreal sinc = qSin(c);
161 
162  lon = centerLon + qAtan2( rx*sinc , ( p*qCos( centerLat )*qCos( c ) - ry*qSin( centerLat )*sinc ) );
163 
164  while ( lon < -M_PI ) lon += 2 * M_PI;
165  while ( lon > M_PI ) lon -= 2 * M_PI;
166 
167  lat = qAsin( qCos(c)*qSin(centerLat) + (ry*sinc*qCos(centerLat))/p );
168 
169  if ( unit == GeoDataCoordinates::Degree ) {
170  lon *= RAD2DEG;
171  lat *= RAD2DEG;
172  }
173 
174  return true;
175 }
176 
177 }
Unit
enum used constructor to specify the units used
A 3d point representation.
A class to implement the spherical projection used by the "Globe" view.
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.
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.
A base class for the Gnomonic and Orthographic (Globe) projections in Marble.
QIcon icon() const override
Returns an icon for the projection.
QString tr(const char *sourceText, const char *disambiguation, int n)
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.
A public class that controls what is visible in the viewport of a Marble map.
This file contains the headers for ViewportParams.
StereographicProjection()
Construct a new StereographicProjection.
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
QString description() const override
Returns a short user description of the projection that can be used in tooltips or dialogs...
qreal width() const const
QString name() const override
Returns the user-visible name of the projection.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Mon Jan 17 2022 23:11:28 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.