You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
QnetGateway/Location.cpp

118 lines
3.1 KiB

/*
* Copyright (C) 2020 by Thomas Early N7TAE
*
* 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 <string>
#include <regex>
#include <cmath>
#include <iostream>
#include "Utilities.h"
#include "Location.h"
CLocation::CLocation()
{
crc = std::regex("^.*([0-9]{1,2})([0-9]{2}\\.[0-9]{1,})([NS])/([0-9]{1,3})([0-9]{2}\\.[0-9]{1,})([WE]).*$", std::regex::extended);
rmc = std::regex("^.*,([0-9]{1,2})([0-9]{2}\\.[0-9]{1,}),([NS]),([0-9]{1,3})([0-9]{2}\\.[0-9]{1,}),([WE]),.*$", std::regex::extended);
}
// returns true on success
bool CLocation::Parse(const char *instr)
{
std::string s(instr);
std::cmatch cm;
trim(s);
if (0 == s.find("$$CRC")) {
std::regex_match(s.c_str(), cm, crc, std::regex_constants::match_default);
} else if ((0 == s.find("$GPGGA")) || (0 == s.find("$GPRMC"))) {
std::regex_match(s.c_str(), cm, rmc, std::regex_constants::match_default);
} else {
if ('$' == s.at(0))
std::cerr << "can't parse GPS string: " << s << std::endl;
return false;
}
auto size = cm.size();
if (size != 7) {
std::cerr << "Bad CRC Match for " << s << ":";
for (unsigned i=0; i<size; i++)
std::cerr << " [" << cm[i] << "]";
std::cerr << std::endl;
return false;
}
double deg = stod(cm[1]);
if (90.0 < deg) {
std::cout << "Latitude degree " << deg << " is out of range" << std::endl;
return false;
}
double min = stod(cm[2]);
if (60.0 < min) {
std::cout << "Latitude minutes " << min << " is out of range" << std::endl;
return false;
}
latitude = deg + min / 60.0;
if ('S' == cm[3])
latitude = 0 - latitude;
deg = stod(cm[4]);
if (180.0 < deg) {
std::cout << "Longitude degree " << deg << " is out of range" << std::endl;
return false;
}
min = stod(cm[5]);
if (60.0 < min) {
std::cout << "Longitude minutes " << min << " is out of range" << std::endl;
return false;
}
longitude = deg + min / 60.0;
if ('W' == cm[6])
longitude = 0 - longitude;
double lat = latitude + 90.0;
double lon = longitude + 180.0;
maidenhead[0] = 'A' + (int(lon) / 20);
maidenhead[1] = 'A' + (int(lat) / 10);
maidenhead[2] = '0' + ((int(lon) % 20) / 2);
maidenhead[3] = '0' + (int(lat) % 10);
maidenhead[4] = 'a' + (int(lon * 12.0) % 24);
maidenhead[5] = 'a' + (int(lat * 24.0) % 24);
maidenhead[6] = '\0';
return true;
}
double CLocation::Latitude() const
{
return latitude;
}
double CLocation::Longitude() const
{
return longitude;
}
const char* CLocation::MaidenHead() const
{
return maidenhead;
}

Powered by TurnKey Linux.