• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.14
  • kdeedu
  • marble
  • src
  • lib
  • marble
  • geodata
  • data
GeoDataLatLonBox.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2007 Andrew Manson <g.real.ate@gmail.com>
9 // Copyright 2008-2009 Torsten Rahn <rahn@kde.org>
10 //
11 
12 
13 #include "GeoDataLatLonBox.h"
14 
15 #include "MarbleDebug.h"
16 #include "GeoDataCoordinates.h"
17 #include "GeoDataLineString.h"
18 
19 #include "GeoDataTypes.h"
20 
21 namespace Marble
22 {
23 
24 const GeoDataLatLonBox GeoDataLatLonBox::empty = GeoDataLatLonBox();
25 
26 class GeoDataLatLonBoxPrivate
27 {
28  public:
29  GeoDataLatLonBoxPrivate()
30  : m_north( 0.0 ),
31  m_south( 0.0 ),
32  m_east( 0.0 ),
33  m_west( 0.0 ),
34  m_rotation( 0.0 )
35  {
36  }
37 
38  const char* nodeType() const
39  {
40  return GeoDataTypes::GeoDataLatLonBoxType;
41  }
42 
43  qreal m_north;
44  qreal m_south;
45  qreal m_east;
46  qreal m_west;
47  qreal m_rotation; // NOT implemented yet!
48 };
49 
50 bool operator==( GeoDataLatLonBox const& lhs, GeoDataLatLonBox const& rhs )
51 {
52  return lhs.d->m_west == rhs.d->m_west &&
53  lhs.d->m_east == rhs.d->m_east &&
54  lhs.d->m_north == rhs.d->m_north &&
55  lhs.d->m_south == rhs.d->m_south &&
56  lhs.d->m_rotation == rhs.d->m_rotation;
57 }
58 
59 bool operator!=( GeoDataLatLonBox const& lhs, GeoDataLatLonBox const& rhs )
60 {
61  return !( lhs == rhs );
62 }
63 
64 GeoDataLatLonBox::GeoDataLatLonBox()
65  : GeoDataObject(),
66  d( new GeoDataLatLonBoxPrivate )
67 {
68 }
69 
70 GeoDataLatLonBox::GeoDataLatLonBox( qreal north, qreal south, qreal east, qreal west, GeoDataCoordinates::Unit unit )
71  : GeoDataObject(),
72  d( new GeoDataLatLonBoxPrivate )
73 {
74  setBoundaries( north, south, east, west, unit );
75 }
76 
77 GeoDataLatLonBox::GeoDataLatLonBox( const GeoDataLatLonBox & other )
78  : GeoDataObject( other ),
79  d( new GeoDataLatLonBoxPrivate( *other.d ) )
80 {
81 }
82 
83 GeoDataLatLonBox::~GeoDataLatLonBox()
84 {
85  delete d;
86 }
87 
88 const char* GeoDataLatLonBox::nodeType() const
89 {
90  return d->nodeType();
91 }
92 
93 qreal GeoDataLatLonBox::north( GeoDataCoordinates::Unit unit ) const
94 {
95  if ( unit == GeoDataCoordinates::Degree ) {
96  return d->m_north * RAD2DEG;
97  }
98  return d->m_north;
99 }
100 
101 void GeoDataLatLonBox::setNorth( const qreal north, GeoDataCoordinates::Unit unit )
102 {
103  switch( unit ){
104  default:
105  case GeoDataCoordinates::Radian:
106  d->m_north = GeoDataCoordinates::normalizeLat( north );
107  break;
108  case GeoDataCoordinates::Degree:
109  d->m_north = GeoDataCoordinates::normalizeLat( north * DEG2RAD );
110  break;
111  }
112 }
113 
114 qreal GeoDataLatLonBox::south( GeoDataCoordinates::Unit unit ) const
115 {
116  if ( unit == GeoDataCoordinates::Degree ) {
117  return d->m_south * RAD2DEG;
118  }
119  return d->m_south;
120 }
121 
122 void GeoDataLatLonBox::setSouth( const qreal south, GeoDataCoordinates::Unit unit )
123 {
124  switch( unit ){
125  default:
126  case GeoDataCoordinates::Radian:
127  d->m_south = GeoDataCoordinates::normalizeLat( south );
128  break;
129  case GeoDataCoordinates::Degree:
130  d->m_south = GeoDataCoordinates::normalizeLat( south * DEG2RAD );
131  break;
132  }
133 }
134 
135 qreal GeoDataLatLonBox::east( GeoDataCoordinates::Unit unit ) const
136 {
137  if ( unit == GeoDataCoordinates::Degree ) {
138  return d->m_east * RAD2DEG;
139  }
140  return d->m_east;
141 }
142 
143 void GeoDataLatLonBox::setEast( const qreal east, GeoDataCoordinates::Unit unit )
144 {
145  switch( unit ){
146  default:
147  case GeoDataCoordinates::Radian:
148  d->m_east = GeoDataCoordinates::normalizeLon( east );
149  break;
150  case GeoDataCoordinates::Degree:
151  d->m_east = GeoDataCoordinates::normalizeLon( east * DEG2RAD );
152  break;
153  }
154 }
155 
156 qreal GeoDataLatLonBox::west( GeoDataCoordinates::Unit unit ) const
157 {
158  if ( unit == GeoDataCoordinates::Degree ) {
159  return d->m_west * RAD2DEG;
160  }
161  return d->m_west;
162 }
163 
164 void GeoDataLatLonBox::setWest( const qreal west, GeoDataCoordinates::Unit unit )
165 {
166  switch( unit ){
167  default:
168  case GeoDataCoordinates::Radian:
169  d->m_west = GeoDataCoordinates::normalizeLon( west );
170  break;
171  case GeoDataCoordinates::Degree:
172  d->m_west = GeoDataCoordinates::normalizeLon( west * DEG2RAD );
173  break;
174  }
175 }
176 
177 void GeoDataLatLonBox::setRotation( const qreal rotation, GeoDataCoordinates::Unit unit )
178 {
179  switch( unit ){
180  default:
181  case GeoDataCoordinates::Radian:
182  d->m_rotation = rotation;
183  break;
184  case GeoDataCoordinates::Degree:
185  d->m_rotation = rotation * DEG2RAD;
186  break;
187  }
188 }
189 
190 qreal GeoDataLatLonBox::rotation( GeoDataCoordinates::Unit unit ) const
191 {
192  if ( unit == GeoDataCoordinates::Degree ) {
193  return d->m_rotation * RAD2DEG;
194  }
195  return d->m_rotation;
196 }
197 
198 void GeoDataLatLonBox::boundaries( qreal &north, qreal &south, qreal &east, qreal &west, GeoDataCoordinates::Unit unit ) const
199 {
200  switch( unit ){
201  default:
202  case GeoDataCoordinates::Radian:
203  north = d->m_north;
204  south = d->m_south;
205  east = d->m_east;
206  west = d->m_west;
207  break;
208  case GeoDataCoordinates::Degree:
209  north = d->m_north * RAD2DEG;
210  south = d->m_south * RAD2DEG;
211  east = d->m_east * RAD2DEG;
212  west = d->m_west * RAD2DEG;
213  break;
214  }
215 }
216 
217 void GeoDataLatLonBox::setBoundaries( qreal north, qreal south, qreal east, qreal west, GeoDataCoordinates::Unit unit )
218 {
219  switch( unit ){
220  default:
221  case GeoDataCoordinates::Radian:
222  d->m_north = GeoDataCoordinates::normalizeLat( north );
223  d->m_south = GeoDataCoordinates::normalizeLat( south );
224  d->m_east = GeoDataCoordinates::normalizeLon( east );
225  d->m_west = GeoDataCoordinates::normalizeLon( west );
226  break;
227  case GeoDataCoordinates::Degree:
228  d->m_north = GeoDataCoordinates::normalizeLat( north * DEG2RAD );
229  d->m_south = GeoDataCoordinates::normalizeLat( south * DEG2RAD );
230  d->m_east = GeoDataCoordinates::normalizeLon( east * DEG2RAD );
231  d->m_west = GeoDataCoordinates::normalizeLon( west * DEG2RAD );
232  break;
233  }
234 }
235 
236 qreal GeoDataLatLonBox::width( GeoDataCoordinates::Unit unit ) const
237 {
238  qreal width = fabs( (qreal)( crossesDateLine()
239  ? 2 * M_PI - d->m_west + d->m_east
240  : d->m_east - d->m_west ) );
241 
242  // This also covers the case where this bounding box covers the whole
243  // longitude range ( -180 <= lon <= + 180 ).
244  if ( width > 2 * M_PI ) {
245  width = 2 * M_PI;
246  }
247 
248  if ( unit == GeoDataCoordinates::Degree ) {
249  return width * RAD2DEG;
250  }
251 
252  return width;
253 }
254 
255 qreal GeoDataLatLonBox::height( GeoDataCoordinates::Unit unit ) const
256 {
257  qreal height = fabs( (qreal)( d->m_south - d->m_north ) );
258 
259  if ( unit == GeoDataCoordinates::Degree ) {
260  return height * RAD2DEG;
261  }
262 
263  return height;
264 }
265 
266 bool GeoDataLatLonBox::crossesDateLine() const
267 {
268  if ( d->m_east < d->m_west ||
269  ( d->m_east == M_PI && d->m_west == -M_PI ) ) {
270  return true;
271  }
272 
273  return false;
274 }
275 
276 GeoDataCoordinates GeoDataLatLonBox::center() const
277 {
278  if( isEmpty() )
279  return GeoDataCoordinates();
280 
281  if( crossesDateLine() )
282  return GeoDataCoordinates( GeoDataCoordinates::normalizeLon( east() + 2 * M_PI - ( east() + 2 * M_PI - west() ) / 2 ) ,
283  north() - ( north() - south() ) / 2 );
284  else
285  return GeoDataCoordinates( east() - ( east() - west() ) / 2,
286  north() - ( north() - south() ) / 2 );
287 }
288 
289 bool GeoDataLatLonBox::containsPole( Pole pole ) const
290 {
291  switch ( pole ) {
292  case NorthPole:
293  return ( 2 * north() == +M_PI );
294  break;
295  case SouthPole:
296  return ( 2 * south() == -M_PI );
297  break;
298  default:
299  case AnyPole:
300  return ( 2 * north() == +M_PI
301  || 2 * south() == -M_PI );
302  break;
303  }
304 
305  mDebug() << Q_FUNC_INFO << "Invalid pole";
306  return false;
307 }
308 
309 bool GeoDataLatLonBox::contains( const GeoDataCoordinates &point ) const
310 {
311  qreal lon, lat;
312 
313  point.geoCoordinates( lon, lat );
314 
315  // We need to take care of the normal case ...
316  if ( ( ( lon < d->m_west || lon > d->m_east ) && ( d->m_west < d->m_east ) ) ||
317  // ... and the case where the bounding box crosses the date line:
318  ( ( lon < d->m_west && lon > d->m_east ) && ( d->m_west > d->m_east ) ) )
319  return false;
320 
321  if ( lat < d->m_south || lat > d->m_north )
322  return false;
323 
324  return true;
325 }
326 
327 bool GeoDataLatLonBox::contains( const GeoDataLatLonBox &other ) const
328 {
329  // check the contain criterion for the latitude first as this is trivial:
330 
331  if ( d->m_north >= other.north() && d->m_south <= other.south() ) {
332 
333  if ( !crossesDateLine() ) {
334  if ( !other.crossesDateLine() ) {
335  // "Normal" case: both bounding boxes don't cross the date line
336  if ( d->m_west <= other.west() && d->m_east >= other.east() ) {
337  return true;
338  }
339  }
340  else {
341  // The other bounding box crosses the date line, "this" one does not:
342  // So the date line splits the other bounding box in two parts.
343  // Hence "this" bounding box could be fully contained by one of them.
344  // So for both cases we are able to ignore the "overhanging" portion
345  // and thereby basically reduce the problem to the "normal" case:
346 
347  if ( ( other.west() <= d->m_west && d->m_east <= +M_PI )
348  || ( other.east() >= d->m_east && d->m_west >= -M_PI ) ) {
349  return true;
350  }
351  }
352  }
353  else {
354  if ( other.crossesDateLine() ) {
355  // Other "Simple" case: both bounding boxes cross the date line
356  if ( d->m_west <= other.west() && d->m_east >= other.east() ) {
357  return true;
358  }
359  }
360  else {
361  // "This" bounding box crosses the date line, the other one does not.
362  // So the date line splits "this" bounding box in two parts.
363  // Hence the other bounding box could be fully contained by one of them.
364  // So for both cases we are able to ignore the "overhanging" portion
365  // and thereby basically reduce the problem to the "normal" case:
366 
367  if ( ( d->m_west <= other.west() && other.east() <= +M_PI )
368  || ( d->m_east >= other.east() && other.west() >= -M_PI ) ) {
369  return true;
370  }
371 
372  // if this bounding box covers the whole longitude range ( -180 <= lon <= + 180 )
373  // then of course the "inner" bounding box is "inside"
374  if ( d->m_west == -M_PI && d->m_east == +M_PI ) {
375  return true;
376  }
377  }
378 
379  }
380  }
381 
382  return false;
383 }
384 
385 bool GeoDataLatLonBox::intersects( const GeoDataLatLonBox &other ) const
386 {
387  if ( isEmpty() || other.isEmpty() ) {
388  return false;
389  }
390 
391  // check the intersection criterion for the latitude first:
392 
393  // Case 1: northern boundary of other box intersects:
394  if ( ( d->m_north >= other.north() && d->m_south <= other.north() )
395  // Case 2: northern boundary of this box intersects:
396  || ( other.north() >= d->m_north && other.south() <= d->m_north )
397  // Case 3: southern boundary of other box intersects:
398  || ( d->m_north >= other.south() && d->m_south <= other.south() )
399  // Case 4: southern boundary of this box intersects:
400  || ( other.north() >= d->m_south && other.south() <= d->m_south ) ) {
401 
402  if ( !crossesDateLine() ) {
403  if ( !other.crossesDateLine() ) {
404  // "Normal" case: both bounding boxes don't cross the date line
405  // Case 1: eastern boundary of other box intersects:
406  if ( ( d->m_east >= other.east() && d->m_west <= other.east() )
407  // Case 2: eastern boundary of this box intersects:
408  || ( other.east() >= d->m_east && other.west() <= d->m_east )
409  // Case 3: western boundary of other box intersects:
410  || ( d->m_east >= other.west() && d->m_west <= other.west() )
411  // Case 4: western boundary of this box intersects:
412  || ( other.east() >= d->m_west && other.west() <= d->m_west ) ) {
413  return true;
414  }
415  }
416  else {
417  // The other bounding box crosses the date line, "this" one does not:
418  // So the date line splits the other bounding box in two parts.
419 
420  if ( d->m_west <= other.east() || d->m_east >= other.west() ) {
421  return true;
422  }
423  }
424  }
425  else {
426  if ( other.crossesDateLine() ) {
427  // The trivial case: both bounding boxes cross the date line and intersect
428  return true;
429  }
430  else {
431  // "This" bounding box crosses the date line, the other one does not.
432  // So the date line splits "this" bounding box in two parts.
433  //
434  // This also covers the case where this bounding box covers the whole
435  // longitude range ( -180 <= lon <= + 180 ).
436  if ( other.west() <= d->m_east || other.east() >= d->m_west ) {
437  return true;
438  }
439  }
440  }
441  }
442 
443  return false;
444 }
445 
446 GeoDataLatLonBox GeoDataLatLonBox::united( const GeoDataLatLonBox& other ) const
447 {
448  if ( isEmpty() ) {
449  return other;
450  }
451 
452  if ( other.isEmpty() ) {
453  return *this;
454  }
455 
456  GeoDataLatLonBox result;
457 
458  // use the position of the centers of the boxes to determine the "smallest"
459  // box (i.e. should the total box go through IDL or not). this
460  // determination does not depend on one box or the other crossing IDL too
461  GeoDataCoordinates c1 = center();
462  GeoDataCoordinates c2 = other.center();
463 
464  // do latitude first, quite simple
465  result.setNorth(qMax( d->m_north, other.north() ) );
466  result.setSouth( qMin( d->m_south, other.south() ) );
467 
468  qreal w1 = d->m_west;
469  qreal w2 = other.west();
470  qreal e1 = d->m_east;
471  qreal e2 = other.east();
472 
473  bool const idl1 = d->m_east < d->m_west;
474  bool const idl2 = other.d->m_east < other.d->m_west;
475 
476  if ( idl1 ) {
477  w1 += 2* M_PI;
478  e1 += 2* M_PI;
479  }
480  if ( idl2 ) {
481  w2 += 2* M_PI;
482  e2 += 2* M_PI;
483  }
484 
485  // in the usual case, we take the maximum of east bounds, and
486  // the minimum of west bounds. The exceptions are:
487  // - centers of boxes are more than 180 apart
488  // (so the smallest box should go around the IDL)
489  //
490  // - 1 but not 2 boxes are crossing IDL
491  if ( fabs( c2.longitude()-c1.longitude() ) > M_PI
492  || ( idl1 ^ idl2 ) ) {
493  // exceptions, we go the unusual way:
494  // min of east, max of west
495  result.setEast( qMin( e1, e2 ) );
496  result.setWest( qMax( w1, w2 ) );
497  }
498  else {
499  // normal case, max of east, min of west
500  result.setEast( qMax( e1, e2 ) );
501  result.setWest( qMin( w1, w2 ) );
502  }
503  return result;
504 }
505 
506 GeoDataLatLonBox GeoDataLatLonBox::toCircumscribedRectangle() const
507 {
508  QList<GeoDataCoordinates> coordinates;
509 
510  coordinates.append( GeoDataCoordinates( west(), north() ) );
511  coordinates.append( GeoDataCoordinates( west(), south() ) );
512  coordinates.append( GeoDataCoordinates( east() + ( crossesDateLine() ? 2 * M_PI : 0 ), north() ) );
513  coordinates.append( GeoDataCoordinates( east() + ( crossesDateLine() ? 2 * M_PI : 0 ), south() ) );
514 
515  const qreal cosRotation = cos( rotation() );
516  const qreal sinRotation = sin( rotation() );
517 
518  qreal centerLat = center().latitude();
519  qreal centerLon = center().longitude();
520  if ( GeoDataLatLonBox( 0, 0, center().longitude(), west() ).crossesDateLine() ) {
521  if ( !centerLon ) centerLon += M_PI;
522  else centerLon += 2 * M_PI;
523  }
524 
525  GeoDataLatLonBox box;
526 
527  bool northSet = false;
528  bool southSet = false;
529  bool eastSet = false;
530  bool westSet = false;
531 
532  foreach ( const GeoDataCoordinates& coord, coordinates ) {
533 
534  const qreal lon = coord.longitude();
535  const qreal lat = coord.latitude();
536 
537  const qreal rotatedLon = ( lon - centerLon ) * cosRotation - ( lat - centerLat ) * sinRotation + centerLon;
538  const qreal rotatedLat = ( lon - centerLon ) * sinRotation + ( lat - centerLat ) * cosRotation + centerLat;
539 
540  if ( !northSet || rotatedLat > box.north() ) {
541  northSet = true;
542  box.setNorth( rotatedLat );
543  }
544 
545  if ( !southSet || rotatedLat < box.south() ) {
546  southSet = true;
547  box.setSouth( rotatedLat );
548  }
549 
550  if ( !westSet || rotatedLon < box.west() ) {
551  westSet = true;
552  box.setWest( rotatedLon );
553  }
554 
555  if ( !eastSet || rotatedLon > box.east() ) {
556  eastSet = true;
557  box.setEast( rotatedLon );
558  }
559  }
560 
561  box.setBoundaries( GeoDataCoordinates::normalizeLat( box.north() ),
562  GeoDataCoordinates::normalizeLat( box.south() ),
563  GeoDataCoordinates::normalizeLon( box.east() ),
564  GeoDataCoordinates::normalizeLon( box.west() ) );
565  return box;
566 }
567 
568 QString GeoDataLatLonBox::toString( GeoDataCoordinates::Unit unit ) const
569 {
570  switch( unit ){
571  default:
572  case GeoDataCoordinates::Radian:
573  return QString( "North: %1; West: %2; South: %3; East: %4" )
574  .arg( d->m_north ).arg( d->m_west ).arg( d->m_south ).arg( d->m_east );
575  break;
576  case GeoDataCoordinates::Degree:
577  return QString( "North: %1; West: %2; South: %3; East: %4" )
578  .arg( d->m_north * RAD2DEG ).arg( d->m_west * RAD2DEG ).arg( d->m_south * RAD2DEG ).arg( d->m_east * RAD2DEG );
579  break;
580  }
581 
582  return QString( "GeoDataLatLonBox::text(): Error in unit: %1\n" )
583  .arg( unit );
584 }
585 
586 GeoDataLatLonBox& GeoDataLatLonBox::operator=( const GeoDataLatLonBox &other )
587 {
588  GeoDataObject::operator=( other );
589 
590  *d = *other.d;
591  return *this;
592 }
593 
594 GeoDataLatLonBox GeoDataLatLonBox::operator|( const GeoDataLatLonBox& other ) const
595 {
596  return united( other );
597 }
598 
599 GeoDataLatLonBox& GeoDataLatLonBox::operator|=( const GeoDataLatLonBox& other )
600 {
601  *this = united( other );
602  return *this;
603 }
604 
605 
606 void GeoDataLatLonBox::pack( QDataStream& stream ) const
607 {
608  GeoDataObject::pack( stream );
609 
610  stream << d->m_north << d->m_south << d->m_east << d->m_west << d->m_rotation;
611 }
612 
613 void GeoDataLatLonBox::unpack( QDataStream& stream )
614 {
615  GeoDataObject::unpack( stream );
616 
617  stream >> d->m_north >> d->m_south >> d->m_east >> d->m_west >> d->m_rotation;
618 }
619 
620 GeoDataLatLonBox GeoDataLatLonBox::fromLineString( const GeoDataLineString& lineString )
621 {
622  // If the line string is empty return an empty boundingbox
623  if ( lineString.isEmpty() ) {
624  return GeoDataLatLonBox();
625  }
626 
627  qreal lon, lat;
628  lineString.first().geoCoordinates( lon, lat );
629  GeoDataCoordinates::normalizeLonLat( lon, lat );
630 
631  qreal north = lat;
632  qreal south = lat;
633  qreal west = lon;
634  qreal east = lon;
635 
636  // If there's only a single node stored then the boundingbox only contains that point
637  if ( lineString.size() == 1 )
638  return GeoDataLatLonBox( north, south, east, west );
639 
640  // Specifies whether the polygon crosses the IDL
641  bool idlCrossed = false;
642 
643  // "idlCrossState" specifies the state concerning IDL crossage.
644  // This is needed in order to create optimal bounding boxes in case of covering the IDL
645  // Every time the IDL gets crossed from east to west the idlCrossState value gets
646  // increased by one.
647  // Every time the IDL gets crossed from west to east the idlCrossState value gets
648  // decreased by one.
649 
650  int idlCrossState = 0;
651  int idlMaxCrossState = 0;
652  int idlMinCrossState = 0;
653 
654  // Holds values for east and west while idlCrossState != 0
655  qreal otherWest = lon;
656  qreal otherEast = lon;
657 
658  qreal previousLon = lon;
659 
660  int currentSign = ( lon < 0 ) ? -1 : +1;
661  int previousSign = currentSign;
662 
663  QVector<GeoDataCoordinates>::ConstIterator it( lineString.constBegin() );
664  QVector<GeoDataCoordinates>::ConstIterator itEnd( lineString.constEnd() );
665 
666  bool processingLastNode = false;
667 
668  while( it != itEnd ) {
669  // Get coordinates and normalize them to the desired range.
670  (it)->geoCoordinates( lon, lat );
671  GeoDataCoordinates::normalizeLonLat( lon, lat );
672 
673  // Determining the maximum and minimum latitude
674  if ( lat > north ) north = lat;
675  if ( lat < south ) south = lat;
676 
677  currentSign = ( lon < 0 ) ? -1 : +1;
678 
679  // Once the polyline crosses the dateline the covered bounding box
680  // would cover the whole [-M_PI; M_PI] range.
681  // When looking separately at the longitude range that gets covered
682  // east and west from the IDL we get two bounding boxes (we prefix
683  // the resulting longitude range on the "other side" with "other").
684  // By picking the "inner" range values we get a more appropriate
685  // optimized single bounding box.
686 
687  // IDL check
688  if ( previousSign != currentSign
689  && fabs( previousLon ) + fabs( lon ) > M_PI ) {
690 
691  // Initialize values for otherWest and otherEast
692  if ( idlCrossed == false ) {
693  otherWest = lon;
694  otherEast = lon;
695  idlCrossed = true;
696  }
697 
698  // Determine the new IDL Cross State
699  if ( previousLon < 0 ) {
700  idlCrossState++;
701  if ( idlCrossState > idlMaxCrossState ) {
702  idlMaxCrossState = idlCrossState;
703  }
704  }
705  else {
706  idlCrossState--;
707  if ( idlCrossState < idlMinCrossState ) {
708  idlMinCrossState = idlCrossState;
709  }
710  }
711  }
712 
713  if ( idlCrossState == 0 ) {
714  if ( lon > east ) east = lon;
715  if ( lon < west ) west = lon;
716  }
717  else {
718  if ( lon > otherEast ) otherEast = lon;
719  if ( lon < otherWest ) otherWest = lon;
720  }
721 
722  previousLon = lon;
723  previousSign = currentSign;
724 
725  if ( processingLastNode ) {
726  break;
727  }
728  ++it;
729 
730  if( lineString.isClosed() && it == itEnd ) {
731  it = lineString.constBegin();
732  processingLastNode = true;
733  }
734  }
735 
736  if ( idlCrossed ) {
737  if ( idlMinCrossState < 0 ) {
738  east = otherEast;
739  }
740  if ( idlMaxCrossState > 0 ) {
741  west = otherWest;
742  }
743  if ( ( idlMinCrossState < 0 && idlMaxCrossState > 0 )
744  || idlMinCrossState < -1 || idlMaxCrossState > 1
745  || west <= east ) {
746  east = +M_PI;
747  west = -M_PI;
748  // if polygon fully in south hemisphere, contain south pole
749  if( north < 0 ) {
750  south = -M_PI/2;
751  } else {
752  north = M_PI/2;
753  }
754  }
755  }
756 
757  return GeoDataLatLonBox( north, south, east, west );
758 }
759 
760 bool GeoDataLatLonBox::isNull() const
761 {
762  if ( d->m_north == d->m_south && d->m_east == d->m_west )
763  return true;
764 
765  return false;
766 }
767 
768 bool GeoDataLatLonBox::isEmpty() const
769 {
770  return *this == empty;
771 }
772 
773 void GeoDataLatLonBox::clear()
774 {
775  *this = empty;
776 }
777 }
Marble::GeoDataCoordinates::Unit
Unit
enum used constructor to specify the units used
Definition: GeoDataCoordinates.h:64
Marble::GeoDataLatLonBox::operator=
GeoDataLatLonBox & operator=(const GeoDataLatLonBox &other)
Definition: GeoDataLatLonBox.cpp:586
GeoDataCoordinates.h
Marble::RAD2DEG
const qreal RAD2DEG
Definition: MarbleGlobal.h:220
Marble::GeoDataLatLonBox::isNull
virtual bool isNull() const
Indicates whether the bounding box only contains a single 2D point ("singularity").
Definition: GeoDataLatLonBox.cpp:760
Marble::GeoDataLatLonBox::height
qreal height(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the height of the latitude interval.
Definition: GeoDataLatLonBox.cpp:255
Marble::AnyPole
Any pole.
Definition: MarbleGlobal.h:156
Marble::GeoDataCoordinates
A 3d point representation.
Definition: GeoDataCoordinates.h:52
Marble::SouthPole
Only South Pole.
Definition: MarbleGlobal.h:158
Marble::GeoDataCoordinates::Radian
Definition: GeoDataCoordinates.h:65
Marble::GeoDataLatLonBox::isEmpty
virtual bool isEmpty() const
Indicates whether the bounding box is not initialised (and contains nothing).
Definition: GeoDataLatLonBox.cpp:768
Marble::GeoDataLatLonBox::width
qreal width(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the width of the longitude interval.
Definition: GeoDataLatLonBox.cpp:236
Marble::GeoDataLatLonBox::setNorth
void setNorth(const qreal north, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
Definition: GeoDataLatLonBox.cpp:101
Marble::GeoDataLineString::constEnd
QVector< GeoDataCoordinates >::ConstIterator constEnd() const
Returns a const iterator that points to the end of the LineString.
Definition: GeoDataLineString.cpp:220
Marble::GeoDataLatLonBox::boundaries
void boundaries(qreal &north, qreal &south, qreal &east, qreal &west, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Definition: GeoDataLatLonBox.cpp:198
Marble::GeoDataLatLonBox::operator|=
GeoDataLatLonBox & operator|=(const GeoDataLatLonBox &other)
Unites this bounding box with the given one.
Definition: GeoDataLatLonBox.cpp:599
Marble::GeoDataCoordinates::normalizeLon
static qreal normalizeLon(qreal lon, GeoDataCoordinates::Unit=GeoDataCoordinates::Radian)
normalize the longitude to always be -M_PI <= lon <= +M_PI (Radian).
Definition: GeoDataCoordinates.cpp:776
QDataStream
Marble::GeoDataLineString::size
int size() const
Returns the number of nodes in a LineString.
Definition: GeoDataLineString.cpp:138
Marble::GeoDataObject
A base class for all geodata objects.
Definition: GeoDataObject.h:48
Marble::GeoDataLatLonBox::united
GeoDataLatLonBox united(const GeoDataLatLonBox &other) const
Returns the bounding LatLonBox of this box with the given one.
Definition: GeoDataLatLonBox.cpp:446
Marble::GeoDataObject::pack
virtual void pack(QDataStream &stream) const
Reimplemented from Serializable.
Definition: GeoDataObject.cpp:114
Marble::GeoDataLatLonBox::setSouth
void setSouth(const qreal south, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
Definition: GeoDataLatLonBox.cpp:122
Marble::GeoDataLatLonBox::operator|
GeoDataLatLonBox operator|(const GeoDataLatLonBox &other) const
Definition: GeoDataLatLonBox.cpp:594
Marble::GeoDataCoordinates::latitude
qreal latitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the latitude of the GeoDataCoordinates object use the unit parameter to switch between Radi...
Definition: GeoDataCoordinates.cpp:751
Marble::GeoDataLatLonBox::setWest
void setWest(const qreal west, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
Definition: GeoDataLatLonBox.cpp:164
Marble::GeoDataLatLonBox::contains
virtual bool contains(const GeoDataCoordinates &) const
Definition: GeoDataLatLonBox.cpp:309
MarbleDebug.h
Marble::GeoDataLatLonBox::clear
virtual void clear()
Resets the bounding box to its uninitialised state (and thus contains nothing).
Definition: GeoDataLatLonBox.cpp:773
Marble::GeoDataCoordinates::Degree
Definition: GeoDataCoordinates.h:66
Marble::operator==
bool operator==(const DownloadPolicyKey &lhs, const DownloadPolicyKey &rhs)
Definition: DownloadPolicy.h:49
Marble::GeoDataLineString::isClosed
virtual bool isClosed() const
Returns whether a LineString is a closed polygon.
Definition: GeoDataLineString.cpp:310
Marble::GeoDataTypes::GeoDataLatLonBoxType
const char * GeoDataLatLonBoxType
Definition: GeoDataTypes.cpp:50
Marble::GeoDataLatLonBox::north
qreal north(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the northern boundary of the bounding box.
Definition: GeoDataLatLonBox.cpp:93
Marble::GeoDataLatLonBox::east
qreal east(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the eastern boundary of the bounding box.
Definition: GeoDataLatLonBox.cpp:135
QList::append
void append(const T &value)
Marble::GeoDataCoordinates::geoCoordinates
void geoCoordinates(qreal &lon, qreal &lat, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
use this function to get the longitude and latitude with one call - use the unit parameter to switch ...
Definition: GeoDataCoordinates.cpp:715
Marble::GeoDataLatLonBox::nodeType
virtual const char * nodeType() const
Provides type information for downcasting a GeoData.
Definition: GeoDataLatLonBox.cpp:88
Marble::GeoDataLatLonBox::intersects
virtual bool intersects(const GeoDataLatLonBox &) const
Definition: GeoDataLatLonBox.cpp:385
GeoDataLineString.h
Marble::operator!=
bool operator!=(GeoDataLatLonBox const &lhs, GeoDataLatLonBox const &rhs)
Definition: GeoDataLatLonBox.cpp:59
Marble::GeoDataLineString::first
GeoDataCoordinates & first()
Returns a reference to the first node in the LineString. This method detaches the returned coordinate...
Definition: GeoDataLineString.cpp:177
Marble::GeoDataCoordinates::normalizeLat
static qreal normalizeLat(qreal lat, GeoDataCoordinates::Unit=GeoDataCoordinates::Radian)
normalize latitude to always be in -M_PI / 2.
Definition: GeoDataCoordinates.cpp:799
QString
QList
Marble::GeoDataLatLonBox::rotation
qreal rotation(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the rotation of the bounding box.
Definition: GeoDataLatLonBox.cpp:190
Marble::GeoDataCoordinates::normalizeLonLat
static void normalizeLonLat(qreal &lon, qreal &lat, GeoDataCoordinates::Unit=GeoDataCoordinates::Radian)
normalize both longitude and latitude at the same time This method normalizes both latitude and longi...
Definition: GeoDataCoordinates.cpp:845
Marble::GeoDataLatLonBox::fromLineString
static GeoDataLatLonBox fromLineString(const GeoDataLineString &lineString)
Create the smallest bounding box from a line string.
Definition: GeoDataLatLonBox.cpp:620
Marble::DEG2RAD
const qreal DEG2RAD
Definition: MarbleGlobal.h:219
Marble::GeoDataLineString
A LineString that allows to store a contiguous set of line segments.
Definition: GeoDataLineString.h:75
Marble::GeoDataLatLonBox::center
virtual GeoDataCoordinates center() const
returns the center of this box
Definition: GeoDataLatLonBox.cpp:276
Marble::GeoDataLatLonBox::toString
virtual QString toString(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Creates a text string of the bounding box.
Definition: GeoDataLatLonBox.cpp:568
Marble::GeoDataCoordinates::longitude
qreal longitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the longitude of the GeoDataCoordinates object use the unit parameter to switch between Rad...
Definition: GeoDataCoordinates.cpp:739
Marble::GeoDataLatLonBox::crossesDateLine
bool crossesDateLine() const
Detect whether the bounding box crosses the IDL.
Definition: GeoDataLatLonBox.cpp:266
Marble::GeoDataLatLonBox::toCircumscribedRectangle
GeoDataLatLonBox toCircumscribedRectangle() const
Definition: GeoDataLatLonBox.cpp:506
GeoDataLatLonBox.h
Marble::GeoDataLatLonBox::pack
virtual void pack(QDataStream &stream) const
Serialize the contents of the feature to stream.
Definition: GeoDataLatLonBox.cpp:606
Marble::GeoDataLatLonBox::west
qreal west(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the western boundary of the bounding box.
Definition: GeoDataLatLonBox.cpp:156
QVector
Marble::GeoDataLineString::isEmpty
bool isEmpty() const
Returns whether the LineString has no nodes at all.
Definition: GeoDataLineString.cpp:133
Marble::GeoDataLatLonBox::~GeoDataLatLonBox
virtual ~GeoDataLatLonBox()
Definition: GeoDataLatLonBox.cpp:83
Marble::GeoDataLineString::constBegin
QVector< GeoDataCoordinates >::ConstIterator constBegin() const
Returns a const iterator that points to the begin of the LineString.
Definition: GeoDataLineString.cpp:215
Marble::GeoDataObject::operator=
GeoDataObject & operator=(const GeoDataObject &)
Definition: GeoDataObject.cpp:54
Marble::GeoDataLatLonBox::south
qreal south(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the southern boundary of the bounding box.
Definition: GeoDataLatLonBox.cpp:114
Marble::GeoDataLatLonBox::setBoundaries
void setBoundaries(qreal north, qreal south, qreal east, qreal west, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
Definition: GeoDataLatLonBox.cpp:217
M_PI
#define M_PI
Definition: GeoDataCoordinates.h:26
Marble::GeoDataObject::unpack
virtual void unpack(QDataStream &steam)
Reimplemented from Serializable.
Definition: GeoDataObject.cpp:120
Marble::GeoDataLatLonBox::containsPole
bool containsPole(Pole pole=AnyPole) const
Detect whether the bounding box contains one of the poles.
Definition: GeoDataLatLonBox.cpp:289
GeoDataTypes.h
Marble::GeoDataLatLonBox::setRotation
void setRotation(const qreal rotation, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
Definition: GeoDataLatLonBox.cpp:177
Marble::GeoDataLatLonBox::unpack
virtual void unpack(QDataStream &stream)
Unserialize the contents of the feature from stream.
Definition: GeoDataLatLonBox.cpp:613
Marble::Pole
Pole
Definition: MarbleGlobal.h:155
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
Marble::mDebug
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:36
Marble::NorthPole
Only North Pole.
Definition: MarbleGlobal.h:157
Marble::GeoDataLatLonBox::GeoDataLatLonBox
GeoDataLatLonBox()
Definition: GeoDataLatLonBox.cpp:64
Marble::GeoDataLatLonBox
A class that defines a 2D bounding box for geographic data.
Definition: GeoDataLatLonBox.h:51
Marble::GeoDataLatLonBox::setEast
void setEast(const qreal east, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
Definition: GeoDataLatLonBox.cpp:143
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:39 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal