2021-07-31 10:01:14 +00:00
< ? php if ( ! defined ( 'BASEPATH' )) exit ( 'No direct script access allowed' );
2011-09-18 13:52:01 +00:00
class Qra {
2020-05-23 20:35:46 +00:00
/*
* Class Description : QRA handles manipulation of the Gridsquares used within amateur radio
*
* Units of measurement are the following
*
* Info : Distance Function
*
* M = Miles
* K = Kilometers
* N = Nautical Miles
*/
2021-07-31 10:01:14 +00:00
2020-05-23 20:35:46 +00:00
// Name: qra2latlong
2011-09-18 13:52:01 +00:00
// Task: convert qra to lat/long
function qra2latlong ( $strQRA )
{
return qra2latlong ( $strQRA );
}
2021-07-31 10:01:14 +00:00
2020-05-23 20:35:46 +00:00
// calculate the bearing between two squares
2019-06-24 13:57:48 +00:00
function bearing ( $tx , $rx , $unit = 'M' ) {
2021-09-16 18:13:08 +00:00
$my = qra2latlong ( $tx );
$stn = qra2latlong ( $rx );
2021-03-30 16:41:56 +00:00
2023-08-25 14:26:25 +00:00
if ( $my !== false && $stn !== false ) {
$bearing = bearing ( $my [ 0 ], $my [ 1 ], $stn [ 0 ], $stn [ 1 ], $unit );
return $bearing ;
} else {
return false ;
}
2011-09-18 13:52:01 +00:00
}
2020-05-23 20:35:46 +00:00
/*
* Function : calculate the distance between two gridsqaures
*
* Inputs are QRA ' s TX and TX and the unit
*
*/
function distance ( $tx , $rx , $unit = 'M' ) {
// Calc LatLongs
$my = qra2latlong ( $tx );
$stn = qra2latlong ( $rx );
// Feed in Lat Longs plus the unit type
2023-06-20 14:26:00 +00:00
try
{
$total_distance = distance ( $my [ 0 ], $my [ 1 ], $stn [ 0 ], $stn [ 1 ], $unit );
}
catch ( Exception $e )
{
$total_distance = 0 ;
}
2021-07-31 10:01:14 +00:00
2020-05-23 20:35:46 +00:00
// Return the distance
return $total_distance ;
}
2022-02-15 19:28:37 +00:00
/*
* Function returns just the bearing
* Input locator1 and locator2
*/
function get_bearing ( $tx , $rx ) {
$my = qra2latlong ( $tx );
$stn = qra2latlong ( $rx );
return get_bearing ( $my [ 0 ], $my [ 1 ], $stn [ 0 ], $stn [ 1 ]);
}
2022-04-04 14:15:24 +00:00
/*
Find the Midpoint between two gridsquares using lat / long
Needs following passed
$coords [] = array ( 'lat' => '53.344104' , 'lng' => '-6.2674937' );
$coords [] = array ( 'lat' => '51.5081289' , 'lng' => '-0.128005' );
*/
function get_midpoint ( $coords )
{
$count_coords = count ( $coords );
$xcos = 0.0 ;
$ycos = 0.0 ;
$zsin = 0.0 ;
foreach ( $coords as $lnglat )
{
$lat = $lnglat [ 'lat' ] * pi () / 180 ;
$lon = $lnglat [ 'lng' ] * pi () / 180 ;
$acos = cos ( $lat ) * cos ( $lon );
$bcos = cos ( $lat ) * sin ( $lon );
$csin = sin ( $lat );
$xcos += $acos ;
$ycos += $bcos ;
$zsin += $csin ;
}
$xcos /= $count_coords ;
$ycos /= $count_coords ;
$zsin /= $count_coords ;
$lon = atan2 ( $ycos , $xcos );
$sqrt = sqrt ( $xcos * $xcos + $ycos * $ycos );
$lat = atan2 ( $zsin , $sqrt );
return array ( $lat * 180 / pi (), $lon * 180 / pi ());
}
2020-05-23 20:35:46 +00:00
}
2019-06-24 11:10:49 +00:00
2011-09-18 13:52:01 +00:00
function distance ( $lat1 , $lon1 , $lat2 , $lon2 , $unit = 'M' ) {
$theta = $lon1 - $lon2 ;
2021-09-16 18:13:08 +00:00
$dist = sin ( deg2rad ( $lat1 )) * sin ( deg2rad ( $lat2 )) + cos ( deg2rad ( $lat1 )) * cos ( deg2rad ( $lat2 )) * cos ( deg2rad ( $theta ));
2011-09-18 13:52:01 +00:00
$dist = acos ( $dist );
$dist = rad2deg ( $dist );
$dist = $dist * 60 * 1.1515 ;
if ( $unit == " K " ) {
$dist *= 1.609344 ;
} else if ( $unit == " N " ) {
$dist *= 0.8684 ;
}
return round ( $dist , 1 );
}
2019-06-24 13:57:48 +00:00
function bearing ( $lat1 , $lon1 , $lat2 , $lon2 , $unit = 'M' ) {
2021-07-31 10:01:14 +00:00
$dist = distance ( $lat1 , $lon1 , $lat2 , $lon2 , $unit );
$dist = round ( $dist , 0 );
$bearing = get_bearing ( $lat1 , $lon1 , $lat2 , $lon2 );
2011-09-18 13:52:01 +00:00
$dirs = array ( " N " , " E " , " S " , " W " );
$rounded = round ( $bearing / 22.5 ) % 16 ;
if (( $rounded % 4 ) == 0 ) {
$dir = $dirs [ $rounded / 4 ];
} else {
$dir = $dirs [ 2 * floor ((( floor ( $rounded / 4 ) + 1 ) % 4 ) / 2 )];
$dir .= $dirs [ 1 + 2 * floor ( $rounded / 8 )];
#if ($rounded % 2 == 1)
# $dir = $dirs[round_to_int($rounded/4) % 4] . "-" . $dir;
}
2021-07-31 10:01:14 +00:00
$var_dist = " " ;
2011-09-18 13:52:01 +00:00
#return $dir;
if ( isset ( $dist )) {
2019-06-24 13:57:48 +00:00
$var_dist = $dist ;
switch ( $unit ) {
case 'M' :
$var_dist .= " miles " ;
break ;
case 'N' :
$var_dist .= " nautic miles " ;
break ;
case 'K' :
$var_dist .= " kilometers " ;
break ;
}
2011-09-18 13:52:01 +00:00
}
return round ( $bearing , 0 ) . " º " . $dir . " " . $var_dist ;
}
2021-07-31 10:01:14 +00:00
function get_bearing ( $lat1 , $lon1 , $lat2 , $lon2 ) {
2023-01-02 20:37:39 +00:00
return ( int )( rad2deg ( atan2 ( sin ( deg2rad ( $lon2 ) - deg2rad ( $lon1 )) * cos ( deg2rad ( $lat2 )), cos ( deg2rad ( $lat1 )) * sin ( deg2rad ( $lat2 )) - sin ( deg2rad ( $lat1 )) * cos ( deg2rad ( $lat2 )) * cos ( deg2rad ( $lon2 ) - deg2rad ( $lon1 )))) + 360 ) % 360 ;
2021-07-31 10:01:14 +00:00
}
2021-09-16 18:13:08 +00:00
function qra2latlong ( $strQRA ) {
2023-08-23 12:48:49 +00:00
if ( substr_count ( $strQRA , ',' ) > 0 ) {
if ( substr_count ( $strQRA , ',' ) == 3 ) {
// Handle grid corners
$grids = explode ( ',' , $strQRA );
2023-08-25 14:26:25 +00:00
$gridlengths = array ( strlen ( $grids [ 0 ]), strlen ( $grids [ 1 ]), strlen ( $grids [ 2 ]), strlen ( $grids [ 3 ]));
$same = array_count_values ( $gridlengths );
if ( count ( $same ) != 1 ) {
return false ;
}
2023-08-23 12:48:49 +00:00
$coords = array ( 0 , 0 );
for ( $i = 0 ; $i < 4 ; $i ++ ) {
$cornercoords [ $i ] = qra2latlong ( $grids [ $i ]);
$coords [ 0 ] += $cornercoords [ $i ][ 0 ];
$coords [ 1 ] += $cornercoords [ $i ][ 1 ];
}
return array ( round ( $coords [ 0 ] / 4 ), round ( $coords [ 1 ] / 4 ));
} else if ( substr_count ( $strQRA , ',' ) == 1 ) {
// Handle grid lines
$grids = explode ( ',' , $strQRA );
2023-08-25 14:26:25 +00:00
if ( strlen ( $grids [ 0 ]) != strlen ( $grids [ 1 ])) {
return false ;
}
2023-08-23 12:48:49 +00:00
$coords = array ( 0 , 0 );
for ( $i = 0 ; $i < 2 ; $i ++ ) {
$linecoords [ $i ] = qra2latlong ( $grids [ $i ]);
}
if ( $linecoords [ 0 ][ 0 ] != $linecoords [ 1 ][ 0 ]) {
$coords [ 0 ] = round ((( $linecoords [ 0 ][ 0 ] + $linecoords [ 1 ][ 0 ]) / 2 ), 1 );
} else {
$coords [ 0 ] = round ( $linecoords [ 0 ][ 0 ], 1 );
}
if ( $linecoords [ 0 ][ 1 ] != $linecoords [ 1 ][ 1 ]) {
$coords [ 1 ] = round (( $linecoords [ 0 ][ 1 ] + $linecoords [ 1 ][ 1 ]) / 2 );
} else {
$coords [ 1 ] = round ( $linecoords [ 0 ][ 1 ]);
}
return $coords ;
2023-08-23 12:22:20 +00:00
} else {
2023-08-23 12:48:49 +00:00
return false ;
2023-08-23 12:22:20 +00:00
}
2022-02-18 13:46:16 +00:00
}
2023-07-28 17:01:18 +00:00
if (( strlen ( $strQRA ) % 2 == 0 ) && ( strlen ( $strQRA ) <= 8 )) { // Check if QRA is EVEN (the % 2 does that) and smaller/equal 8
2023-07-28 15:48:35 +00:00
$strQRA = strtoupper ( $strQRA );
2023-07-28 17:01:18 +00:00
if ( strlen ( $strQRA ) == 4 ) $strQRA .= " MM " ; // Only 4 Chars? Fill with center "MM"
if ( strlen ( $strQRA ) == 6 ) $strQRA .= " 55 " ; // Only 6 Chars? Fill with center "55"
2011-09-18 13:52:01 +00:00
2023-07-28 17:01:18 +00:00
if ( ! preg_match ( '/^[A-R]{2}[0-9]{2}[A-X]{2}[0-9]{2}$/' , $strQRA )) {
2023-07-28 15:48:35 +00:00
return false ;
}
2023-07-28 17:01:18 +00:00
list ( $a , $b , $c , $d , $e , $f , $g , $h ) = str_split ( $strQRA , 1 ); // Maidenhead is always alternating. e.g. "AA00AA00AA00" - doesn't matter how deep. 2 chars, 2 numbers, etc.
2023-07-28 15:48:35 +00:00
$a = ord ( $a ) - ord ( 'A' );
$b = ord ( $b ) - ord ( 'A' );
$c = ord ( $c ) - ord ( '0' );
$d = ord ( $d ) - ord ( '0' );
$e = ord ( $e ) - ord ( 'A' );
$f = ord ( $f ) - ord ( 'A' );
2023-07-28 17:01:18 +00:00
$g = ord ( $g ) - ord ( '0' );
$h = ord ( $h ) - ord ( '0' );
$nLong = ( $a * 20 ) + ( $c * 2 ) + (( $e + 0.5 ) / 12 ) + (( $g - 5 ) / 120 ) - 180 ; // the 4th pair is "in the middle", so we've to substract 5
$nLat = ( $b * 10 ) + $d + (( $f + 0.5 ) / 24 ) + (( $h - 5 ) / 240 ) - 90 ;
2023-07-28 15:48:35 +00:00
$arLatLong = array ( $nLat , $nLong );
return $arLatLong ;
} else {
return array ( 0 , 0 );
}
2011-09-18 13:52:01 +00:00
}
2022-04-04 14:15:24 +00:00
2023-07-28 15:48:35 +00:00
2020-12-04 10:30:40 +00:00
/* End of file Qra.php */