📄 track.cpp
字号:
/*
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 "track.h"
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "convert.h"
// write config file
#define WRITE_CONFIG application->writeConfig()
// ----- NON-MEMBER FUNCTIONS -----
/*
* move to next comma separated field
*/
char * nextfield(const char * s)
{
char * r = strchr(s, ',');
return ( ( r ) ? (r + 1) : NULL );
}
/*
* calculate NMEA checksum
*/
void checksumNMEA(QString * ns)
{
const char * n = ns->latin1();
unsigned checksum = n[1];
QString nend;
for ( unsigned int i = 2; i < strlen(n); ++i ) {
checksum ^= (unsigned int)n[i];
}
nend.sprintf("*%02x\r\n", checksum);
ns->append(nend);
}
/*
* convert (char*) "hh:mm:ss" to (double) hhmmss
*/
double tmstr2double(const char * str)
{
int h, m, s;
sscanf(str, "%d:%d:%d", &h, &m, &s);
return (double)(3600 * h + 60 * m + s);
}
/*
* convert (double) hhmmss to (char*) "hh:mm:ss"
*/
void tmdouble2str(double tm, char * str) {
int h = (int)(tm) / 3600;
int m = (int)(tm) / 60 - 60 * h;
int s = (int)(tm) % 60;
sprintf(str, "%02d:%02d:%02d", h, m, s);
}
// ----- METHODS -----
/*********************************************************************
* TRACKPOINT constructor - create trackpoint from various formats
*********************************************************************/
TrackPoint::TrackPoint(QString * nmea)
{
const char * str = nmea->latin1();
switch ( *str )
{
case '$':
{
// assuming NMEA GPGGA messages
double lon, lat, hdop;
char lonsign, latsign, *s = (char *)str;
int status, sats;
s = nextfield(s); time = atof(s);
s = nextfield(s); lat = atof(s);
s = nextfield(s); latsign = *s;
s = nextfield(s); lon = atof(s);
s = nextfield(s); lonsign = *s;
s = nextfield(s); status = atoi(s);
s = nextfield(s); sats = atoi(s);
s = nextfield(s); hdop = atof(s);
s = nextfield(s); altitude = atof(s);
pos.lat = floor(lat / 100)
+ (lat - floor(lat / 100) * 100) / 60;
pos.lon = floor(lon / 100)
+ (lon - floor(lon / 100) * 100) / 60;
if ( latsign == 'S' ) {
pos.lat *= -1.0;
}
if ( lonsign == 'W' ) {
pos.lon *= -1.0;
}
break;
}
case 'T':
{
// assuming PCX5 format
char tm[20], dt[20];
sscanf(str, "T %lf %lf %s %s %lf", &pos.lat, &pos.lon,
dt, tm, &altitude);
time = tmstr2double(tm);
break;
}
case ' ':
case '-':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
// assuming gpsdrive format
char t[5][20];
sscanf(str, "%lf %lf %lf %s %s %s %s %s",
&pos.lat, &pos.lon, &altitude,
t[0], t[1], t[2], t[3], t[4]);
for ( int i = 0; i < 5; ++i ) {
if ( strchr(t[i], ':') ) {
// looking for time
time = tmstr2double(t[i]);
}
}
break;
}
default:
qWarning(tr("unknown trackpoint format"));
break;
}
}
/*
* create trackpoint from real values
*/
TrackPoint::TrackPoint(QString tim, double lat, double lon, double alt)
{
time = tmstr2double((char *)tim.latin1());
pos.lat = lat;
pos.lon = lon;
altitude = alt;
}
/*
* create NMEA GGA message from the trackpoint
*/
QString TrackPoint::toNMEA()
{
// latitude
double lat = fabs(pos.lat);
char tsign = ( pos.lat > 0 ) ? 'N' : 'S';
double tdeg = floor(lat);
double tmin = (lat-tdeg)*60.0;
// longitude
double lon = fabs(pos.lon);
char nsign = ( pos.lon > 0 ) ? 'E' : 'W';
double ndeg = floor(lon);
double nmin = (lon - ndeg) * 60.0;
QString nmea;
nmea.sprintf(
"$GPGGA,%010.3f,%02d%07.4f,%c,%02d%07.4f,%c,1,0,0,%d,M,,,,0000",
time, (int)tdeg, tmin, tsign,
(int)ndeg, nmin, nsign, (int)altitude);
checksumNMEA(&nmea);
return nmea;
}
/*
* create Garmin PCX5 message for the trackpoint
*/
QString TrackPoint::toPCX5()
{
char tm[20];
tmdouble2str(time, tm);
// TODO: date
QString pcx;
pcx.sprintf(
"T %+09.6f %+09.6f %s %s %4d\n",
pos.lat, pos.lon, "00-JAN-00", tm, (int)altitude);
return pcx;
}
/*
* create gpsdrive trackpoint
*/
QString TrackPoint::toDrive()
{
char tm[20];
tmdouble2str(time,tm);
// TODO: date
QString drive;
drive.sprintf(
"%9.6f %9.6f %4d %s\n",
pos.lat, pos.lon, (int)altitude, tm);
return drive;
}
/*
* return distance from given point in a strange metric (degree based)
*/
double TrackPoint::dist(Position & p)
{
return fabs(pos.lat - p.lat)
+ fabs(pos.lon - p.lon);
}
/*
* return time difference from given point in seconds
*/
double TrackPoint::timediff(const QString & tim)
{
// int h, m, s;
// sscanf(tim.latin1(), "%d:%d:%d", &h, &m, &s);
return fabs(time - tmstr2double(tim));
}
/*********************************************************************
* TRACK constructor - set default values, create widgets
*********************************************************************/
void Track::placeSelected(int ind)
{
if ( ind ) {
Place *place = places->at(ind);
commMLE->setText(place->comment);
}
}
void Track::delPlace()
{
int ind = mapLatLonCB->currentItem();
if (ind) {
mapLatLonCB->removeItem(ind);
commMLE->setText("");
mapLatLonCB->setCurrentItem(0);
places->remove(ind);
places->writePlaces(trackOptions.trackPathStr + "/places.txt");
if (placesOptions->showPlaces)
emit waypointsChanged();
}
}
void Track::updateConfig()
{
tLE->setText(trackOptions.trackPathStr);
dLE->setText(QString::number(trackOptions.updt_freq));
lMenuB->select(trackOptions.track_thick - 1);
placesTB->setChecked(placesOptions->showPlaces);
textSizeSB->setValue(placesOptions->placesTextSize);
// update Places
updatePlaces();
// update track lists
updateFileList();
}
Track::Track(Qpegps * appl, PlacesOptions *placesOpts,
QWidget * parent, const char * name, WFlags f)
: QScrollView(parent, name, f), placesOptions(placesOpts),
application(appl), wDo(false), rDo(false)
{
logdir = new QDir();
logdir->setNameFilter("[^.]*");
setHScrollBarMode(AlwaysOff);
setVScrollBarMode(Auto);
QVBox * mainBox = new QVBox(this);
addChild(mainBox);
setResizePolicy(AutoOneFit);
QHBox * hBox = new QHBox(mainBox);
QVGroupBox * PlaceGB = new QVGroupBox(tr("Places"), hBox);
hBox = new QHBox(PlaceGB);
mapLatLonCB = new QComboBox(hBox);
connect( mapLatLonCB, SIGNAL(activated(int)),
this, SLOT(placeSelected(int)) );
QPushButton * QDelButt = new QPushButton("Delete", hBox);
connect(QDelButt, SIGNAL(pressed()), SLOT(delPlace()));
hBox = new QHBox(PlaceGB);
commMLE = new QMultiLineEdit(hBox);
commMLE->setWordWrap(QMultiLineEdit::WidgetWidth);
commMLE->setWrapPolicy(QMultiLineEdit::Anywhere);
commMLE->setReadOnly(TRUE);
commMLE->setFixedVisibleLines(2);
// Show places
hBox = new QHBox(PlaceGB);
placesTB = new QCheckBox(hBox);
placesTB->setText(tr("Show places"));
placesTB->setChecked(placesOptions->showPlaces);
QLabel * textSizeL = new QLabel(tr("Text Size"), hBox);
textSizeL->setAlignment(AlignRight | AlignVCenter);
textSizeSB = new QSpinBox(4, 30, 1, hBox, "Text Size");
textSizeSB->setValue(placesOptions->placesTextSize);
connect(placesTB, SIGNAL(toggled(bool)),
SLOT(setShowPlacesTB(bool)));
connect( textSizeSB , SIGNAL(valueChanged(int)),
SLOT(setPlacesTextSize(int)) );
(void)new QLabel(
tr( " - TRACKLOG is saved when unchecking write checkbox\n"
" - (re)select map to display track in Info"), mainBox);
// create field for track directory
QHBox * tBox = new QHBox(mainBox);
// tBox->setMargin(2);
(void)new QLabel(tr("Track dir: "), tBox);
tLE = new QLineEdit(tBox);
QPushButton * tButton = new QPushButton(tr("search"), tBox);
tLE->setText(trackOptions.trackPathStr);
connect(tButton, SIGNAL(pressed()), SLOT(setTrackPath()));
connect(tLE, SIGNAL(returnPressed()), SLOT(tLEChanged()));
// create checkboxes and comboboxes for tracklog files
QHBox * wBox = new QHBox(mainBox);
// wBox->setMargin(2);
QCheckBox * wCB = new QCheckBox(wBox);
// wBox->setMargin(2);
(void)new QLabel(tr("write "), wBox);
wLog = new QComboBox(true, wBox, tr("write_log_filename"));
connect(wCB, SIGNAL(toggled(bool)), SLOT(setWriteCB(bool)));
QHBox * rBox = new QHBox(mainBox);
// rBox->setMargin(2);
QCheckBox * rCB = new QCheckBox(rBox);
(void)new QLabel(tr("read "), rBox);
rLog = new QComboBox(true, rBox, tr("read_log_filename"));
connect(rCB, SIGNAL(toggled(bool)), SLOT(setReadCB(bool)));
connect(rLog, SIGNAL(activated(const QString &)),
SLOT(setReadName(const QString &)));
updateFileList();
// minimal time difference between 2 positions
QHBox * dBox = new QHBox(mainBox);
// dBox->setMargin(2);
(void)new QLabel(tr("min time difference [s] "), dBox);
dLE = new QLineEdit(dBox);
QString buf;
buf.sprintf("%d", trackOptions.updt_freq);
dLE->setText(buf);
connect(dLE, SIGNAL(returnPressed()), SLOT(dLEChanged()));
#ifndef DESKTOP
// track line thickness
QStringList thickList;
thickList << "1" << "2" << "3" << "4" << "5";
QHBox * lBox = new QHBox(mainBox);
// lBox->setMargin(2);
(void)new QLabel(tr("line thickness"), lBox);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -