• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.14
  • kdeedu
  • marble
  • src
  • lib
  • marble
  • projections
MercatorProjection.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2007-2008 Inge Wallin <ingwa@kde.org>
9 // Copyright 2007-2012 Torsten Rahn <rahn@kde.org>
10 //
11 
12 
13 // Local
14 #include "MercatorProjection.h"
15 
16 #include "MarbleDebug.h"
17 
18 // Marble
19 #include "ViewportParams.h"
20 
21 #include "MathHelper.h"
22 #include "GeoDataPoint.h"
23 #include "MarbleMath.h"
24 
25 using namespace Marble;
26 
27 MercatorProjection::MercatorProjection()
28  : CylindricalProjection()
29 {
30  setMinLat( minValidLat() );
31  setMaxLat( maxValidLat() );
32 }
33 
34 MercatorProjection::~MercatorProjection()
35 {
36 }
37 
38 qreal MercatorProjection::maxValidLat() const
39 {
40  // This is the max value where atanh( sin( lat ) ) is defined.
41  return +85.05113 * DEG2RAD;
42 }
43 
44 qreal MercatorProjection::minValidLat() const
45 {
46  // This is the min value where atanh( sin( lat ) ) is defined.
47  return -85.05113 * DEG2RAD;
48 }
49 
50 bool MercatorProjection::screenCoordinates( const GeoDataCoordinates &geopoint,
51  const ViewportParams *viewport,
52  qreal &x, qreal &y, bool &globeHidesPoint ) const
53 {
54  globeHidesPoint = false;
55  qreal lon;
56  qreal lat;
57 
58  geopoint.geoCoordinates( lon, lat );
59 
60  const bool isLatValid = minLat() <= lat && lat <= maxLat();
61 
62  if ( lat > maxLat() ) {
63  GeoDataCoordinates approxCoords( geopoint );
64  approxCoords.setLatitude( maxLat() );
65  approxCoords.geoCoordinates( lon, lat );
66  }
67 
68  if ( lat < minLat() ) {
69  GeoDataCoordinates approxCoords( geopoint );
70  approxCoords.setLatitude( minLat() );
71  approxCoords.geoCoordinates( lon, lat );
72  }
73 
74  // Convenience variables
75  int radius = viewport->radius();
76  qreal width = (qreal)(viewport->width());
77  qreal height = (qreal)(viewport->height());
78 
79  qreal rad2Pixel = 2 * radius / M_PI;
80 
81  const qreal centerLon = viewport->centerLongitude();
82  const qreal centerLat = viewport->centerLatitude();
83 
84  // Let (x, y) be the position on the screen of the placemark..
85  x = ( width / 2 + rad2Pixel * ( lon - centerLon ) );
86  y = ( height / 2 - rad2Pixel * ( gdInv( lat ) - gdInv( centerLat ) ) );
87 
88  // Return true if the calculated point is inside the screen area,
89  // otherwise return false.
90  return isLatValid && ( ( 0 <= y && y < height )
91  && ( ( 0 <= x && x < width )
92  || ( 0 <= x - 4 * radius && x - 4 * radius < width )
93  || ( 0 <= x + 4 * radius && x + 4 * radius < width ) ) );
94 }
95 
96 bool MercatorProjection::screenCoordinates( const GeoDataCoordinates &coordinates,
97  const ViewportParams *viewport,
98  qreal *x, qreal &y, int &pointRepeatNum,
99  const QSizeF& size,
100  bool &globeHidesPoint ) const
101 {
102  pointRepeatNum = 0;
103  // On flat projections the observer's view onto the point won't be
104  // obscured by the target planet itself.
105  globeHidesPoint = false;
106 
107  // Convenience variables
108  int radius = viewport->radius();
109  qreal width = (qreal)(viewport->width());
110  qreal height = (qreal)(viewport->height());
111 
112  // Let (itX, y) be the first guess for one possible position on screen..
113  qreal itX;
114  bool visible = screenCoordinates( coordinates, viewport, itX, y);
115 
116  // Make sure that the requested point is within the visible y range:
117  if ( 0 <= y + size.height() / 2.0 && y < height + size.height() / 2.0 ) {
118  // For the repetition case the same geopoint gets displayed on
119  // the map many times.across the longitude.
120 
121  int xRepeatDistance = 4 * radius;
122 
123  // Finding the leftmost positive x value
124  if ( itX + size.width() / 2.0 >= xRepeatDistance ) {
125  const int repeatNum = (int)( ( itX + size.width() / 2.0 ) / xRepeatDistance );
126  itX = itX - repeatNum * xRepeatDistance;
127  }
128  if ( itX + size.width() / 2.0 < 0 ) {
129  itX += xRepeatDistance;
130  }
131  // the requested point is out of the visible x range:
132  if ( itX > width + size.width() / 2.0 ) {
133  return false;
134  }
135 
136  // Now iterate through all visible x screen coordinates for the point
137  // from left to right.
138  int itNum = 0;
139  while ( itX - size.width() / 2.0 < width ) {
140  *x = itX;
141  ++x;
142  ++itNum;
143  itX += xRepeatDistance;
144  }
145 
146  pointRepeatNum = itNum;
147 
148  return visible && true;
149  }
150 
151  // the requested point is out of the visible y range:
152  return false;
153 }
154 
155 
156 bool MercatorProjection::geoCoordinates( const int x, const int y,
157  const ViewportParams *viewport,
158  qreal& lon, qreal& lat,
159  GeoDataCoordinates::Unit unit ) const
160 {
161  const int radius = viewport->radius();
162  Q_ASSERT( radius > 0 );
163 
164  // Calculate translation of center point
165  const qreal centerLon = viewport->centerLongitude();
166  const qreal centerLat = viewport->centerLatitude();
167 
168  // Calculate how many pixel are being represented per radians.
169  const float rad2Pixel = (qreal)( 2 * radius )/M_PI;
170  const qreal pixel2Rad = M_PI / (2 * radius);
171 
172  {
173  const int halfImageWidth = viewport->width() / 2;
174  const int xPixels = x - halfImageWidth;
175  lon = xPixels * pixel2Rad + centerLon;
176 
177  while ( lon > M_PI ) lon -= 2*M_PI;
178  while ( lon < -M_PI ) lon += 2*M_PI;
179 
180  if ( unit == GeoDataCoordinates::Degree ) {
181  lon *= RAD2DEG;
182  }
183  }
184 
185  {
186  const int halfImageHeight = viewport->height() / 2;
187  const int yCenterOffset = (int)( asinh( tan( centerLat ) ) * rad2Pixel );
188  const int yTop = halfImageHeight - 2 * radius + yCenterOffset;
189  const int yBottom = yTop + 4 * radius;
190  if ( y >= yTop && y < yBottom ) {
191  lat = atan( sinh( ( ( halfImageHeight + yCenterOffset ) - y)
192  * pixel2Rad ) );
193 
194  if ( unit == GeoDataCoordinates::Degree ) {
195  lat *= RAD2DEG;
196  }
197 
198  return true; // lat successfully calculated
199  }
200  }
201 
202  return false; // lat unchanged
203 }
204 
205 
206 GeoDataLatLonAltBox MercatorProjection::latLonAltBox( const QRect& screenRect,
207  const ViewportParams *viewport ) const
208 {
209  qreal west;
210  qreal north = 85*DEG2RAD;
211  geoCoordinates( screenRect.left(), screenRect.top(), viewport, west, north, GeoDataCoordinates::Radian );
212 
213  qreal east;
214  qreal south = -85*DEG2RAD;
215  geoCoordinates( screenRect.right(), screenRect.bottom(), viewport, east, south, GeoDataCoordinates::Radian );
216 
217  // For the case where the whole viewport gets covered there is a
218  // pretty dirty and generic detection algorithm:
219  GeoDataLatLonAltBox latLonAltBox;
220  latLonAltBox.setNorth( north, GeoDataCoordinates::Radian );
221  latLonAltBox.setSouth( south, GeoDataCoordinates::Radian );
222  latLonAltBox.setWest( west, GeoDataCoordinates::Radian );
223  latLonAltBox.setEast( east, GeoDataCoordinates::Radian );
224  latLonAltBox.setMinAltitude( -100000000.0 );
225  latLonAltBox.setMaxAltitude( 100000000000000.0 );
226 
227  // The remaining algorithm should be pretty generic for all kinds of
228  // flat projections:
229 
230  // If the whole globe is visible we can easily calculate
231  // analytically the lon-/lat- range.
232  // qreal pitch = GeoDataPoint::normalizeLat( viewport->planetAxis().pitch() );
233 
234  int xRepeatDistance = 4 * viewport->radius();
235  if ( viewport->width() >= xRepeatDistance ) {
236  latLonAltBox.setWest( -M_PI );
237  latLonAltBox.setEast( +M_PI );
238  }
239 
240  return latLonAltBox;
241 }
242 
243 
244 bool MercatorProjection::mapCoversViewport( const ViewportParams *viewport ) const
245 {
246  int radius = viewport->radius();
247  int height = viewport->height();
248 
249  // Calculate translation of center point
250  const qreal centerLat = viewport->centerLatitude();
251 
252  // Calculate how many pixel are being represented per radians.
253  const float rad2Pixel = (float)( 2 * radius )/M_PI;
254 
255  int yCenterOffset = (int)( asinh( tan( centerLat ) ) * rad2Pixel );
256  int yTop = height / 2 - 2 * radius + yCenterOffset;
257  int yBottom = yTop + 4 * radius;
258 
259  if ( yTop >= 0 || yBottom < height )
260  return false;
261 
262  return true;
263 }
Marble::GeoDataCoordinates::Unit
Unit
enum used constructor to specify the units used
Definition: GeoDataCoordinates.h:64
Marble::RAD2DEG
const qreal RAD2DEG
Definition: MarbleGlobal.h:220
Marble::GeoDataCoordinates
A 3d point representation.
Definition: GeoDataCoordinates.h:52
Marble::gdInv
qreal gdInv(qreal x)
This method is a fast Mac Laurin power series approximation of the.
Definition: MarbleMath.h:96
Marble::GeoDataCoordinates::Radian
Definition: GeoDataCoordinates.h:65
Marble::GeoDataLatLonBox::setNorth
void setNorth(const qreal north, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
Definition: GeoDataLatLonBox.cpp:101
MarbleMath.h
QRect::right
int right() const
Marble::MercatorProjection::MercatorProjection
MercatorProjection()
Construct a new MercatorProjection.
Definition: MercatorProjection.cpp:27
MercatorProjection.h
This file contains the headers for MercatorProjection.
Marble::MercatorProjection::screenCoordinates
bool screenCoordinates(const GeoDataCoordinates &coordinates, const ViewportParams *params, qreal &x, qreal &y, bool &globeHidesPoint) const
Get the screen coordinates corresponding to geographical coordinates in the map.
Definition: MercatorProjection.cpp:50
Marble::MercatorProjection::mapCoversViewport
bool mapCoversViewport(const ViewportParams *viewport) const
Definition: MercatorProjection.cpp:244
Marble::AbstractProjection::maxLat
qreal maxLat() const
Definition: AbstractProjection.cpp:54
MarbleDebug.h
Marble::GeoDataCoordinates::Degree
Definition: GeoDataCoordinates.h:66
Marble::ViewportParams::height
int height() const
Definition: ViewportParams.cpp:255
QRect
Marble::CylindricalProjection
A base class for the Equirectangular and Mercator projections in Marble.
Definition: CylindricalProjection.h:33
Marble::GeoDataCoordinates::geoCoordinates
void geoCoordinates(qreal &lon, qreal &lat, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
use this function to get the longitude and latitude with one call - use the unit parameter to switch ...
Definition: GeoDataCoordinates.cpp:715
Marble::AbstractProjection::setMaxLat
void setMaxLat(qreal maxLat)
Definition: AbstractProjection.cpp:60
Marble::ViewportParams::width
int width() const
Definition: ViewportParams.cpp:250
QRect::top
int top() const
asinh
double asinh(double xval)
Definition: sgp4ext.cpp:211
MathHelper.h
QRect::left
int left() const
Marble::radius
static qreal radius(qreal zoom)
Definition: thumbnailer.cpp:99
Marble::DEG2RAD
const qreal DEG2RAD
Definition: MarbleGlobal.h:219
Marble::ViewportParams
A public class that controls what is visible in the viewport of a Marble map.
Definition: ViewportParams.h:44
Marble::GeoDataCoordinates::setLatitude
void setLatitude(qreal lat, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
set the longitude in a GeoDataCoordinates object
Definition: GeoDataCoordinates.cpp:699
ViewportParams.h
This file contains the headers for ViewportParams.
Marble::MercatorProjection::latLonAltBox
GeoDataLatLonAltBox latLonAltBox(const QRect &screenRect, const ViewportParams *viewport) const
Definition: MercatorProjection.cpp:206
Marble::ViewportParams::centerLatitude
qreal centerLatitude() const
Definition: ViewportParams.cpp:294
GeoDataPoint.h
QSizeF
Marble::ViewportParams::radius
int radius() const
Definition: ViewportParams.cpp:195
Marble::ViewportParams::centerLongitude
qreal centerLongitude() const
Definition: ViewportParams.cpp:289
Marble::MercatorProjection::~MercatorProjection
virtual ~MercatorProjection()
Definition: MercatorProjection.cpp:34
QRect::bottom
int bottom() const
M_PI
#define M_PI
Definition: GeoDataCoordinates.h:26
Marble::MercatorProjection::minValidLat
virtual qreal minValidLat() const
Definition: MercatorProjection.cpp:44
Marble::MercatorProjection::geoCoordinates
bool geoCoordinates(const int x, const int y, const ViewportParams *params, qreal &lon, qreal &lat, GeoDataCoordinates::Unit=GeoDataCoordinates::Degree) const
Get the earth coordinates corresponding to a pixel in the map.
Definition: MercatorProjection.cpp:156
QSizeF::height
qreal height() const
Marble::AbstractProjection::minLat
qreal minLat() const
Definition: AbstractProjection.cpp:76
Marble::GeoDataLatLonAltBox
A class that defines a 3D bounding box for geographic data.
Definition: GeoDataLatLonAltBox.h:49
Marble::AbstractProjection::setMinLat
void setMinLat(qreal minLat)
Definition: AbstractProjection.cpp:82
QSizeF::width
qreal width() const
Marble::MercatorProjection::maxValidLat
virtual qreal maxValidLat() const
Definition: MercatorProjection.cpp:38
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:40 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal