Marble

GeoDataPolygon.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2008-2009 Patrick Spendrin <ps_ml@gmx.de>
4// SPDX-FileCopyrightText: 2008 Inge Wallin <inge@lysator.liu.se>
5//
6
7#include "GeoDataPolygon.h"
8#include "GeoDataCoordinates.h"
9#include "GeoDataPolygon_p.h"
10#include "GeoDataTypes.h"
11#include "MarbleDebug.h"
12
13#include <QDataStream>
14#include <algorithm>
15
16namespace Marble
17{
18
20 : GeoDataGeometry(new GeoDataPolygonPrivate(f))
21{
22 // nothing to do
23}
24
26 : GeoDataGeometry(other)
27{
28 // nothing to do
29}
30
32{
33#ifdef DEBUG_GEODATA
34 mDebug() << "delete polygon";
35#endif
36}
37
38const char *GeoDataPolygon::nodeType() const
39{
40 return GeoDataTypes::GeoDataPolygonType;
41}
42
43EnumGeometryId GeoDataPolygon::geometryId() const
44{
45 return GeoDataPolygonId;
46}
47
48GeoDataGeometry *GeoDataPolygon::copy() const
49{
50 return new GeoDataPolygon(*this);
51}
52
54{
55 Q_D(const GeoDataPolygon);
56 const GeoDataPolygonPrivate *other_d = other.d_func();
57
58 if (!GeoDataGeometry::equals(other) || tessellate() != other.tessellate() || isClosed() != other.isClosed() || d->inner.size() != other_d->inner.size()
59 || d->outer != other_d->outer) {
60 return false;
61 }
62
63 QList<GeoDataLinearRing>::const_iterator itBound = d->inner.constBegin();
64 QList<GeoDataLinearRing>::const_iterator itEnd = d->inner.constEnd();
65 QList<GeoDataLinearRing>::const_iterator otherItBound = other_d->inner.constBegin();
66 QList<GeoDataLinearRing>::const_iterator otherItEnd = other_d->inner.constEnd();
67
68 for (; itBound != itEnd && otherItBound != otherItEnd; ++itBound, ++otherItBound) {
69 if (*itBound != *otherItBound) {
70 return false;
71 }
72 }
73
74 Q_ASSERT(itBound == itEnd && otherItBound == otherItEnd);
75 return true;
76}
77
78bool GeoDataPolygon::operator!=(const GeoDataPolygon &other) const
79{
80 return !this->operator==(other);
81}
82
84{
85 return true;
86}
87
89{
90 Q_D(const GeoDataPolygon);
91 return d->m_tessellationFlags.testFlag(Tessellate);
92}
93
94void GeoDataPolygon::setTessellate(bool tessellate)
95{
96 // According to the KML reference the tesselation is done along great circles
97 // for polygons in Google Earth. Our "Tesselate" flag does this.
98 // Only for pure line strings and linear rings the
99 // latitude circles are followed for subsequent points that share the same latitude.
100 detach();
101
103 if (tessellate) {
104 d->m_tessellationFlags |= Tessellate;
105 } else {
106 d->m_tessellationFlags ^= Tessellate;
107 }
108}
109
111{
112 Q_D(const GeoDataPolygon);
113 return d->m_tessellationFlags;
114}
115
117{
118 detach();
119
121 d->m_tessellationFlags = f;
122}
123
125{
126 Q_D(const GeoDataPolygon);
127 return d->outer.latLonAltBox();
128}
129
131{
132 detach();
133
135 return (d->outer);
136}
137
139{
140 Q_D(const GeoDataPolygon);
141 return d->outer;
142}
143
145{
146 detach();
147
149 d->outer = boundary;
150}
151
153{
154 detach();
155
157 return d->inner;
158}
159
161{
162 Q_D(const GeoDataPolygon);
163 return d->inner;
164}
165
167{
168 detach();
169
171 d->inner.append(boundary);
172}
173
174void GeoDataPolygon::setRenderOrder(int renderOrder)
175{
176 detach();
177
179 d->m_renderOrder = renderOrder;
180}
181
182int GeoDataPolygon::renderOrder() const
183{
184 Q_D(const GeoDataPolygon);
185 return d->m_renderOrder;
186}
187
189{
190 Q_D(const GeoDataPolygon);
191
192 GeoDataObject::pack(stream);
193
194 d->outer.pack(stream);
195
196 stream << d->inner.size();
197 stream << (qint32)(d->m_tessellationFlags);
198
199 for (QList<GeoDataLinearRing>::const_iterator iterator = d->inner.constBegin(); iterator != d->inner.constEnd(); ++iterator) {
200 mDebug() << "innerRing: size" << d->inner.size();
201 GeoDataLinearRing linearRing = (*iterator);
202 linearRing.pack(stream);
203 }
204}
205
207{
208 detach();
209
211
212 GeoDataObject::unpack(stream);
213
214 d->outer.unpack(stream);
215
216 qint32 size;
217 qint32 tessellationFlags;
218
219 stream >> size;
220 stream >> tessellationFlags;
221
222 d->m_tessellationFlags = (TessellationFlags)(tessellationFlags);
223
224 QList<GeoDataLinearRing> &inner = d->inner;
225 inner.reserve(inner.size() + size);
226 for (qint32 i = 0; i < size; i++) {
227 GeoDataLinearRing linearRing;
228 linearRing.unpack(stream);
229 inner.append(linearRing);
230 }
231}
232
233bool GeoDataPolygon::contains(const GeoDataCoordinates &coordinates) const
234{
235 if (!outerBoundary().contains(coordinates)) {
236 // Not inside the polygon at all
237 return false;
238 }
239
240 for (const GeoDataLinearRing &ring : innerBoundaries()) {
241 if (ring.contains(coordinates)) {
242 // Inside the polygon, but in one of its holes
243 return false;
244 }
245 }
246
247 return true;
248}
249
250}
A 3d point representation.
A base class for all geodata features.
A class that defines a 3D bounding box for geographic data.
void unpack(QDataStream &stream) override
Unserialize the LineString from a stream.
void pack(QDataStream &stream) const override
Serialize the LineString to a stream.
A LinearRing that allows to store a closed, contiguous set of line segments.
void pack(QDataStream &stream) const override
Reimplemented from Serializable.
void unpack(QDataStream &steam) override
Reimplemented from Serializable.
A polygon that can have "holes".
bool operator==(const GeoDataPolygon &other) const
Returns true/false depending on whether this and other are/are not equal.
~GeoDataPolygon() override
Destroys a Polygon.
void appendInnerBoundary(const GeoDataLinearRing &boundary)
Appends a given LinearRing as an inner boundary of the Polygon.
const GeoDataLatLonAltBox & latLonAltBox() const override
Returns the smallest latLonAltBox that contains the Polygon.
void setTessellate(bool tessellate)
Sets the tessellation property for the Polygon.
void setOuterBoundary(const GeoDataLinearRing &boundary)
Sets the given LinearRing as an outer boundary of the Polygon.
GeoDataLinearRing & outerBoundary()
Returns the outer boundary that is represented as a LinearRing.
const char * nodeType() const override
Provides type information for downcasting a GeoNode.
void setTessellationFlags(TessellationFlags f)
Sets the given tessellation flags for a Polygon.
QList< GeoDataLinearRing > & innerBoundaries()
Returns a set of inner boundaries which are represented as LinearRings.
void unpack(QDataStream &stream) override
Unserialize the Polygon from a stream.
virtual bool contains(const GeoDataCoordinates &coordinates) const
Returns whether the given coordinates lie within the polygon.
virtual bool isClosed() const
Returns whether a Polygon is a closed polygon.
void pack(QDataStream &stream) const override
Serialize the Polygon to a stream.
bool tessellate() const
Returns whether the Polygon follows the earth's surface.
GeoDataPolygon(TessellationFlags f=NoTessellation)
Creates a new Polygon.
TessellationFlags tessellationFlags() const
Returns the tessellation flags for a Polygon.
Binds a QML item to a specific geodetic location in screen coordinates.
void append(QList< T > &&value)
void reserve(qsizetype size)
qsizetype size() const const
Q_D(Todo)
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.