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

📄 mapdisp.cpp

📁 给予QT的qps开源最新源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*
 ** $Id: mapdisp.h 236 2006-11-12 10:20:24Z ztep $

  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 "mapdisp.h"

#include <math.h>
#include <qdatetime.h>
#include <qpopupmenu.h>

#include "convert.h"

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

double calcAngle(Position & dest, Position & src) // angle in degrees
{
   double angle;
   double cos_dlat = cos(deg2rad(dest.lat));
   double sin_dlat = sin(deg2rad(dest.lat));
   double cos_dlon = cos(deg2rad(dest.lon));
   double sin_dlon = sin(deg2rad(dest.lon));
   double cos_slat = cos(deg2rad(src.lat));
   double sin_slat = sin(deg2rad(src.lat));
   double cos_slon = cos(deg2rad(src.lon));
   double sin_slon = sin(deg2rad(src.lon));
   double a = acos(
         cos_slat * (cos_dlat * square(cos_slon) + cos_dlat * square(sin_slon))
         + sin_dlat * sin_slat
         ) * 6378;
   double b = acos(
         square(cos_slat) * (cos_dlon * cos_slon + sin_dlon * sin_slon)
         + square(sin_slat)
         ) * 6378;

   if ( (a != 0) || (b != 0) ) {
      angle = rad2deg(acos(a / sqrt(square(a) + square(b))));
      if ( dest.lon < src.lon ) {
         angle += 180;
         if ( dest.lat > src.lat ) {
            angle = (360 + 180) - angle;
         }
      } else if ( dest.lat < src.lat ) {
         angle = 180 - angle;
      }
   } else {
      angle = 0;
   }
   return angle;
}

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

MapDisp::MapDisp(Qpegps * app, MapSelector * maps, GpsData *gps,
      QWidget * parent, const char *name, WFlags f)
   : QWidget (parent, name, f | WRepaintNoErase), 
   app(app), gpsData(gps), places(app->places),  
   mapSelector(maps), centerX(0), centerY(0), 
   mapOrientation(0), accDist(0),
   placesIt(*places), ManualWp(false), 
   ttwph(0), ttwpm(0), ttwps(0),
    WriteTimeout(1200), FirstKey(true)
{
   mapdisp = new QPixmap;

   placesIt.toFirst();
   // skip "none"
   ++placesIt;
   
   mapDispOptions.textSize = 10;
   placesOptions.placesTextSize = 10;
   setBackgroundMode(NoBackground);

   createMap();

   timer = new QTimer(this);
   connect( timer, SIGNAL(timeout()), this, SLOT(timerDone()) );

	aniTimer = new QTimer( this );
	connect( aniTimer, SIGNAL(timeout()), 
      this, SLOT(animateTrack()));

   connect( this, SIGNAL(lessDetail()), 
      mapSelector, SLOT(chooseLessDetailedMap()) );
   connect( this, SIGNAL(moreDetail()), 
      mapSelector, SLOT(chooseMoreDetailedMap()) );
   connect( this, SIGNAL(debugMaps()), 
      mapSelector, SLOT(showAvailableMaps()) );
   connect( this, SIGNAL(waypointsChanged()), 
      mapSelector, SLOT(clearMapsLoaded()) );

   setFocusPolicy(QWidget::StrongFocus);
   setFocus();  
   //WTconunter = 0;
   WTTimer = time(NULL);

#ifndef DESKTOP
   // enables Right click on hold.
   QPEApplication::setStylusOperation (this, QPEApplication::RightOnHold);
#endif
   inAnimation = false;
}

void MapDisp::createMap()
{
   static QSize geoSize(0,0);
   QPainter painter;
   double xc, yc;

   if ( FirstKey ){
      emit mouseClick(this);
      emit mouseClick(this);
      FirstKey = false;
   }

   /* Debug only */
//   gpsData->fix.position.lon = -4.744162;
//   gpsData->fix.position.lat = 42.799525;
   /* Debug only */
   
   QSize newSize = geometry().size();
   if (newSize != geoSize) {
      mapdisp->resize(newSize);
      geoSize = newSize;
   }
	if ( app->viewTrack && (time(NULL)-WTTimer) >= WriteTimeout ){ 
		app->viewTrack->Write(app->viewTrack->wLog->currentText());
		WTTimer=time(NULL); 
	}


   if (!mapDispOptions.mode) {
      currentPos.lat = gpsData->fix.position.lat;
      currentPos.lon = gpsData->fix.position.lon;
      currentAltitude.val = gpsData->fix.altitude.val;
   }

   if (mapDispOptions.rotateMap && !mapDispOptions.mode) {
      if (gpsData->fix.speed.val > 0.7) {
         mapOrientation = -gpsData->fix.heading.val;
      }
      int ns;
      if (mapDispOptions.zoom2x)
         ns = (int) (sqrt((newSize.width()*newSize.width()+newSize.height()*newSize.height()))/2);
      else
         ns = (int) sqrt(newSize.width()*newSize.width()+newSize.height()*newSize.height());

      QPixmap pm(ns, ns);
		// get the map
		pm.fill();
		mapSelector->drawMap(&pm, currentPos);
		// zoom the map
		QWMatrix m;
      if (mapDispOptions.zoom2x)
         m.scale(2, 2);
      m.rotate(mapOrientation);
      pm = pm.xForm(m);
      int ix = (pm.width()-newSize.width())/2;
      int iy = (pm.height()-newSize.height())/2;
      bitBlt(mapdisp, 0, 0, &pm, ix, iy, newSize.width(), newSize.height());
   }
   else if (mapDispOptions.zoom2x) {
      QPixmap pm((newSize.width()+1)/2, (newSize.height()+1)/2);
		// get the map
		pm.fill();
		mapSelector->drawMap(&pm, currentPos);
		// zoom the map
		QWMatrix m;
		m.scale(2, 2);
      //m.rotate(0.01); 
      pm = pm.xForm(m);
      bitBlt(mapdisp, 0, 0, &pm, 0, 0, newSize.width(), newSize.height());
	} 
	else {
		mapdisp->fill();
		// get the map
		mapSelector->drawMap(mapdisp, currentPos);
	}

   if ( mapSelector->isMap() ) {
      mapSelector->currentMap()->calcxy(&xc, &yc, currentPos);
      centerX=(int)rint(xc);	/* Added by A. Karhov */
      centerY=(int)rint(yc);
   }


   painter.begin(mapdisp);
   QPen p=painter.pen();
   p.setWidth(1);
   statColor = ( gpsData->status ) ?
      mapDispOptions.statusOkColor : mapDispOptions.statusNoFixColor;
   p.setColor(statColor);
   painter.setPen(p);

	int xcenter = mapdisp->width()/2;
	int ycenter = mapdisp->height()/2;
   if( xcenter < ycenter )
      lgth = xcenter/6;
   else
      lgth = ycenter/6;

   if (placesOptions.showPlaces)
      DrawPlaces(&painter);

   if ( mapSelector->isMap() )
      DrawScaleLine(&painter);

	DrawStatus(&painter);

   if ( !mapDispOptions.mode ){ // GPS mode

		DrawCross(&painter);

		if(mapDispOptions.showBearing)
			DrawBearingLine(&painter);
		
		if(mapDispOptions.showHeading)
			DrawHeading(&painter);
	}

   painter.end();
}

void MapDisp::DrawStatus(QPainter *painter)
{
	QRect rect = mapdisp->rect();

	QFont f=painter->font();
   f.setPointSize(mapDispOptions.textSize);
   painter->setFont(f);
   QPen p=painter->pen();
   //    p.setWidth(1);
   p.setColor(statColor);

   painter->setPen(p);

   painter->drawText(rect, AlignVCenter | AlignLeft,
         Position::string(currentPos.lat, Position::Lat));
   painter->drawText(rect, AlignVCenter | AlignRight,
         Position::string(currentPos.lon, Position::Lon));

   if( gpsData->statusStr.length() > 0)
      painter->drawText(rect, AlignVCenter | AlignHCenter, gpsData->statusStr);
   else if ( mapDispOptions.mode )
   {
	   painter->drawText(rect, AlignVCenter | AlignHCenter, "X");
      if ( inAnimation ) {
			int tx=aniTime/(60*60*1000);
			int ty=(aniTime-tx*(60*60*1000))/60000; 
			int th=(aniTime-tx*(60*60*1000)-ty*60000)/1000;
         painter->drawText(rect, AlignBottom | AlignHCenter,
					  tr("%1:%2:%3")
				  .arg(tx, 2)
				  .arg(ty, 2)
				  .arg(th, 2));
      }
   }
   else
   {
      if ( mapSelector->scale() > 1 ) { // != 0
			QString mapSelectString;
         if ( mapSelector->canLessDetail() ) {
            mapSelectString.append(tr("-/"));
         } else {
            mapSelectString.append(tr(" /"));
         }
         if ( mapSelector->canMoreDetail() ) {
            mapSelectString.append(tr("+"));
         } else {
            mapSelectString.append(tr("D"));
         }
			//if(mapSelector->istMap()) // only for debugging, don't forget to remove this !!!!
			//QTextOStream(&mapSelectString) << mapSelectString << mapSelector->currentMap()->scale << " " << selectedScale;
			painter->drawText(rect, AlignTop | AlignLeft, mapSelectString);
		}

      Angle Bearing(gpsData->fix.bearing);
      if ( ManualWp ) {
       //  if (gpsData->wpDistance.distUnit != Distance::None) dist.distUnit=gpsData->wpDistance.distUnit;
       //  else dist.distUnit=Distance::Km;
         double latr = deg2rad(currentPos.lat);
         double lonr = deg2rad(currentPos.lon);
         double destlatr = deg2rad(dest.lat);
         double destlonr = deg2rad(dest.lon);
         wpDistance.val = acos(
               cos(destlatr) * cos(destlonr) * cos(latr) * cos(lonr)
               + cos(destlatr) * sin(destlonr) * cos(latr) * sin(lonr)
               + sin(destlatr) * sin(latr)) * 6378;
         wpDistance.val /= 1.852; // Conversion from km to GPS distance units (Nautical mile)
         // FIXME: wrap Bearing with deg2rad (like others instances)?
         Bearing.val = calcAngle(dest, currentPos);
      }
      painter->drawText( rect, AlignTop | AlignHCenter,
            currentAltitude.toString(false) );
      painter->drawText( rect, AlignBottom | AlignHCenter,
            tr("%1 %2\n%3 %4 %5").arg(gpsData->fix.heading.toString())
            .arg(gpsData->fix.speed.toString())
            .arg(Bearing.toString())
            .arg(wpDistance.toString())
            .arg(timeToString()) );
   }
}

void MapDisp::DrawCross(QPainter *painter)
{
	int xcenter = mapdisp->width()/2;
	int ycenter = mapdisp->height()/2;

    //cross
   QPen p= painter->pen();
	p.setWidth(1);
   painter->setPen(p);

   painter->drawLine(xcenter, ycenter, xcenter, ycenter + lgth );
   painter->drawLine(xcenter - lgth, ycenter , xcenter + lgth, ycenter );

	p.setWidth(2);
   painter->setPen(p);
   painter->drawLine(xcenter, ycenter - lgth , xcenter, ycenter);
}

void MapDisp::DrawHeading(QPainter *painter)
{
	// heading line
	int xcenter = mapdisp->width()/2;  /* Added by A. Karhov */
	int ycenter = mapdisp->height()/2;

	int tx, ty, tw,th;

   double headingAngle = gpsData->fix.heading.val;
   if (mapDispOptions.rotateMap)
      headingAngle += mapOrientation;

	tx = xcenter;
	ty = ycenter;
	tw = xcenter + (int)((double)(sin(deg2rad(headingAngle))
								  *(double)lgth*2.0));
	th = ycenter - (int)((double)(cos(deg2rad(headingAngle))
								  *(double)lgth*2.0));
	QPen p=painter->pen();
	p.setColor(mapDispOptions.headColor);
	p.setWidth(3);
	painter->setPen(p);
	painter->drawLine(tx,ty,tw,th);

#if 1
	int tw1, th1, tw2, th2;  
   // draw arrow, 
	tw1 = xcenter + (int)((double)(sin(deg2rad(headingAngle+120))
								  *(double)lgth*1.0));
	th1 = ycenter - (int)((double)(cos(deg2rad(headingAngle+120))
								  *(double)lgth*1.0));
	tw2 = xcenter + (int)((double)(sin(deg2rad(headingAngle-120))
								  *(double)lgth*1.0));
	th2 = ycenter - (int)((double)(cos(deg2rad(headingAngle-120))
								  *(double)lgth*1.0));
	p.setWidth(2);
	painter->setPen(p);
	painter->drawLine(tx,ty,tw1,th1);
	painter->drawLine(tx,ty,tw2,th2);
	painter->drawLine(tw,th,tw1,th1);
	painter->drawLine(tw,th,tw2,th2);
#endif
}

void MapDisp::DrawBearingLine(QPainter *painter)
{
   double xwp=0,ywp=0;
   int tx = 0, ty = 0; 

   int xcenter = mapdisp->width()/2;
	int ycenter = mapdisp->height()/2;

   int halflgth = lgth / 2;

   if ( mapSelector->isMap() ) {
      // current waypoint
      Position wp;

⌨️ 快捷键说明

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