Marble

EquirectProjection.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2007-2012 Torsten Rahn <rahn@kde.org>
4// SPDX-FileCopyrightText: 2007-2008 Inge Wallin <ingwa@kde.org>
5//
6
7
8// Local
10
11// Marble
12#include "ViewportParams.h"
13#include "GeoDataLatLonAltBox.h"
14
15#include "MarbleDebug.h"
16
17#include <QIcon>
18
19using namespace Marble;
20
21
24{
25 setMinLat( minValidLat() );
26 setMaxLat( maxValidLat() );
27}
28
29EquirectProjection::~EquirectProjection()
30{
31}
32
34{
35 return QObject::tr( "Flat Map" );
36}
37
39{
40 return QObject::tr( "<p><b>Equirectangular Projection</b> (\"Plate carrée\")</p><p>Applications: De facto standard for global texture data sets for computer software.</p>" );
41}
42
44{
45 return QIcon(QStringLiteral(":/icons/map-flat.png"));
46}
47
49 const ViewportParams *viewport,
50 qreal &x, qreal &y, bool &globeHidesPoint ) const
51{
52 globeHidesPoint = false;
53
54 // Convenience variables
55 int radius = viewport->radius();
56 int width = viewport->width();
57 int height = viewport->height();
58
59 qreal lon;
60 qreal lat;
61 qreal rad2Pixel = 2.0 * viewport->radius() / M_PI;
62
63 const qreal centerLon = viewport->centerLongitude();
64 const qreal centerLat = viewport->centerLatitude();
65
66 geopoint.geoCoordinates( lon, lat );
67
68 // Let (x, y) be the position on the screen of the geopoint.
69 x = ((qreal)(viewport->width()) / 2.0 + rad2Pixel * (lon - centerLon));
70 y = ((qreal)(viewport->height()) / 2.0 - rad2Pixel * (lat - centerLat));
71
72 // Return true if the calculated point is inside the screen area,
73 // otherwise return false.
74 return ( ( 0 <= y && y < height )
75 && ( ( 0 <= x && x < width )
76 || ( 0 <= x - 4 * radius && x - 4 * radius < width )
77 || ( 0 <= x + 4 * radius && x + 4 * radius < width ) ) );
78}
79
81 const ViewportParams *viewport,
82 qreal *x, qreal &y,
83 int &pointRepeatNum,
84 const QSizeF& size,
85 bool &globeHidesPoint ) const
86{
87 pointRepeatNum = 0;
88 // On flat projections the observer's view onto the point won't be
89 // obscured by the target planet itself.
90 globeHidesPoint = false;
91
92 // Convenience variables
93 int radius = viewport->radius();
94 qreal width = (qreal)(viewport->width());
95 qreal height = (qreal)(viewport->height());
96
97 // Let (itX, y) be the first guess for one possible position on screen.
98 qreal itX;
99 screenCoordinates( coordinates, viewport, itX, y);
100
101 // Make sure that the requested point is within the visible y range:
102 if ( 0 <= y + size.height() / 2.0 && y < height + size.height() / 2.0 ) {
103 // For the repetition case the same geopoint gets displayed on
104 // the map many times.across the longitude.
105
106 int xRepeatDistance = 4 * radius;
107
108 // Finding the leftmost positive x value
109 if ( itX + size.width() > xRepeatDistance ) {
110 const int repeatNum = (int)( ( itX + size.width() ) / xRepeatDistance );
111 itX = itX - repeatNum * xRepeatDistance;
112 }
113 if ( itX + size.width() / 2.0 < 0 ) {
114 itX += xRepeatDistance;
115 }
116 // The requested point is out of the visible x range:
117 if ( itX > width + size.width() / 2.0 ) {
118 return false;
119 }
120
121 // Now iterate through all visible x screen coordinates for the point
122 // from left to right.
123 int itNum = 0;
124 while ( itX - size.width() / 2.0 < width ) {
125 *x = itX;
126 ++x;
127 ++itNum;
128 itX += xRepeatDistance;
129 }
130
131 pointRepeatNum = itNum;
132
133 return true;
134 }
135
136 // The requested point is out of the visible y range.
137 return false;
138}
139
140
141bool EquirectProjection::geoCoordinates( const int x, const int y,
142 const ViewportParams *viewport,
143 qreal& lon, qreal& lat,
144 GeoDataCoordinates::Unit unit ) const
145{
146 const int radius = viewport->radius();
147 const qreal pixel2Rad = M_PI / (2.0 * radius);
148
149 // Get the Lat and Lon of the center point of the screen.
150 const qreal centerLon = viewport->centerLongitude();
151 const qreal centerLat = viewport->centerLatitude();
152
153 {
154 const int halfImageWidth = viewport->width() / 2;
155 const int xPixels = x - halfImageWidth;
156
157 lon = + xPixels * pixel2Rad + centerLon;
158
159 while ( lon > M_PI ) lon -= 2.0 * M_PI;
160 while ( lon < -M_PI ) lon += 2.0 * M_PI;
161
162 if ( unit == GeoDataCoordinates::Degree ) {
163 lon *= RAD2DEG;
164 }
165 }
166
167 {
168 // Get yTop and yBottom, the limits of the map on the screen.
169 const int halfImageHeight = viewport->height() / 2;
170 const int yCenterOffset = (int)( centerLat * (qreal)(2 * radius) / M_PI);
171 const int yTop = halfImageHeight - radius + yCenterOffset;
172 const int yBottom = yTop + 2 * radius;
173
174 // Return here if the y coordinate is outside the map
175 if ( yTop <= y && y < yBottom ) {
176 const int yPixels = y - halfImageHeight;
177 lat = - yPixels * pixel2Rad + centerLat;
178
179 if ( unit == GeoDataCoordinates::Degree ) {
180 lat *= RAD2DEG;
181 }
182
183 return true;
184 }
185 }
186
187 return false;
188}
189
191 const ViewportParams *viewport ) const
192{
193 qreal west;
194 qreal north = 90*DEG2RAD;
195 geoCoordinates( screenRect.left(), screenRect.top(), viewport, west, north, GeoDataCoordinates::Radian );
196
197 qreal east;
198 qreal south = -90*DEG2RAD;
199 geoCoordinates( screenRect.right(), screenRect.bottom(), viewport, east, south, GeoDataCoordinates::Radian );
200
201 // For the case where the whole viewport gets covered there is a
202 // pretty dirty and generic detection algorithm:
204 latLonAltBox.setNorth( north, GeoDataCoordinates::Radian );
205 latLonAltBox.setSouth( south, GeoDataCoordinates::Radian );
206 latLonAltBox.setWest( west, GeoDataCoordinates::Radian );
207 latLonAltBox.setEast( east, GeoDataCoordinates::Radian );
208 latLonAltBox.setMinAltitude( -100000000.0 );
209 latLonAltBox.setMaxAltitude( 100000000000000.0 );
210
211 // Convenience variables
212 int radius = viewport->radius();
213 int width = viewport->width();
214
215 // The remaining algorithm should be pretty generic for all kinds of
216 // flat projections:
217
218 int xRepeatDistance = 4 * radius;
219 if ( width >= xRepeatDistance ) {
220 latLonAltBox.setWest( -M_PI );
221 latLonAltBox.setEast( +M_PI );
222 }
223
224 // Now we need to check whether maxLat (e.g. the north pole) gets displayed
225 // inside the viewport.
226
227 // We need a point on the screen at maxLat that definitely gets displayed:
228 qreal averageLongitude = latLonAltBox.east();
229
230 GeoDataCoordinates maxLatPoint( averageLongitude, maxLat(), 0.0, GeoDataCoordinates::Radian );
231 GeoDataCoordinates minLatPoint( averageLongitude, minLat(), 0.0, GeoDataCoordinates::Radian );
232
233 qreal dummyX, dummyY; // not needed
234
235 if ( screenCoordinates( maxLatPoint, viewport, dummyX, dummyY ) ) {
236 latLonAltBox.setEast( +M_PI );
237 latLonAltBox.setWest( -M_PI );
238 }
239 if ( screenCoordinates( minLatPoint, viewport, dummyX, dummyY ) ) {
240 latLonAltBox.setEast( +M_PI );
241 latLonAltBox.setWest( -M_PI );
242 }
243
244 return latLonAltBox;
245}
246
247
249{
250 // Convenience variables
251 int radius = viewport->radius();
252 //int width = viewport->width();
253 int height = viewport->height();
254 int halfImageHeight = viewport->height() / 2;
255
256 // Get the Lat and Lon of the center point of the screen.
257 const qreal centerLat = viewport->centerLatitude();
258
259 // Calculate how many pixel are being represented per radians.
260 const float rad2Pixel = (qreal)( 2 * radius )/M_PI;
261
262 // Get yTop and yBottom, the limits of the map on the screen.
263 int yCenterOffset = (int)( centerLat * rad2Pixel );
264 int yTop = halfImageHeight - radius + yCenterOffset;
265 int yBottom = yTop + 2 * radius;
266
267 return !(yTop >= 0 || yBottom < height);
268}
This file contains the headers for EquirectProjection.
This file contains the headers for ViewportParams.
qreal minLat() const
Returns the arbitrarily chosen minimum (southern) latitude.
qreal maxLat() const
Returns the arbitrarily chosen maximum (northern) latitude.
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 Equirectangular and Mercator projections in Marble.
bool mapCoversViewport(const ViewportParams *viewport) const override
Returns whether the projected data fully obstructs the current viewport.
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.
GeoDataLatLonAltBox latLonAltBox(const QRect &screenRect, const ViewportParams *viewport) const override
Returns a GeoDataLatLonAltBox bounding box of the given screenrect inside the given viewport.
QIcon icon() const override
Returns an icon for the projection.
QString description() const override
Returns a short user description of the projection that can be used in tooltips or dialogs.
QString name() const override
Returns the user-visible name of 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.
EquirectProjection()
Construct a new EquirectProjection.
A 3d point representation.
Unit
enum used constructor to specify the units used
void geoCoordinates(qreal &lon, qreal &lat, GeoDataCoordinates::Unit unit) const
use this function to get the longitude and latitude with one call - use the unit parameter to switch ...
A class that defines a 3D bounding box for geographic data.
qreal east(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the eastern boundary of the bounding box.
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)
int bottom() const const
int left() const const
int right() const const
int top() const const
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 Tue Mar 26 2024 11:18:17 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.