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

marble

  • sources
  • kde-4.12
  • kdeedu
  • marble
  • src
  • lib
  • marble
GeoPolygon.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 2004-2007 Torsten Rahn <tackat@kde.org>
9 // Copyright 2007 Inge Wallin <ingwa@kde.org>
10 //
11 
12 
13 #include "GeoPolygon.h"
14 
15 #include <cstdlib>
16 #include <fcntl.h>
17 #include <cmath>
18 using std::fabs;
19 
20 #include <QFile>
21 #include <QDataStream>
22 #include <QTime>
23 #ifdef Q_OS_UNIX
24 # include <unistd.h>
25 # include <sys/types.h>
26 # include <sys/stat.h>
27 # include <sys/mman.h> /* mmap() is defined in this header */
28 #endif
29 
30 #include "MarbleDebug.h"
31 #include "Quaternion.h"
32 
33 using namespace Marble;
34 
35 const qreal ARCMINUTE = 10800; // distance of 180deg in arcminutes
36 const qreal INT2RAD = M_PI / 10800.0;
37 
38 GeoPolygon::GeoPolygon()
39  : m_dateLineCrossing( false ),
40  m_closed( false ),
41  m_index( 0 )
42 {
43 }
44 
45 GeoPolygon::~GeoPolygon()
46 {
47 // qDeleteAll( begin(), end() );
48  qDeleteAll( m_boundary );
49 }
50 
51 void GeoPolygon::setBoundary( qreal lonLeft, qreal latTop, qreal lonRight, qreal latBottom)
52 {
53  m_boundary.clear();
54  if ( getDateLine() == GeoPolygon::Even ) {
55  qreal xcenter = ( lonLeft + ( 2.0 * M_PI + lonRight) ) / 2.0;
56 
57  if ( xcenter > M_PI )
58  xcenter -= 2.0 * M_PI;
59  if ( xcenter < -M_PI )
60  xcenter += 2.0 * M_PI;
61 
62  m_boundary.append( new GeoDataCoordinates( xcenter, 0.5 * (latTop + latBottom), 0.0,
63  GeoDataCoordinates::Radian, 1 ) );
64  }
65  else
66  m_boundary.append( new GeoDataCoordinates( 0.5 * (lonLeft + lonRight),
67  0.5 * (latTop + latBottom), 0.0,
68  GeoDataCoordinates::Radian, 1 ) );
69 
70  m_boundary.append( new GeoDataCoordinates( lonLeft, latTop, 0.0, GeoDataCoordinates::Radian, 1 ));
71  m_boundary.append( new GeoDataCoordinates( lonRight, latBottom, 0.0, GeoDataCoordinates::Radian, 1 ));
72  m_boundary.append( new GeoDataCoordinates( lonRight, latTop, 0.0, GeoDataCoordinates::Radian, 1 ));
73  m_boundary.append( new GeoDataCoordinates( lonLeft, latBottom, 0.0, GeoDataCoordinates::Radian, 1 ));
74 
75 }
76 
77 void GeoPolygon::displayBoundary()
78 {
79  Quaternion q;
80  qreal lon;
81  qreal lat;
82  m_boundary.at(0)->geoCoordinates(lon, lat, GeoDataCoordinates::Degree);
83  mDebug() << "Boundary:" << lon << ", " << lat;
84  m_boundary.at(1)->geoCoordinates(lon, lat, GeoDataCoordinates::Degree);
85  mDebug() << "Boundary:" << lon << ", " << lat;
86  m_boundary.at(2)->geoCoordinates(lon, lat, GeoDataCoordinates::Degree);
87  mDebug() << "Boundary:" << lon << ", " << lat;
88  m_boundary.at(3)->geoCoordinates(lon, lat, GeoDataCoordinates::Degree);
89  mDebug() << "Boundary:" << lon << ", " << lat;
90  m_boundary.at(4)->geoCoordinates(lon, lat, GeoDataCoordinates::Degree);
91  mDebug() << "Boundary:" << lon << ", " << lat;
92 
93 // mDebug() << "Points#: " << size() << " File: " << m_sourceFileName
94 // << " dateline " << getDateLine() << " Index: " << getIndex();
95 }
96 
97 // ================================================================
98 // class PntMap
99 
100 
101 PntMap::PntMap()
102  : m_isInitialized( false ),
103  m_loader( 0 )
104 {
105 }
106 
107 bool PntMap::isInitialized() const
108 {
109  return m_isInitialized;
110 }
111 
112 PntMap::~PntMap()
113 {
114  if ( m_loader ) {
115  m_loader->wait();
116  }
117  qDeleteAll( begin(), end() );
118 }
119 
120 void PntMap::load(const QString &filename)
121 {
122  m_loader = new PntMapLoader( this, filename );
123 
124  connect ( m_loader, SIGNAL(pntMapLoaded(bool)), SLOT(setInitialized(bool)) );
125  m_loader->start();
126 }
127 
128 void PntMap::setInitialized( bool isInitialized )
129 {
130  if ( m_loader->isFinished() ) {
131  delete m_loader;
132  m_loader = 0;
133  }
134 
135  m_isInitialized = isInitialized;
136  emit initialized();
137 }
138 
139 PntMapLoader::PntMapLoader( PntMap* parent, const QString& filename )
140  : m_parent( parent ),
141  m_filename( filename )
142 {
143 }
144 
145 void PntMapLoader::run()
146 {
147 // qDebug("PntMap::load trying to load: " + m_filename.toLocal8Bit());
148  QTime timer;
149  timer.restart();
150 
151 #ifdef Q_OS_UNIX
152  // MMAP Start
153  int fd;
154  unsigned char* src;
155  struct stat statbuf;
156 
157  if ( (fd = open (m_filename.toLatin1(), O_RDONLY) ) < 0) // krazy:exclude=syscalls
158  mDebug() << "cannot open" << m_filename << " for reading";
159 
160  int filelength;
161  if ( fstat (fd,&statbuf) < 0 ) { // krazy:exclude=syscalls
162  filelength = 0;
163  mDebug() << "fstat error";
164  } else {
165  filelength = statbuf.st_size;
166  }
167 
168  if ((src = (unsigned char*) mmap (0, filelength, PROT_READ, MAP_SHARED, fd, 0))
169  == (unsigned char*) (caddr_t) -1)
170  mDebug() << "mmap error for input";
171 
172  short header;
173  short iLat;
174  short iLon;
175  int count = 0;
176 
177  //const int halfFileLength = filelength / 2;
178 
179  for (int i=0; i < filelength; i+=6){
180  header = src[i] | (src[i+1] << 8);
181  iLat = src[i+2] | (src[i+3] << 8);
182  iLon = src[i+4] | (src[i+5] << 8);
183 
184  // Transforming Range of Coordinates to iLat [0,ARCMINUTE] ,
185  // iLon [0,2 * ARCMINUTE]
186 
187  //
188  // 90 00N = -ARCMINUTE / 2
189  // 90 00S = ARCMINUTE / 2
190  // 180 00W = -ARCMINUTE
191  // 180 00E = ARCMINUTE
192  //
193  if ( header > 5 ) {
194 
195  // qDebug(QString("header: %1 iLat: %2 iLon: %3").arg(header).arg(iLat).arg(iLon).toLatin1());
196 
197  GeoPolygon *polyline = new GeoPolygon();
198  m_parent->append( polyline );
199 
200 // polyline->m_sourceFileName=filename;
201  polyline->setIndex( header );
202 
203  // Find out whether the Polyline is a river or a closed polygon
204  if ( ( header >= 7000 && header < 8000 )
205  || ( header >= 9000 && header < 20000 ) )
206  polyline->setClosed( false );
207  else
208  polyline->setClosed( true );
209 
210  polyline->append( GeoDataCoordinates( (qreal)(iLon) * INT2RAD, (qreal)(iLat) * INT2RAD,
211  0.0, GeoDataCoordinates::Radian, 5 ) );
212  }
213  else {
214  // qDebug(QString("header: %1 iLat: %2 iLon: %3").arg(header).arg(iLat).arg(iLon).toLatin1());
215  m_parent->last()->append( GeoDataCoordinates( (qreal)(iLon) * INT2RAD,
216  (qreal)(iLat) * INT2RAD, 0.0,
217  GeoDataCoordinates::Radian,
218  (int)(header) ) );
219  }
220  ++count;
221  }
222  munmap(src,filelength);
223  close(fd);
224 
225  // qDebug(QString("Opened %1 with %2 Polylines and %3 Points").arg(filename).arg(this->count()).arg(count).toLatin1());
226  // MMAP End
227 #else
228 # ifdef Q_OS_WIN
229 
230  // qDebug("Loading PntMap ...");
231  int count = 0;
232  QFile file( m_filename );
233 
234  file.open( QIODevice::ReadOnly );
235  QDataStream stream( &file ); // read the data serialized from the file
236  stream.setByteOrder( QDataStream::LittleEndian );
237 
238  short header;
239  short iLat;
240  short iLon;
241 
242  // Iterator that points to current PolyLine in PntMap
243  // QList<GeoPolygon*>::iterator it = begin();
244  // int count = 0;
245 
246  while( !stream.atEnd() ){
247  stream >> header >> iLat >> iLon;
248  // Transforming Range of Coordinates to iLat [0,ARCMINUTE] , iLon [0,2 * ARCMINUTE]
249 
250  if ( header > 5 ) {
251 
252  // qDebug(QString("header: %1 iLat: %2 iLon: %3").arg(header).arg(iLat).arg(iLon).toLatin1());
253  GeoPolygon *polyline = new GeoPolygon();
254  m_parent->append( polyline );
255 
256  polyline->setIndex(header);
257 
258  // Find out whether the Polyline is a river or a closed polygon
259  if ( ( header >= 7000 && header < 8000 )
260  || ( header >= 9000 && header < 20000 ) )
261  polyline->setClosed( false );
262  else
263  polyline->setClosed( true );
264 
265  polyline->append( GeoDataCoordinates( (qreal)(iLon) * INT2RAD, (qreal)(iLat) * INT2RAD,
266  0.0, GeoDataCoordinates::Radian, 5 ) );
267  }
268  else {
269  // qDebug(QString("header: %1 iLat: %2 iLon: %3").arg(header).arg(iLat).arg(iLon).toLatin1());
270  m_parent->last()->append( GeoDataCoordinates( (qreal)(iLon) * INT2RAD,
271  (qreal)(iLat) * INT2RAD, 0.0,
272  GeoDataCoordinates::Radian,
273  (int)(header) ) );
274  }
275  ++count;
276  }
277 
278  file.close();
279  // qDebug(QString("Opened %1 with %2 Polylines and %3 Points").arg(filename).arg(this->count()).arg(count).toLatin1());
280 
281 # else
282 # warning Your OS is not supported!
283 # endif
284 #endif
285 
286 
287  // To optimize performance we compute the boundaries of the
288  // polygons. To detect inside/outside we need to detect the
289  // dateline first We probably won't need this for spherical
290  // projection but for flat projection
291  //
292  // FIXME: Break this out into its own function.
293 
294  qreal lon = 0.0;
295  qreal lastLon = 0.0;
296  qreal lat = 0.0;
297 
298  GeoPolygon::PtrVector::ConstIterator itPolyLine;
299  GeoPolygon::PtrVector::ConstIterator itEndPolyLine = m_parent->constEnd();
300  GeoDataCoordinates::Vector::ConstIterator itPoint;
301 
302  // Now we calculate the boundaries
303 
304  for ( itPolyLine = m_parent->constBegin(); itPolyLine != itEndPolyLine; ++itPolyLine ) {
305 
306  qreal lonLeft = +M_PI;
307  qreal lonRight = -M_PI;
308  qreal otherLonLeft = +M_PI;
309  qreal otherLonRight = -M_PI;
310  qreal latTop = -M_PI / 2.0;
311  qreal latBottom = +M_PI / 2.0;
312 
313  bool isCrossingDateLine = false;
314  bool isOriginalSide = true;
315  int lastSign = 0;
316 
317  GeoDataCoordinates::Vector::ConstIterator itEndPoint = (*itPolyLine)->constEnd();
318 
319  for ( itPoint = (*itPolyLine)->constBegin();
320  itPoint != itEndPoint;
321  ++itPoint )
322  {
323  itPoint->geoCoordinates( lon, lat );
324 
325  int currentSign = ( lon > 0.0 ) ? 1 : -1 ;
326 
327  if( itPoint == (*itPolyLine)->constBegin() ) {
328  lastSign = currentSign;
329  lastLon = lon;
330  }
331 
332  if ( lastSign != currentSign && fabs(lastLon) + fabs(lon) > M_PI ) {
333  isOriginalSide = !isOriginalSide;
334  isCrossingDateLine = true;
335  }
336 
337  if ( isOriginalSide ) {
338  if ( lon < lonLeft ) lonLeft = lon;
339  if ( lon > lonRight ) lonRight = lon;
340  } else {
341  if ( lon < otherLonLeft ) otherLonLeft = lon;
342  if ( lon > otherLonRight ) otherLonRight = lon;
343  }
344 
345  if ( lat > latTop ) latTop = lat;
346  if ( lat < latBottom ) latBottom = lat;
347 
348  lastSign = currentSign;
349  lastLon = lon;
350  }
351 
352  if ( !isOriginalSide ) {
353  (*itPolyLine)->setDateLine( GeoPolygon::Odd );
354 // mDebug() << "Odd >> File: " << (*itPolyLine)->m_sourceFileName;
355  (*itPolyLine)->setBoundary( -M_PI, latTop, M_PI, -M_PI / 2.0 );
356 // mDebug() << " lonLeft: " << lonLeft << " lonRight: " << lonRight << " otherLonLeft: " << otherLonLeft << " otherlonRight: " << otherLonRight;
357  }
358 
359  if ( isOriginalSide && isCrossingDateLine ) {
360  (*itPolyLine)->setDateLine( GeoPolygon::Even );
361 // mDebug() << "Even >> File: " << (*itPolyLine)->m_sourceFileName << " Size: " << (*itPolyLine)->size();
362 
363 // mDebug() << " lonLeft: " << lonLeft << " lonRight: " << lonRight << " otherLonLeft: " << otherLonLeft << " otherlonRight: " << otherLonRight;
364 
365  qreal leftLonRight, rightLonLeft;
366 
367  if ( fabs( M_PI * lonRight/fabs(lonRight) - lonRight ) >
368  fabs( M_PI * otherLonRight/fabs(otherLonRight) - otherLonRight ) ) {
369  rightLonLeft = otherLonLeft;
370  leftLonRight = lonRight;
371  } else {
372  rightLonLeft = lonLeft;
373  leftLonRight = otherLonRight;
374  }
375 
376  (*itPolyLine)->setBoundary( rightLonLeft, latTop, leftLonRight, latBottom );
377 
378 // mDebug() << "Crosses: lonLeft: " << rightLonLeft << " is right from: lonRight: " << leftLonRight;
379 
380  }
381  if ( !isCrossingDateLine ) {
382  (*itPolyLine)->setDateLine( GeoPolygon::None );
383  (*itPolyLine)->setBoundary( lonLeft, latTop, lonRight, latBottom );
384  }
385  }
386 
387  mDebug() << Q_FUNC_INFO << "Loaded" << m_filename << "in" << timer.elapsed() << "ms";
388 
389  emit pntMapLoaded( true );
390 }
391 
392 #include "GeoPolygon.moc"
Marble::PntMap::load
void load(const QString &)
Definition: GeoPolygon.cpp:120
Quaternion.h
Marble::GeoDataCoordinates
A 3d point representation.
Definition: GeoDataCoordinates.h:52
Marble::GeoDataCoordinates::Radian
Definition: GeoDataCoordinates.h:65
GeoPolygon.h
Marble::PntMapLoader::PntMapLoader
PntMapLoader(PntMap *parent, const QString &filename)
Definition: GeoPolygon.cpp:139
Marble::GeoPolygon::displayBoundary
void displayBoundary()
Definition: GeoPolygon.cpp:77
Marble::GeoPolygon::setClosed
void setClosed(bool closed)
Definition: GeoPolygon.h:60
MarbleDebug.h
Marble::GeoDataCoordinates::Degree
Definition: GeoDataCoordinates.h:66
Marble::PntMap::initialized
void initialized()
Marble::GeoPolygon::getDateLine
int getDateLine() const
Definition: GeoPolygon.h:64
Marble::PntMap
Definition: GeoPolygon.h:95
Marble::PntMapLoader
Definition: GeoPolygon.h:120
Marble::GeoPolygon
Definition: GeoPolygon.h:33
Marble::GeoPolygon::setIndex
void setIndex(int index)
Definition: GeoPolygon.h:62
Marble::GeoPolygon::Even
Definition: GeoPolygon.h:56
Marble::INT2RAD
const qreal INT2RAD
Definition: PntRunner.cpp:27
Marble::PntMap::isInitialized
bool isInitialized() const
Definition: GeoPolygon.cpp:107
Marble::GeoPolygon::None
Definition: GeoPolygon.h:56
Marble::GeoPolygon::~GeoPolygon
virtual ~GeoPolygon()
Definition: GeoPolygon.cpp:45
ARCMINUTE
const qreal ARCMINUTE
Definition: GeoPolygon.cpp:35
Marble::GeoPolygon::Odd
Definition: GeoPolygon.h:56
Marble::PntMapLoader::run
void run()
Definition: GeoPolygon.cpp:145
Marble::GeoPolygon::setBoundary
void setBoundary(qreal, qreal, qreal, qreal)
Definition: GeoPolygon.cpp:51
Marble::PntMap::~PntMap
~PntMap()
Definition: GeoPolygon.cpp:112
Marble::Quaternion
Definition: Quaternion.h:43
M_PI
#define M_PI
Definition: GeoDataCoordinates.h:26
Marble::GeoPolygon::GeoPolygon
GeoPolygon()
Definition: GeoPolygon.cpp:38
Marble::PntMapLoader::pntMapLoaded
void pntMapLoaded(bool)
Marble::mDebug
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:31
Marble::PntMap::PntMap
PntMap()
Definition: GeoPolygon.cpp:101
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:38:50 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
  • kstars
  • libkdeedu
  •   keduvocdocument
  • 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