Marble

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

KDE's Doxygen guidelines are available online.