Marble

GeoDataLatLonAltBox.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2007 Andrew Manson <[email protected]>
4 // SPDX-FileCopyrightText: 2008 Torsten Rahn <[email protected]>
5 //
6 
7 
8 #include "GeoDataLatLonAltBox.h"
9 
10 #include "MarbleDebug.h"
11 #include "GeoDataCoordinates.h"
12 #include "GeoDataLineString.h"
13 
14 #include "GeoDataTypes.h"
15 
16 #include <QDataStream>
17 
18 namespace Marble
19 {
20 
21 class GeoDataLatLonAltBoxPrivate
22 {
23  public:
24  GeoDataLatLonAltBoxPrivate()
25  : m_minAltitude( 0 ),
26  m_maxAltitude( 0 ),
27  m_altitudeMode( ClampToGround )
28  {
29  }
30 
31  qreal m_minAltitude;
32  qreal m_maxAltitude;
33  AltitudeMode m_altitudeMode;
34 };
35 
36 bool operator==( GeoDataLatLonAltBox const& lhs, GeoDataLatLonAltBox const& rhs )
37 {
38  return lhs.west() == rhs.west() &&
39  lhs.east() == rhs.east() &&
40  lhs.north() == rhs.north() &&
41  lhs.south() == rhs.south() &&
42  lhs.rotation() == rhs.rotation() &&
43  lhs.d->m_minAltitude == rhs.d->m_minAltitude &&
44  lhs.d->m_maxAltitude == rhs.d->m_maxAltitude &&
45  lhs.d->m_altitudeMode == rhs.d->m_altitudeMode;
46 }
47 
48 GeoDataLatLonAltBox& GeoDataLatLonAltBox::operator=( const GeoDataLatLonAltBox &other )
49 {
50  GeoDataLatLonBox::operator=( other );
51 
52  *d = *other.d;
53  return *this;
54 }
55 
56 GeoDataLatLonAltBox& GeoDataLatLonAltBox::operator=( const GeoDataCoordinates &other )
57 {
58  setWest( other.longitude() );
59  setEast( other.longitude() );
60  setNorth( other.latitude() );
61  setSouth( other.latitude() );
62  setMinAltitude( other.altitude() );
63  setMaxAltitude( other.altitude() );
64  return *this;
65 }
66 
67 GeoDataLatLonAltBox::GeoDataLatLonAltBox()
68  : GeoDataLatLonBox(),
69  d( new GeoDataLatLonAltBoxPrivate )
70 {
71 }
72 
73 GeoDataLatLonAltBox::GeoDataLatLonAltBox( const GeoDataLatLonAltBox & other )
74  : GeoDataLatLonBox( other ),
75  d( new GeoDataLatLonAltBoxPrivate( *other.d ))
76 {
77 }
78 
79 GeoDataLatLonAltBox::GeoDataLatLonAltBox( const GeoDataLatLonBox &other, qreal minAltitude, qreal maxAltitude )
80  : GeoDataLatLonBox( other ),
81  d( new GeoDataLatLonAltBoxPrivate )
82 {
83  setWest( other.west() );
84  setEast( other.east() );
85  setNorth( other.north() );
86  setSouth( other.south() );
87  setRotation( other.rotation() );
88 
89  d->m_minAltitude = minAltitude;
90  d->m_maxAltitude = maxAltitude;
91 }
92 
93 
94 GeoDataLatLonAltBox::GeoDataLatLonAltBox( const GeoDataCoordinates & coordinates )
95  : GeoDataLatLonBox(),
96  d( new GeoDataLatLonAltBoxPrivate )
97 {
98  setWest( coordinates.longitude() );
99  setEast( coordinates.longitude() );
100  setNorth( coordinates.latitude() );
101  setSouth( coordinates.latitude() );
102 
103  d->m_minAltitude = coordinates.altitude();
104  d->m_maxAltitude = coordinates.altitude();
105 }
106 
107 
108 GeoDataLatLonAltBox::~GeoDataLatLonAltBox()
109 {
110  delete d;
111 }
112 
113 const char* GeoDataLatLonAltBox::nodeType() const
114 {
115  return GeoDataTypes::GeoDataLatLonAltBoxType;
116 }
117 
119 {
120  return d->m_minAltitude;
121 }
122 
123 void GeoDataLatLonAltBox::setMinAltitude( const qreal minAltitude )
124 {
125  d->m_minAltitude = minAltitude;
126 }
127 
129 {
130  return d->m_maxAltitude;
131 }
132 
133 void GeoDataLatLonAltBox::setMaxAltitude( const qreal maxAltitude )
134 {
135  d->m_maxAltitude = maxAltitude;
136 }
137 
139 {
140  return d->m_altitudeMode;
141 }
142 
144 {
145  if ( isEmpty() )
146  return GeoDataCoordinates();
147  if( crossesDateLine() )
148  return GeoDataCoordinates( GeoDataCoordinates::normalizeLon(east() + 2 * M_PI - (east() + 2 * M_PI - west()) / 2),
149  north() - (north() - south()) / 2,
150  d->m_maxAltitude - (d->m_maxAltitude - d->m_minAltitude) / 2);
151  else
152  return GeoDataCoordinates( east() - (east() - west()) / 2,
153  north() - (north() - south()) / 2,
154  d->m_maxAltitude - (d->m_maxAltitude - d->m_minAltitude) / 2);
155 }
156 
157 void GeoDataLatLonAltBox::setAltitudeMode( const AltitudeMode altitudeMode )
158 {
159  d->m_altitudeMode = altitudeMode;
160 }
161 
162 bool GeoDataLatLonAltBox::contains( const GeoDataCoordinates &point ) const
163 {
164  if ( !GeoDataLatLonBox::contains( point ) )
165  return false;
166 
167  if ( point.altitude() < d->m_minAltitude || point.altitude() > d->m_maxAltitude ) {
168  return false;
169  }
170 
171  return true;
172 }
173 
174 bool GeoDataLatLonAltBox::contains( const GeoDataLatLonAltBox &other ) const
175 {
176  // check the contain criterion for the altitude first as this is trivial:
177 
178  // mDebug() << "this " << this->toString(GeoDataCoordinates::Degree);
179  // mDebug() << "other" << other.toString(GeoDataCoordinates::Degree);
180 
181  if ( d->m_maxAltitude >= other.maxAltitude() && d->m_minAltitude <= other.minAltitude() ) {
182  return GeoDataLatLonBox::contains( other );
183  }
184 
185  return false;
186 }
187 
189 {
190  // Case 1: maximum altitude of other box intersects:
191  if ( ( d->m_maxAltitude >= other.maxAltitude() && d->m_minAltitude <= other.maxAltitude() )
192  // Case 2: maximum altitude of this box intersects:
193  || ( other.maxAltitude() >= d->m_maxAltitude && other.minAltitude() <= d->m_maxAltitude )
194  // Case 3: minimum altitude of other box intersects:
195  || ( d->m_maxAltitude >= other.minAltitude() && d->m_minAltitude <= other.minAltitude() )
196  // Case 4: minimum altitude of this box intersects:
197  || ( other.maxAltitude() >= d->m_minAltitude && other.minAltitude() <= d->m_minAltitude ) ) {
198 
199  if ( GeoDataLatLonBox::intersects( other ) )
200  return true;
201 
202  }
203 
204  return false;
205 }
206 
208 {
209  // If the line string is empty return a boundingbox that contains everything
210  if ( lineString.size() == 0 ) {
211  return GeoDataLatLonAltBox();
212  }
213 
214  const qreal altitude = lineString.first().altitude();
215 
216  GeoDataLatLonAltBox temp ( GeoDataLatLonBox::fromLineString( lineString ), altitude, altitude );
217 
218  qreal maxAltitude = altitude;
219  qreal minAltitude = altitude;
220 
221  // If there's only a single node stored then the boundingbox only contains that point
222  if ( lineString.size() == 1 ) {
223  temp.setMinAltitude( minAltitude );
224  temp.setMaxAltitude( maxAltitude );
225  return temp;
226  }
227 
230 
231  for ( ; it != itEnd; ++it )
232  {
233  // Get coordinates and normalize them to the desired range.
234  const qreal altitude = (it)->altitude();
235 
236  // Determining the maximum and minimum altitude
237  if ( altitude > maxAltitude ) {
238  maxAltitude = altitude;
239  } else if ( altitude < minAltitude ) {
240  minAltitude = altitude;
241  }
242  }
243 
244  temp.setMinAltitude( minAltitude );
245  temp.setMaxAltitude( maxAltitude );
246  return temp;
247 }
248 
250 {
251  return GeoDataLatLonBox::isNull() && d->m_maxAltitude == d->m_minAltitude;
252 }
253 
255 {
257  d->m_minAltitude = 0;
258  d->m_maxAltitude = 0;
259  d->m_altitudeMode = ClampToGround;
260 }
261 
263 {
264  GeoDataObject::pack( stream );
265 
266  stream << d->m_minAltitude << d->m_maxAltitude;
267  stream << d->m_altitudeMode;
268 }
269 
271 {
272  GeoDataObject::unpack( stream );
273 
274  stream >> d->m_minAltitude >> d->m_maxAltitude;
275  int a;
276  stream >> a;
277  d->m_altitudeMode = static_cast<AltitudeMode>( a );
278 }
279 
280 uint qHash(const GeoDataLatLonAltBox &box, uint seed)
281 {
282  seed = ::qHash(box.east(), seed);
283  seed = ::qHash(box.west(), seed);
284  seed = ::qHash(box.south(), seed);
285  seed = ::qHash(box.north(), seed);
286  seed = ::qHash(box.maxAltitude(), seed);
287 
288  return ::qHash(box.minAltitude(), seed);
289 }
290 
291 }
bool crossesDateLine() const
Detect whether the bounding box crosses the IDL.
A 3d point representation.
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.
virtual bool isNull() const
Indicates whether the bounding box only contains a single 2D point ("singularity").
qreal longitude(GeoDataCoordinates::Unit unit) const
retrieves the longitude of the GeoDataCoordinates object use the unit parameter to switch between Rad...
qreal north(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the northern boundary of the bounding box.
QVector< GeoDataCoordinates >::ConstIterator constBegin() const
Returns a const iterator that points to the begin of the LineString.
bool operator==(const Qt3DRender::QGraphicsApiFilter &reference, const Qt3DRender::QGraphicsApiFilter &sample)
A LineString that allows to store a contiguous set of line segments.
virtual bool isEmpty() const
Indicates whether the bounding box is not initialised (and contains nothing).
qreal altitude() const
return the altitude of the Point in meters
qreal west(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the western boundary of the bounding box.
qreal latitude(GeoDataCoordinates::Unit unit) const
retrieves the latitude of the GeoDataCoordinates object use the unit parameter to switch between Radi...
QVector< GeoDataCoordinates >::ConstIterator constEnd() const
Returns a const iterator that points to the end of the LineString.
A class that defines a 2D bounding box for geographic data.
void pack(QDataStream &stream) const override
Reimplemented from Serializable.
KCALENDARCORE_EXPORT uint qHash(const KCalendarCore::Period &key)
Binds a QML item to a specific geodetic location in screen coordinates.
GeoDataCoordinates & first()
Returns a reference to the first node in the LineString. This method detaches the returned coordinate...
AltitudeMode altitudeMode() const
Get the reference system for the altitude.
GeoDataCoordinates center() const override
returns the center of this box
bool isNull() const override
Indicates whether the bounding box only contains a single 2D point ("singularity").
qreal south(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the southern boundary of the bounding box.
const char * nodeType() const override
Provides type information for downcasting a GeoData.
qreal minAltitude() const
Get the lower altitude boundary of the bounding box.
qreal maxAltitude() const
Get the upper altitude boundary of the bounding box.
@ ClampToGround
Altitude always sticks to ground level.
Definition: MarbleGlobal.h:132
static GeoDataLatLonBox fromLineString(const GeoDataLineString &lineString)
Create the smallest bounding box from a line string.
static GeoDataLatLonAltBox fromLineString(const GeoDataLineString &lineString)
Create the smallest bounding box from a line string.
void pack(QDataStream &stream) const override
Serialize the contents of the feature to stream.
virtual bool intersects(const GeoDataLatLonAltBox &) const
Check if this GeoDataLatLonAltBox intersects with the given one.
void unpack(QDataStream &steam) override
Reimplemented from Serializable.
static qreal normalizeLon(qreal lon, GeoDataCoordinates::Unit=GeoDataCoordinates::Radian)
normalize the longitude to always be -M_PI <= lon <= +M_PI (Radian).
void clear() override
Resets the bounding box to its uninitialised state (and thus contains nothing).
void unpack(QDataStream &stream) override
Unserialize the contents of the feature from stream.
int size() const
Returns the number of nodes in a LineString.
virtual void clear()
Resets the bounding box to its uninitialised state (and thus contains nothing).
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Oct 2 2023 03:52:08 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.