⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 maps.cpp

📁 给予QT的qps开源最新源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
   qpegps is a program for displaying a map centered at the current longitude/
   latitude as read from a gps receiver.

   Copyright (C) 2002 Ralf Haselmeier <Ralf.Haselmeier@gmx.de>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 */
#include <dirent.h> 
#include <sys/stat.h> 
#include "qpegps.h"
#include "mapdisp.h"
#include "track.h"

#include "convert.h"

const double PI_1_2 = M_PI / 2.0;
const double PI_1_4 = M_PI / 4.0;
const double PI_3_4 = M_PI * 0.75;

// ----- NON-MEMBER FUNCTIONS -----

inline double checkLg(double lon)
{
   if ( lon > M_PI ) {
      lon -= 2 * M_PI;
   } else if ( lon < -M_PI ) {
      lon += 2 * M_PI;
   }
   return lon;
}

MapSelector * MapBase::mapSelector = NULL;

// ----- METHODS ------

MapBase::MapBase(QString &, const QString &subdir)
{
   // read map info
//   mapIStream = new QTextIStream(&mapInfo);
//   *mapIStream >> mapName >> scale >> mapSizeX >> mapSizeY;
   mapDir = subdir;
}

MapBase::MapBase()
{
}

MapBase::~MapBase()
{
}

int MapBase::operator<(MapBase & map)
{
   return (scale < map.scale);
}

int MapBase::operator==(MapBase & map)
{
   return (scale == map.scale);
}

int MapBase::operator>(MapBase & map)
{
   return (scale > map.scale);
}

bool MapBase::isInside(const Position & pos)
{
//qDebug("Latitude %f < %f < %f = %d", limitSouthEast.lat, pos.lat, limitNorthWest.lat, pos.lat>=limitSouthEast.lat && pos.lat<=limitNorthWest.lat);
//qDebug("Longitude %f < %f < %f = %d", limitSouthEast.lon, pos.lon, limitNorthWest.lon, pos.lon <= limitSouthEast.lon && pos.lon >= limitNorthWest.lon);
	return (pos.lat>=limitSouthEast.lat && pos.lat<=limitNorthWest.lat &&
		pos.lon <= limitSouthEast.lon && pos.lon >= limitNorthWest.lon);
}

QString MapBase::name( void )
{
    QString fullname = mapDir + mapName;
    return( fullname );
}

MapBase *MapBase::newMap(QString &mapType, QString &mapInfo, const QString &subdir)
{
   MapBase *map;

   if(mapType == "LAMBERT")
		map = new MapLambert(mapInfo, subdir);
	else if(mapType == "CEA")
		map = new MapCEA(mapInfo, subdir);
	else if(mapType == "MERCATOR")
		map = new MapMercator(mapInfo, subdir);
	else if(mapType == "TM")
		map = new MapUTM(mapInfo,FALSE, subdir);
	else if(mapType == "UTM")
		map = new MapUTM(mapInfo,TRUE, subdir);
	else if(mapType == "LINEAR")
		map = new MapLin(mapInfo, subdir);
	else if(mapType == "FRITZ")
		map = new MapFritz(mapInfo, subdir);
	else if(mapType == "TILED")
		map = new MapTiled(mapInfo, subdir);
	else
		map = NULL;

   return map;
}

MapSelector::MapSelector(Qpegps *app/*, QString *mapPath*/)
{
   application = app;
   //	mapPathStr = mapPath;
   maps.setAutoDelete(TRUE);
   actMapList.setAutoDelete(FALSE);
   actMap = NULL;
   selectedScale = 0;
   currentMapImg = new QImage;

   MapBase::mapSelector = this;

   timer = new QTimer(this);
   connect( timer, SIGNAL(timeout()),
         SLOT(updateMapsLoaded()) ); 
   // check for non used image maps every 500 ms
   timer->start(500, false);
}

MapSelector::~MapSelector()
{
	delete currentMapImg;
}

void MapSelector::reReadMaps()
{
   application->wait(true, "Please wait: reading maps...");
   clearMaps();
   readMaps();

   emit mapsChanged();
   application->wait(false);
}

void MapSelector::readMaps( const QString &subdir )
{
   QString filename(mapPathStr());
/*   if( newSubdir != "" ) {
      newSubdir += "/";
   }*/
   filename.append( "/" + subdir + "maps.txt");
   QFile mapFile(filename);
   if ( mapFile.open(IO_ReadOnly) ) {
      application->wait(true, "Please wait: reading maps from " + filename);
      
      QTextStream t( &mapFile );
	   QString pro;
	   QString mapInfo;
	   MapBase *map;
      const QStringList& list = QStringList::split('\n', t.read());
      mapFile.close();
      QStringList::ConstIterator it;
      for(it=list.begin(); it!=list.end(); ++it) {
         const QString& s = *it;
         int sp = s.find(' ');
         pro = s.left(sp);
         mapInfo = s.right(s.length()-sp-1);
         map = MapBase::newMap(pro, mapInfo, subdir);
         // add the map
		   if (map)
			   maps.append(map);
      }
		maps.sort();
   } else if( subdir == "" ) {
		QFileInfo mfi(filename);
		QMessageBox::critical( 0, "qpeGPS",
			tr( "couldn't open \n%1\n"
			"If file does not exist it will be created.\n"
			"File info:\n"
			"exists = %2\n"
			"is readable = %3\n"
			"is a file = %4\n"
			"is a directory = %5\n"
			"is a symbolic link = %6\n"
			"owner = %7")
			.arg(filename).arg(mfi.exists())
			.arg(mfi.isReadable()).arg(mfi.isFile())
			.arg(mfi.isDir()).arg(mfi.isSymLink()).arg(mfi.owner()));
		if ( !mfi.exists() ) { 
			mapFile.open(IO_ReadWrite); 
			mapFile.close(); 
			chmod((const char*)filename,0777);
		} 
	}
   /* Now open any subfolders and search for their "maps.txt" 
   entries and add those maps as well */
   if (mapOptions.searchMapsInSubdirs) {
#ifdef __arm__
      // this approach is faster than using QDir
      DIR *d;
      struct dirent *de;
	   QString newDir = "";
      if( (d = ::opendir(mapPathStr() + "/" + subdir)) == NULL ) {
         application->wait(false);
         return;
      }
      while( (de = readdir( d )) != NULL ) {
         if (de->d_type == DT_DIR && 
            strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..")) {
            newDir = subdir + de->d_name;
		      readMaps( newDir + "/" );
         }
      }

      closedir( d);
#else
      QDir d( mapPathStr() + "/" + subdir );
	   d.setFilter( QDir::Dirs );
    //    d.setSorting( QDir::Size | QDir::Reversed );

	   const QFileInfoList *list = d.entryInfoList();
	   QFileInfoListIterator it( *list );      // create list iterator
	   QFileInfo *fi;                          // pointer for traversing

	   QString newDir = "";

    //    printf( "     BYTES FILENAME\n" );      // print header
	   while ( (fi=it.current()) ) {           // for each file...
	      if( ( fi->fileName() != "." ) && ( fi->fileName() != ".." ) ) {
            newDir = subdir + fi->fileName();
		      readMaps( newDir + "/" );
	      }
	      ++it;                               // goto next list element
	   } 
#endif
   }
   application->wait(false);
}

void MapSelector::writeMapFile()
{
   QString filename = mapPathStr();
   filename.append("/");
   filename.append("/maps.txt");
   QFile mapFile(filename);
   mapFile.open(IO_WriteOnly);
   QTextStream t(&mapFile);
   MapBase *aMap;
   for (aMap = maps.first (); aMap != 0; aMap = maps.next())
   {
       if( aMap->mapDir == "" ) /* Try to only save when the maps is recorded not in a sub folder */
	   t << aMap->getParameterStr() << "\n";
   }
   mapFile.close();
   // re-read maps for initialiting structs

   reReadMaps();
}

void MapSelector::clearMaps()
{
   actMapList.clear();
	clearMapsLoaded();
	// clear previous map list
	maps.setAutoDelete(TRUE);
	maps.clear(); // FIXME => critical for mapInfo ...
}

void MapSelector::chooseLessDetailedMap()
{
   MapBase *aMap;
    if(actMap) {
		if(actMap->scale < actMapList.last()->scale)
		{
			// if no scale selected
			if (selectedScale == 0)
				// start with the current (most detail) to search a lower detail
				selectedScale = actMap->scale;
			aMap=actMapList.first();
			while(aMap && (aMap->scale < /*actmap->scale*/selectedScale*1.1))
			{
				aMap = actMapList.next();
			}
			if(aMap)
				selectedScale = aMap->scale;
			else
				selectedScale = actMap->scale;
		}
		else
			selectedScale = actMap->scale;
    }
}

void MapSelector::chooseMoreDetailedMap()
{
    MapBase *aMap;

    if(actMap && actMap->scale > actMapList.first()->scale) {
		aMap = actMapList.last();
		while(aMap && (aMap->scale > /*actmap->scale*/selectedScale*0.9))
			aMap = actMapList.prev();
		if(aMap)
			selectedScale = aMap->scale;
    }
    else
		selectedScale = 0;
}

void MapSelector::showAvailableMaps()
{
    MapBase *aMap;

    qDebug(tr("Maps at current position:"));
    aMap = actMapList.first();
    while(aMap) {
		qDebug(tr("%1 %2").arg(aMap->scale).arg(aMap->name()));
		aMap = actMapList.next();
    }
}

void MapSelector::clearMapsLoaded()
{
   QMap<MapImage *,int>::Iterator it;
   for( it = mapsLoaded.begin(); it != mapsLoaded.end(); ++it ){
		it.key()->unload();
   }
   mapsLoaded.clear();
}

bool MapSelector::searchMap(const Position & pos/*, int maxMaps*/)
{
	MapBase *aMap;
	int numberOfChecks;
   bool mapAdded = false;
	// find map
	// and get position in map coordinates

	// check if the actual maps are still valid
	aMap = actMapList.first();
	while(aMap)
	{
		if(!aMap->isInside(pos))
		{
         actMapList.take();
			aMap = actMapList.current(); //next item
		}
		else
			aMap = actMapList.next();
	}
	// search all the list until it found a map
	numberOfChecks = maps.count();
/*	if(numberOfChecks > maxMaps)
		numberOfChecks = maxMaps;
	else if(numberOfChecks < 1)
		// less than 10 -> check all
		numberOfChecks = maps.count();*/
	aMap = maps.current();
	while(numberOfChecks)
	{
		if(aMap && aMap->isInside(pos) && !actMapList.containsRef(aMap) )
		{
			actMapList.append(aMap);
         mapAdded = true;
		}
		if(aMap)
			aMap = maps.next();
		if(!aMap)
			aMap = maps.first();
		numberOfChecks--;
	}
   if (mapAdded)
      // order the list
      actMapList.sort();

   if(actMapList.isEmpty())
		return FALSE;
	else
		return TRUE;
}

void MapSelector::selectMap(const Position & pos, QRect rect)
{
	MapBase *aMap, *theMap;
	double xc, yc, scale, cover, tcover;

	// get Map with best scale + coverage
	// list is still sorted by scale
	// scroll to the map, with appropriate scale
	aMap = actMapList.first();
	scale = aMap->scale;
	while(aMap && (aMap->scale < 0.9*selectedScale))
	{
		aMap = actMapList.next();
	};
	// all maps have a lower scale => take map with highest scale
	if(!aMap)
		aMap = actMapList.last();

	theMap = aMap;
	scale = aMap->scale;
	// get map with best coverage with approx. the same scale
	aMap->calcxy(&xc, &yc, pos);
	cover = aMap->coverage(xc, yc, rect.width(),rect.height());
	aMap = actMapList.next();
	while( aMap && (cover < -1) && (1.9 * scale > aMap->scale))
	{
		aMap->calcxy(&xc, &yc, pos);
		tcover = aMap->coverage(xc, yc, rect.width(),rect.height());
		if(tcover > cover)
		{
			theMap=aMap;
			cover = tcover;
		}
		aMap = actMapList.next();
	}

   if(theMap != actMap){
      // replace the current map
      actMap = theMap;
   }
}

bool MapSelector::loadMapImage( MapImage *map )
{
   // check if it is loaded
   if (mapsLoaded.contains(map)) {
      // already loaded, restart counter
      mapsLoaded[map] = 20; // 10 seconds
      return true;
   }
   // load the map
   if (map->load()) {
      // add tracks 
		if (application->viewTrack)
			map->addTrack(application->viewTrack, 
				application->viewTrack->trackOptions.trackColor, 
            application->viewTrack->trackOptions.track_thick);
      // all ok, add the map to the loaded map list
      mapsLoaded[map] = 20; // 10 seconds
      return true;
   }
   return false;
}

void MapSelector::drawMap(QPixmap *viewer, const Position & pos)
{
	if (searchMap(pos)) {
		selectMap(pos, viewer->rect());
		
		// draw the map
		actMap->draw(viewer, pos);
	}
	else {
      actMap = NULL;
   }
}

double MapBase::coverage(double x, double y, int width, int height)
{
    // determines the area on the display, which is not covered by the Map
    // 0 = map fills the display
    // <0 = -1 * pixels without map

   double tmp = mapSizeX - x;
   double coverX = ( x > tmp ) ? tmp : x;
   tmp = mapSizeY - y;
   double coverY = ( y > tmp ) ? tmp : y;
   coverX -= width / 2;
   coverY -= height / 2;
   coverX = ( coverX > 0 ) ? 0 : coverX * height;
   coverY = ( coverY > 0 ) ? 0 : coverY * width;

   return coverX + coverY;
}

void MapSelector::updateMapsLoaded()
{
   QMap<MapImage *,int>::Iterator it;
   MapImage *deleteMap = NULL;
   for( it = mapsLoaded.begin(); it != mapsLoaded.end(); ++it ){
      if (deleteMap != NULL) {
         mapsLoaded.remove(deleteMap);
         deleteMap = NULL;
      }
      int counter = it.data() -1;
      if (counter) {
         // update value
         mapsLoaded[it.key()] = counter;
      }
      else {
         deleteMap = it.key();
         deleteMap->unload();
      }
   }
   if (deleteMap != NULL)
      mapsLoaded.remove(deleteMap);
}

MapBase *MapSelector::find( QString &mapName )
{
   MapBase *map;
   for (map = maps.first(); map != 0; map = maps.next()) {
      if (map->name() == mapName)
         return map;
   }
   // not found
   return NULL;
}

void MapSelector::delMap( MapBase *delmap )
{
   if (actMapList.find(delmap))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -