klog/locator.cpp
2015-01-14 18:51:30 +00:00

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);
}
}