Marble

AbstractProjection.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
4// SPDX-FileCopyrightText: 2007-2012 Torsten Rahn <rahn@kde.org>
5// SPDX-FileCopyrightText: 2012 Cezar Mocan <mocancezar@gmail.com>
6//
7
8// Local
10
11#include "AbstractProjection_p.h"
12
13#include "MarbleDebug.h"
14#include <QRegion>
15#include <QPainterPath>
16
17// Marble
18#include "GeoDataLineString.h"
19#include "GeoDataLinearRing.h"
20#include "GeoDataLatLonAltBox.h"
21#include "ViewportParams.h"
22
23using namespace Marble;
24
26 : d_ptr( new AbstractProjectionPrivate( this ) )
27{
28}
29
30AbstractProjection::AbstractProjection( AbstractProjectionPrivate* dd )
31 : d_ptr( dd )
32{
33}
34
35AbstractProjection::~AbstractProjection()
36{
37}
38
39AbstractProjectionPrivate::AbstractProjectionPrivate( AbstractProjection * parent )
40 : m_maxLat(0),
41 m_minLat(0),
42 m_previousResolution(-1),
43 m_level(-1),
44 q_ptr( parent)
45{
46}
47
48int AbstractProjectionPrivate::levelForResolution(qreal resolution) const {
49 if (m_previousResolution == resolution) return m_level;
50
51 m_previousResolution = resolution;
52
53 if (resolution < 0.0000005) m_level = 17;
54 else if (resolution < 0.0000010) m_level = 16;
55 else if (resolution < 0.0000020) m_level = 15;
56 else if (resolution < 0.0000040) m_level = 14;
57 else if (resolution < 0.0000080) m_level = 13;
58 else if (resolution < 0.0000160) m_level = 12;
59 else if (resolution < 0.0000320) m_level = 11;
60 else if (resolution < 0.0000640) m_level = 10;
61 else if (resolution < 0.0001280) m_level = 9;
62 else if (resolution < 0.0002560) m_level = 8;
63 else if (resolution < 0.0005120) m_level = 7;
64 else if (resolution < 0.0010240) m_level = 6;
65 else if (resolution < 0.0020480) m_level = 5;
66 else if (resolution < 0.0040960) m_level = 4;
67 else if (resolution < 0.0081920) m_level = 3;
68 else if (resolution < 0.0163840) m_level = 2;
69 else m_level = 1;
70
71 return m_level;
72}
73
75{
76 return +90.0 * DEG2RAD;
77}
78
80{
81 Q_D(const AbstractProjection );
82 return d->m_maxLat;
83}
84
85void AbstractProjection::setMaxLat( qreal maxLat )
86{
87 if ( maxLat < maxValidLat() ) {
88 mDebug() << "Trying to set maxLat to a value that is out of the valid range.";
89 return;
90 }
91
93 d->m_maxLat = maxLat;
94}
95
97{
98 return -90.0 * DEG2RAD;
99}
100
102{
103 Q_D( const AbstractProjection );
104 return d->m_minLat;
105}
106
107void AbstractProjection::setMinLat( qreal minLat )
108{
109 if ( minLat < minValidLat() ) {
110 mDebug() << "Trying to set minLat to a value that is out of the valid range.";
111 return;
112 }
113
115 d->m_minLat = minLat;
116}
117
119{
120 return false;
121}
122
124{
125 return false;
126}
127
128bool AbstractProjection::traversableDateLine() const
129{
130 return false;
131}
132
133AbstractProjection::PreservationType AbstractProjection::preservationType() const
134{
135 return NoPreservation;
136}
137
138bool AbstractProjection::isOrientedNormal() const
139{
140 return true;
141}
142
144{
145 return false;
146}
147
148qreal AbstractProjection::clippingRadius() const
149{
150 return 0;
151}
152
153
154bool AbstractProjection::screenCoordinates( const qreal lon, const qreal lat,
155 const ViewportParams *viewport,
156 qreal &x, qreal &y ) const
157{
158 bool globeHidesPoint;
159 GeoDataCoordinates geopoint(lon, lat);
160 return screenCoordinates( geopoint, viewport, x, y, globeHidesPoint );
161}
162
164 const ViewportParams *viewport,
165 qreal &x, qreal &y ) const
166{
167 bool globeHidesPoint;
168
169 return screenCoordinates( geopoint, viewport, x, y, globeHidesPoint );
170}
173 const ViewportParams *viewport ) const
174{
175 // For the case where the whole viewport gets covered there is a
176 // pretty dirty and generic detection algorithm:
177
178 // Move along the screenborder and save the highest and lowest lon-lat values.
179 QRect projectedRect = mapRegion( viewport ).boundingRect();
180 QRect mapRect = screenRect.intersected( projectedRect );
181
182 GeoDataLineString boundingLineString;
183
184 qreal lon, lat;
185
186 for ( int x = mapRect.left(); x < mapRect.right(); x += latLonAltBoxSamplingRate ) {
187 if ( geoCoordinates( x, mapRect.bottom(), viewport, lon, lat,
188 GeoDataCoordinates::Radian ) ) {
189 boundingLineString << GeoDataCoordinates( lon, lat );
190 }
191
192 if ( geoCoordinates( x, mapRect.top(),
193 viewport, lon, lat, GeoDataCoordinates::Radian ) ) {
194 boundingLineString << GeoDataCoordinates( lon, lat );
195 }
196 }
197
198 if ( geoCoordinates( mapRect.right(), mapRect.top(), viewport, lon, lat,
199 GeoDataCoordinates::Radian ) ) {
200 boundingLineString << GeoDataCoordinates( lon, lat );
201 }
202
203 if ( geoCoordinates( mapRect.right(), mapRect.bottom(),
204 viewport, lon, lat, GeoDataCoordinates::Radian ) ) {
205 boundingLineString << GeoDataCoordinates( lon, lat );
206 }
207
208 for ( int y = mapRect.bottom(); y < mapRect.top(); y += latLonAltBoxSamplingRate ) {
209 if ( geoCoordinates( mapRect.left(), y, viewport, lon, lat,
210 GeoDataCoordinates::Radian ) ) {
211 boundingLineString << GeoDataCoordinates( lon, lat );
212 }
213
214 if ( geoCoordinates( mapRect.right(), y,
215 viewport, lon, lat, GeoDataCoordinates::Radian ) ) {
216 boundingLineString << GeoDataCoordinates( lon, lat );
217 }
218 }
219
220 GeoDataLatLonAltBox latLonAltBox = boundingLineString.latLonAltBox();
221
222 // Now we need to check whether maxLat (e.g. the north pole) gets displayed
223 // inside the viewport.
224
225 // We need a point on the screen at maxLat that definitely gets displayed:
226
227 // FIXME: Some of the following code can be safely removed as soon as we properly handle
228 // GeoDataLinearRing::latLonAltBox().
229 qreal averageLongitude = ( latLonAltBox.west() + latLonAltBox.east() ) / 2.0;
230
231 GeoDataCoordinates maxLatPoint( averageLongitude, maxLat(), 0.0, GeoDataCoordinates::Radian );
232 GeoDataCoordinates minLatPoint( averageLongitude, minLat(), 0.0, GeoDataCoordinates::Radian );
233
234 qreal dummyX, dummyY; // not needed
235
236 if ( latLonAltBox.north() > maxLat() ||
237 screenCoordinates( maxLatPoint, viewport, dummyX, dummyY ) ) {
238 latLonAltBox.setNorth( maxLat() );
239 }
240 if ( latLonAltBox.north() < minLat() ||
241 screenCoordinates( minLatPoint, viewport, dummyX, dummyY ) ) {
242 latLonAltBox.setSouth( minLat() );
243 }
244
245 latLonAltBox.setMinAltitude( -100000000.0 );
246 latLonAltBox.setMaxAltitude( 100000000000000.0 );
247
248 return latLonAltBox;
249}
250
251
252QRegion AbstractProjection::mapRegion( const ViewportParams *viewport ) const
253{
254 return QRegion( mapShape( viewport ).toFillPolygon().toPolygon() );
255}
This file contains the headers for AbstractProjection.
This file contains the headers for ViewportParams.
A base class for all projections in Marble.
qreal minLat() const
Returns the arbitrarily chosen minimum (southern) latitude.
bool screenCoordinates(const qreal lon, const qreal lat, const ViewportParams *viewport, qreal &x, qreal &y) const
Get the screen coordinates corresponding to geographical coordinates in the map.
qreal maxLat() const
Returns the arbitrarily chosen maximum (northern) latitude.
virtual bool geoCoordinates(const int x, const int y, const ViewportParams *viewport, qreal &lon, qreal &lat, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Degree) const =0
Get the earth coordinates corresponding to a pixel in the map.
virtual QPainterPath mapShape(const ViewportParams *viewport) const =0
Returns the shape/outline of a map projection.
virtual bool traversablePoles() const
Returns whether the projection allows to navigate seamlessly "over" the pole.
virtual qreal maxValidLat() const
Returns the maximum (northern) latitude that is mathematically defined and reasonable.
virtual bool isClippedToSphere() const
Defines whether a projection is supposed to be clipped to a certain radius.
virtual bool repeatableX() const
Returns whether the projection allows for wrapping in x direction (along the longitude scale).
virtual GeoDataLatLonAltBox latLonAltBox(const QRect &screenRect, const ViewportParams *viewport) const
Returns a GeoDataLatLonAltBox bounding box of the given screenrect inside the given viewport.
AbstractProjection()
Construct a new AbstractProjection.
virtual qreal minValidLat() const
Returns the minimum (southern) latitude that is mathematically defined and reasonable.
A 3d point representation.
A class that defines a 3D bounding box for geographic data.
qreal north(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the northern boundary of the bounding box.
qreal east(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the eastern boundary of the bounding box.
qreal west(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the western boundary of the bounding box.
A LineString that allows to store a contiguous set of line segments.
const GeoDataLatLonAltBox & latLonAltBox() const override
Returns the smallest latLonAltBox that contains the LineString.
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.
int bottom() const const
QRect intersected(const QRect &rectangle) const const
int left() const const
int right() const const
int top() const const
QRect boundingRect() const const
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 31 2024 17:23:59 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.