mirror of
https://github.com/ea4k/klog.git
synced 2024-09-21 10:28:06 +00:00
360 lines
11 KiB
C++
360 lines
11 KiB
C++
/***************************************************************************
|
|
locator.cpp - description
|
|
-------------------
|
|
begin : vie feb 7 2003
|
|
copyright : (C) 2003 by Jaime Robles
|
|
email : jaime@robles.es
|
|
***************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
* This file is part of KLog. *
|
|
* *
|
|
* KLog 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 3 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* KLog 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 KLog. If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
#include "locator.h"
|
|
#include <QtDebug>
|
|
|
|
Locator::Locator(){
|
|
ideg = 0;
|
|
imin = 0;
|
|
isec = 0;
|
|
}
|
|
|
|
Locator::~Locator(){
|
|
}
|
|
|
|
bool Locator::isValidLocator(const QString& tlocator){
|
|
/* -------------- Subroutine -----------------------
|
|
Check valid locator (VALID: AA00AA -> RR99XX
|
|
Input : char *locator = 4 or 6 characters word wide locator.
|
|
returned value == -1 No error. (Valid locator).
|
|
returned value == 0 Error. (Invalid locator).
|
|
Note: also string "END" is considered a valid locator, but returned value is -2.
|
|
------------------------------------------------- */
|
|
//qDebug() << "Locator::isValidLocator: " << tlocator << endl;
|
|
|
|
int lenght_of_locator;
|
|
testLocator ="A";
|
|
testLocator = tlocator.toUpper();
|
|
lenght_of_locator = testLocator.length();
|
|
|
|
if (lenght_of_locator == 4){
|
|
testLocator = testLocator +"LM";
|
|
lenght_of_locator = 6;
|
|
}
|
|
|
|
if (lenght_of_locator != 6) {
|
|
return false;
|
|
}else{
|
|
theChar = testLocator.at(0);
|
|
if (!theChar.isLetter()){ //First letter is not a valid letter
|
|
|
|
return false;
|
|
}
|
|
if ((theChar<'A') && (theChar>'R') ){ //First letter is not a valid letter
|
|
|
|
return false;
|
|
}
|
|
theChar = testLocator.at(1);
|
|
if (!theChar.isLetter()){ //Second letter is not a valid letter
|
|
|
|
return false;
|
|
}
|
|
if ((theChar<'A') && (theChar>'R') ){ //Second letter is not a valid letter
|
|
|
|
return false;
|
|
}
|
|
theChar = testLocator.at(2);
|
|
if (!theChar.isDigit()){ //Second letter is not a number
|
|
|
|
return false;
|
|
}
|
|
theChar = testLocator.at(3);
|
|
if (!theChar.isDigit()){ //Second letter is not a number
|
|
|
|
return false;
|
|
}
|
|
theChar = testLocator.at(4);
|
|
if (!theChar.isLetter()){ //First letter is not a valid letter
|
|
|
|
return false;
|
|
}
|
|
if ((theChar<'A') && (theChar>'X') ){ //First letter is not a valid letter
|
|
|
|
return false;
|
|
}
|
|
theChar = testLocator.at(5);
|
|
if (!theChar.isLetter()){ //Second letter is not a valid letter
|
|
|
|
return false;
|
|
}
|
|
if ((theChar<'A') && (theChar>'X') ){ //Second letter is not a valid letter
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
double Locator::getLat(const QString& tlocator){
|
|
//qDebug() << "Locator::getLat: " << tlocator;
|
|
|
|
if (!isValidLocator(tlocator))
|
|
{
|
|
return 0.0;
|
|
}
|
|
|
|
if (tlocator.length() == 2)
|
|
{
|
|
return (((tlocator.at(1)).toLatin1() - 65) * 10) - 90;
|
|
}
|
|
if (tlocator.length() == 4)
|
|
{
|
|
return (((tlocator.at(1)).toLatin1() - 65) * 10) + ((tlocator.at(3)).toLatin1() - 48) - 90;
|
|
}
|
|
else if (tlocator.length()== 6)
|
|
{
|
|
return (((tlocator.at(1)).toLatin1() - 65) * 10) + ((tlocator.at(3)).toLatin1() - 48) + (((tlocator.at(5)).toLatin1() - 65 + 0.5) / 24) - 90;
|
|
}
|
|
else
|
|
{
|
|
return 0.0;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
double Locator::getLon(const QString& tlocator)
|
|
{
|
|
//qDebug() << "Locator::getLon: " << tlocator;
|
|
|
|
if (!isValidLocator(tlocator))
|
|
{
|
|
return 0.0;
|
|
}
|
|
|
|
if (tlocator.length() == 2)
|
|
{
|
|
return (((tlocator.at(0)).toLatin1() - 65) * 20) - 180;
|
|
}
|
|
|
|
if (tlocator.length() == 4)
|
|
{
|
|
return (((tlocator.at(0)).toLatin1() - 65) * 20) + (((tlocator.at(2)).toLatin1() - 48) * 2) - 180;
|
|
}
|
|
else if (tlocator.length()== 6)
|
|
{
|
|
return (((tlocator.at(0)).toLatin1() - 65) * 20) + (((tlocator.at(2)).toLatin1() - 48) * 2) + (((tlocator.at(4)).toLatin1() - 65 + 0.5) / 12) - 180;
|
|
}
|
|
else
|
|
{
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
int Locator::getBeam(const double lon1, const double lat1, const double lon2, const double lat2){
|
|
double lon_a,lat_a,lon_b,lat_b, bearing;
|
|
//qDebug() << "Locator::getBeam1: " << QString::number(lon1) << "/" << QString::number(lat1) << endl;
|
|
//qDebug() << "Locator::getBeam2: " << QString::number(lon2) << "/" << QString::number(lat2) << endl;
|
|
|
|
|
|
lon_a=lon1*PI/180; // Convert degrees to radians
|
|
lat_a=lat1*PI/180;
|
|
lon_b=lon2*PI/180;
|
|
lat_b=lat2*PI/180;
|
|
|
|
//earing_Distance( double lon_a, double lat_a, /* Lon/Lat of point A */
|
|
// double lon_b, double lat_b, /* Lon/Lat of point B */
|
|
// double *bearing, double *distance )/* From A to B */
|
|
//{
|
|
double
|
|
gc_arc, cos_gc_arc, /* Great circle arc A to B */
|
|
cos_bearing, sin_bearing, /* cos/sin of bearing A to B */
|
|
lon_diff; /* Difference in longitude of B from A */
|
|
|
|
/* Longitude differnce of B from A */
|
|
lon_diff = lon_b - lon_a;
|
|
|
|
/* Calculate great circle distance A to B */
|
|
cos_gc_arc = cos(lon_diff)*cos(lat_a)*cos(lat_b) + sin(lat_a)*sin(lat_b);
|
|
gc_arc = acos( cos_gc_arc );
|
|
|
|
/* Distance in km */
|
|
// *distance = eradius * gc_arc;
|
|
|
|
/* Calculate bearing A to B */
|
|
cos_bearing = sin(lat_b) - sin(lat_a) * cos_gc_arc;
|
|
sin_bearing = sin(lon_diff) * cos(lat_a) * cos(lat_b);
|
|
bearing = atan2(sin_bearing, cos_bearing);
|
|
|
|
/* Correct negative (anticlockwise) bearings */
|
|
|
|
if( bearing < 0.0 )
|
|
{
|
|
bearing = (2*PI) + bearing;
|
|
}
|
|
bearing = 360 - (180/PI*bearing);
|
|
bearing = 360 - bearing;
|
|
|
|
//qDebug() << "Locator::getBeam: " << QString::number(bearing) << endl;
|
|
/* Convert to degrees */
|
|
|
|
return (int)bearing;
|
|
|
|
}
|
|
|
|
int Locator::getDistance(const double lon1, const double lat1, const double lon2, const double lat2, const bool _imperialSystem){
|
|
//http://en.wikipedia.org/wiki/Haversine_formula
|
|
//qDebug() << "Locator::getDistanceKilometres: MyPos("<< QString::number(lon1) << "/"
|
|
// << QString::number(lat1) << ") - DxPos(" << QString::number(lon2) << "/" << QString::number(lat2) << ")" << endl;
|
|
double lo1,la1,lo2,la2;
|
|
|
|
// TODO: Is it needed to check if the longitude and latitude are correct and/or between the magins?
|
|
// if (!( (checkCoords(lon1, lat1) ) && (checkCoords(lon2, lat2)) ))
|
|
// return 0;
|
|
|
|
lo1=lon1* DEG_TO_RAD; // Convert degrees to radians
|
|
la1=lat1* DEG_TO_RAD;
|
|
lo2=lon2* DEG_TO_RAD;
|
|
la2=lat2* DEG_TO_RAD;
|
|
|
|
if (!_imperialSystem){
|
|
//qDebug() << "Locator::getDistance (Km): " << QString::number((int)(acos(cos(la1)*cos(lo1)*cos(la2)*cos(lo2)+cos(la1)*sin(lo1)*cos(la2)*sin(lo2)+sin(la1)*sin(la2)) * EARTH_RADIUS)) << endl;
|
|
return (int)(acos(cos(la1)*cos(lo1)*cos(la2)*cos(lo2)+cos(la1)*sin(lo1)*cos(la2)*sin(lo2)+sin(la1)*sin(la2)) * EARTH_RADIUS);
|
|
}else{ // In milles
|
|
//qDebug() << "Locator::getDistance (Milles): " << QString::number(((int)(acos(cos(la1)*cos(lo1)*cos(la2)*cos(lo2)+cos(la1)*sin(lo1)*cos(la2)*sin(lo2)+sin(la1)*sin(la2)) * EARTH_RADIUS))* 0.62137) << endl;
|
|
return ((int)(acos(cos(la1)*cos(lo1)*cos(la2)*cos(lo2)+cos(la1)*sin(lo1)*cos(la2)*sin(lo2)+sin(la1)*sin(la2)) * EARTH_RADIUS)) * 0.62137;
|
|
}
|
|
}
|
|
|
|
|
|
bool Locator::checkCoords(const double lon1, const double lat1){
|
|
//qDebug() << "Locator::checkCoords" ;
|
|
// Checks if a coordinates is correct.
|
|
if ((lat1 > 90.0 || lat1 < -90.0) && (lon1 > 180.0 || lon1 < -180.0)){
|
|
return true;
|
|
}else{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
QString Locator::getLocator(const double lon1, const double lat1) const{
|
|
/* -------------- Subroutine -----------------------
|
|
Calculate locator from longitude and latitude
|
|
Input : lon = Longitude in decimal degrees (+ = West; - = East).
|
|
lat = Latitude in decimal degrees (+ = North; - = South).
|
|
Output: locator = 6 characters world wide locator.
|
|
------------------------------------------------- */
|
|
//qDebug() << "Locator::getLocator: (" << QString::number(lon1) << "/" << QString::number(lat1) << ")" << endl;
|
|
QString locat = ""; //NO locator
|
|
|
|
double lo, la;
|
|
int alo,bla,clo,dla,elo,fla;
|
|
|
|
lo=(-lon1+180)/20;
|
|
la = (lat1+90)/10;
|
|
|
|
alo=(int)floor(lo);
|
|
bla=(int)floor(la);
|
|
lo=(lo-(double)alo)*10;
|
|
la=(la-(double)bla)*10;
|
|
|
|
clo = (int)floor(lo);
|
|
dla = (int)floor(la);
|
|
|
|
elo = (int)floor((lo-(double)clo)*24);
|
|
fla = (int)floor((la-(double)dla)*24);
|
|
|
|
//TODO: Test if locators are calculated correctly.
|
|
// generation function has been changed because of the QT4 migration
|
|
locat = locat + QChar(alo+'A');
|
|
locat = locat + QChar(bla+'A');
|
|
locat = locat + QChar(clo+'0');
|
|
locat = locat + QChar(dla+'0');
|
|
locat = locat + QChar(elo+'A');
|
|
locat = locat + QChar(fla+'A');
|
|
|
|
// locat.at(0)=QChar(alo+'A');
|
|
|
|
// locat.at(1)=QChar(bla+'A');
|
|
// locat.at(2)=QChar(clo+'0');
|
|
// locat.at(3)=QChar(dla+'0');
|
|
// locat.at(4)=QChar(elo+'A');
|
|
// locat.at(5)=QChar(fla+'A');
|
|
|
|
|
|
|
|
return locat;
|
|
}
|
|
|
|
void Locator::degTodms(const double deg){
|
|
double temp;
|
|
double ddeg;
|
|
ddeg = 0;
|
|
ddeg += 1.0/7200.0; /* Round-up to 0.5 sec */
|
|
ideg = (int)ddeg;
|
|
temp = ( deg - (double)ideg ) * 60.0;
|
|
imin = (int)temp;
|
|
temp = ( temp - (double)imin ) * 60.0;
|
|
isec = (int)(temp);
|
|
}
|
|
|
|
double Locator::dmsTodeg (int deg, int min, int sec){
|
|
return (double)deg + (double)min/60.0 + (double)sec/3600.0;
|
|
}
|
|
|
|
|
|
int Locator::getBeamBetweenLocators (const QString& tlocator1, const QString& tlocator2)
|
|
{
|
|
//qDebug() << "Locator::getBeamBetweenLocators: " << tlocator1 << "/" << tlocator2 << endl;
|
|
if ( !(isValidLocator(tlocator1) && isValidLocator(tlocator2) ) )
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
double lon1 = getLon(tlocator1);
|
|
double lon2 = getLon(tlocator2);
|
|
double lat1 = getLat(tlocator1);
|
|
double lat2 = getLat(tlocator2);
|
|
|
|
return getBeam(lon1, lat1, lon2, lat2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int Locator::getDistanceBetweenLocators (const QString& tlocator1, const QString& tlocator2, const bool _imperialSystem)
|
|
{
|
|
if ( !(isValidLocator(tlocator1) && isValidLocator(tlocator2) ) )
|
|
{
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
double lon1 = getLon(tlocator1);
|
|
double lon2 = getLon(tlocator2);
|
|
double lat1 = getLat(tlocator1);
|
|
double lat2 = getLat(tlocator2);
|
|
|
|
return getDistance(lon1, lat1, lon2, lat2, _imperialSystem);
|
|
//return getBeam(lon1, lat1, lon2, lat2);
|
|
|
|
}
|
|
}
|