Marble

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

KDE's Doxygen guidelines are available online.