JavaScript Implementation of Base26GPS Standard
This is the JavaScript implementation of Base26GPS Standard
Introduction
I am continuing the tip about the implementation in ANSI C.
The Base26GPS standard is used for sharing location between platforms by converting the longitude
and latitude
to a string
. The string
is from A to Z, having 26 characters all together thus making it a Base26 in the numeral system which is also known as Hexavigesimal. In this tip, I will describe the code that is used to implement it.
For more information, you can visit the website here.
Background
Location is based on Longitude
and Latitude
. Longitude
is a number between -180.0 to 180 and latitude
is a number between -90 to 90. Until now, applications from different platforms did not have a standard to send the location between one another, they used their own internal standards.
Using the Code
There are two functions:
ConcertLocToBase26
- convertsLongitude
andLatitude
to astring
ConvertBase26ToLoc
- converts astring
toLongitude
andLatitude
Converting from Longitude
and Latitude
to Alphabetic letters is done using the following steps:
- The first three letters are "GPS", next six letters represent
Longitude
and last six letters representLatitude
. All together fifteen letters. - The
Longitude
andLatitude
should always have 4 numbers after the dot.
For example: -180 will be -180.0000, 12.53 will be 12.5300 and 151.45319 will be 151.4532 - Each one is separated to the number located at the left side of the decimal point and the number located at the right of the decimal point.
- The left number is from -180 to 180 for
Longitude
. -180 equals to AA and 180 equals to NW. Here the counting begins from -180.
ForLatitude
, the left number is from -90 to 90. -90 equals to AA and 90 equals to GY. Here the counting begins from -90. - The right number is divided into two groups. Each group is from 00 to 99. 00 equals to AA and 99 equals to DV. Here the counting begins from 0.
- After conversion, there are six letters for
Longitude
and six letters forLatitude
.
For example –Longitude
of 12.45 andLatitude
of -11.54 will generate thestring
"GPSHKBTAADBCCAA
".
Converting from alphabetic letters to Longitude
and Latitude
is done using the same principle.
Below are the JavaScript functions that convert from Longitude, Latitude to Base26GPS and vise versa.
I learned some things while writing this code.
For example, I noticed the Google Chrome does not support in a transparant manner the 'GetElementById
' which searches the name of the form box. Instead, I had to dig into the path of the form.
Another thing I studied is how to manipulate inside a string
and how to convert it to decimal value and I also learned how to return more than one variable from a function.
What amazes me in JavaScript is that there is no need to declare the variable's type.
The thing I enjoyed the most is using my own browser to debug and run the script. There is no need for any external compilers. I used a Debug box form to display variables for debugging and that's it...
function ConvertLongitude(Longitude)
{
/* ======================================================================
function name : ConvertLongitude
function activity : convert Longitude parameter to string according to
Base26GPS standard
input parameters : float Longitude - the Longitude to be translated
output parameters : int Return Value [0]- the function success or failure.
"1" = success otherwise fail
string ReturnString [1] - a six chars string representing
the translated Longitude
========================================================================= */
var TempFloat;
var FractPart;
var TempFractPart;
var IntPart;
var Multiply;
var Add;
var Fail = 0;
var Sign;
var LongitudeString;
Check for longitude validity:
if (Longitude<-180 || Longitude>180)
{
ShowError('Longitude parameter out of limits. -180 to 180');
return [0,0];
}
if (Longitude<0)
{
Longitude-=0.00005;
Sign=-1;
}
else
{
Longitude+=0.00005;
Sign=1;
}
Get the integer part:
IntPart=MakeInteg(Longitude);
Get the fraction part:
FractPart=Math.abs(Longitude - IntPart)*10000;
Get the two letters of the integer part:
TempFloat=MakeInteg((IntPart+180)/26);
Multiply=TempFloat+65;
If Longitude is between -0.9999 to -0.001, use the letter 'Z':
if (MakeInteg(Longitude)==0 && Sign== -1)
Multiply=90; LongitudeString=String.fromCharCode(Multiply);
TempFloat=((((IntPart+180)/26) - MakeInteg((IntPart+180)/26))*26)+0.1;
Add = Math.floor(TempFloat)+65;
LongitudeString+=String.fromCharCode(Add);
Get the first two letters of the fract part:
TempFractPart = FractPart/100;
TempFloat = MakeInteg(TempFractPart/26);
Multiply = TempFloat+65;
LongitudeString+=String.fromCharCode(Multiply);
TempFloat=(((TempFractPart/26) - MakeInteg(TempFractPart/26))*26);
Add = Math.floor(TempFloat)+65;
LongitudeString+=String.fromCharCode(Add);
Get the second two letters of the fract part:
TempFractPart = (FractPart/100 - MakeInteg(FractPart/100))*100;
TempFloat = MakeInteg(TempFractPart/26);
Multiply = TempFloat+65;
LongitudeString+=String.fromCharCode(Multiply);
TempFloat=(((TempFractPart/26) - MakeInteg(TempFractPart/26))*26);
Add = Math.floor(TempFloat)+65;
LongitudeString+=String.fromCharCode(Add);
Return the longitude string:
return[1,LongitudeString];
}
function ConvertLatitude(Latitude)
{
/* ======================================================================
function name : ConvertLatitude
function activity : convert Latitude parameter to string according to
Base26GPS standard
input parameters : float Latitude - the Longitude to be translated
output parameters : int Return Value [0]- the function success or failure.
"1" = success otherwise fail
string ReturnString [1] - a six chars string representing
the translated Latitude
========================================================================= */
var TempFloat;
var FractPart;
var TempFractPart;
var IntPart;
var Multiply;
var Add;
var Fail = 0;
var Sign;
var LatitudeString;
Check for validity:
if (Latitude<-90 || Latitude>90)
{
ShowError('Latitude parameter out of limits. -90 to 90');
return [0,0];
}
if (Latitude<0)
{
Latitude-=0.00005;
Sign=-1;
}
else
{
Latitude+=0.00005;
Sign=1;
}
Get the integer part:
IntPart=MakeInteg(Latitude);
Get the fract part:
FractPart=Math.abs(Latitude - IntPart)*10000;
Get the two letters of the integer part:
TempFloat=MakeInteg((IntPart+90)/26);
Multiply=TempFloat+65;
If Latitude is between -0.9999 to -0.001, use the letter 'Z':
if (MakeInteg(Latitude)==0 && Sign== -1)
Multiply=90;
LatitudeString=String.fromCharCode(Multiply);
TempFloat=((((IntPart+90)/26) - MakeInteg((IntPart+90)/26))*26)+0.1;
Add = MakeInteg(TempFloat)+65;
LatitudeString+=String.fromCharCode(Add);
TempFractPart = FractPart/100;
TempFloat = MakeInteg(TempFractPart/26);
Multiply = TempFloat+65;
LatitudeString+=String.fromCharCode(Multiply);
Get the first two letters of the fract part:
TempFloat=(((TempFractPart/26) - MakeInteg(TempFractPart/26))*26);
Add = MakeInteg(TempFloat)+65;
LatitudeString+=String.fromCharCode(Add);
TempFractPart = (FractPart/100 - MakeInteg(FractPart/100))*100;
TempFloat = Math.floor(TempFractPart/26);
Multiply = TempFloat+65;
LatitudeString+=String.fromCharCode(Multiply);
Get the second two letters of the fract part:
TempFloat=(((TempFractPart/26) - Math.floor(TempFractPart/26))*26);
Add = Math.floor(TempFloat)+65;
LatitudeString+=String.fromCharCode(Add);
Return the latitude string:
return[1,LatitudeString];
}
function ConvertLocToBase26()
{
/* ======================================================================
function name : ConvertLocToBase26
function activity : convert Longitude and Latitude parameter to string
according to Base26GPS standard
input parameters : float Longitude - the Longitude to be translated
float Latitude - the Latitude to be translated
output parameters: int Return Value [0] - the function success or failure.
"1" = success otherwise fail
string Base26GPSString [1] - a 15 chars string representing
the Base26GPS standard.
========================================================================= */
var Longitude;
var Latitude;
var ReturnArray;
ReturnArray = GetLongitudeLatitude()
if (ReturnArray[0]==0)
return 0;
Longitude = parseFloat(ReturnArray[1]);
Latitude = parseFloat(ReturnArray[2]);
Set the string header to GPS:
var Base26GPSString='GPS';
Get the longitude string:
ReturnArray=ConvertLongitude(Longitude);
if (ReturnArray[0]==0)
return 0;
Base26GPSString+=ReturnArray[1];
Get the latitude string:
ReturnArray=ConvertLatitude(Latitude);
if (ReturnArray[0]==0)
return 0;
Base26GPSString+=ReturnArray[1];
Combined string:
ShowBase26GPSString(Base26GPSString);
}
function ConvertBase26ToLoc()
{
var LongitudeString;
var NewLongitudeString="";
var LatitudeString;
var NewLatitudeString="";
var SetStringMultiply;
var SetStringAdd;
var SetString;
var RetNum;
var count;
var PassFail;
var Fail = 0;
var Sign;
var SignForZero;
var GPSString;
var ReturnArray;
var ReturnLongitude;
var ReturnLatitude;
Base26GPSString = GetBase26GPS();
Check the length. It must be 15
.
if (Base26GPSString.length!=15)
{
ShowError('String must have 15 characters');
return [0,0,0];
}
GPSString = Base26GPSString.slice(0,3);
// check for GPS header
if (GPSString !='GPS')
{
ShowError('GPS Header is missing');
return [0,0,0];
}
LongitudeString = Base26GPSString.slice(3,9);
LatitudeString = Base26GPSString.slice(9,16);
Change the lower case char
s to upper case and check for legal characters
for (count=0;count<6;count++)
{
if (!((LongitudeString.slice(count,count+1)).charCodeAt(0)>64 &&
(LongitudeString.slice(count,count+1)).charCodeAt(0)<91 ||
(LongitudeString.slice(count,count+1)).charCodeAt(0)>96 &&
(LongitudeString.slice(count,count+1)).charCodeAt(0)<123))
{
ShowError('Longitude string has illegal characters');
return [0,0,0];
}
if ((LongitudeString.slice(count,count+1)).charCodeAt(0)>96)
NewLongitudeString+=String.fromCharCode
((LongitudeString.slice(count,count+1).charCodeAt(0)) -32);
else
NewLongitudeString+=LongitudeString.slice(count,count+1);
if (!((LatitudeString.slice(count,count+1)).charCodeAt(0)>64 &&
(LatitudeString.slice(count,count+1)).charCodeAt(0)<91 ||
(LatitudeString.slice(count,count+1)).charCodeAt(0)>96 &&
(LatitudeString.slice(count,count+1)).charCodeAt(0)<123))
{
ShowError('Latitude string has illegal characters');
return [0,0,0];
}
if ((LatitudeString.slice(count,count+1)).charCodeAt(0)>96)
NewLatitudeString+=String.fromCharCode
(LatitudeString.slice(count,count+1).charCodeAt(0) -32);
else
NewLatitudeString+=LatitudeString.slice(count,count+1);
}
Longitude Activity
Extract the integer part:
SetStringMultiply = (NewLongitudeString.slice(0,1));
SetStringAdd = (NewLongitudeString.slice(1,2));
SignForZero = 1;
Check if the number is between -0.0001 to -0.9999:
if (SetStringMultiply.charCodeAt(0) == (90))
{
SignForZero = -1;
SetStringMultiply = String.fromCharCode(71);
}
SetString = SetStringMultiply+SetStringAdd;
RetNum = Base26ToNum(SetString);
Substract the longitude minimum value:
RetNum -=180;
if (RetNum<0)
Sign=-1;
else
Sign=1;
Check validity:
if (RetNum<-180 || RetNum>180)
{
ShowError('string parameters out of limits');
return [0,0,0];
}
ReturnLongitude=RetNum;
Extract the first fract part pair:
SetString = NewLongitudeString.slice(2,4);
RetNum = Base26ToNum(SetString);
if (RetNum<0 || RetNum>99)
{
ShowError('string parameters out of limits');
return 0;
}
ReturnLongitude+=RetNum*0.01*Sign;
Extract the last fract part pair:
SetString = NewLongitudeString.slice(4,6);
RetNum = Base26ToNum(SetString);
if (RetNum<0 || RetNum>99)
{
ShowError('string parameters out of limits');
return 0;
}
ReturnLongitude+=RetNum*0.0001*Sign;
ReturnLongitude*=SignForZero;
ShowLongitude(ReturnLongitude);
Latitude Activity
Extract the integer part:
SetStringMultiply = (NewLatitudeString.slice(0,1));
SetStringAdd = (NewLatitudeString.slice(1,2));
SignForZero = 1;
Check if the number is between -0.0001 to -0.9999:
if (SetStringMultiply.charCodeAt(0) == (90))
{
SignForZero = -1;
SetStringMultiply = String.fromCharCode(68);
}
SetString = SetStringMultiply+SetStringAdd;
// subasract the latitude minimum value
RetNum = Base26ToNum(SetString);
RetNum -=90;
if (RetNum<0)
Sign=-1;
else
Sign=1;
if (RetNum<-90 || RetNum>90)
{
ShowError('string parameters out of limits');
return [0,0,0];
}
ReturnLatitude=RetNum;
Extract the first fract part pair:
SetString = NewLatitudeString.slice(2,4);
RetNum = Base26ToNum(SetString);
if (RetNum<0 || RetNum>99)
{
ShowError('string parameters out of limits');
return 0;
}
ReturnLatitude+=RetNum*0.01*Sign;
Extract the last fract part pair:
SetString = NewLatitudeString.slice(4,6);
RetNum = Base26ToNum(SetString);
if (RetNum<0 || RetNum>99)
{
ShowError('string parameters out of limits');
return 0;
}
ReturnLatitude+=RetNum*0.0001*Sign;
ReturnLatitude*=SignForZero;
ShowLatitude(ReturnLatitude);
}
function Base26ToNum(InputString)
{
/* ======================================================================
function name : Base26ToNum
function activity : convert a string value to integer according to
Base26
input parameters : InputString - the string to be translated
output parameters: int Return Value - the integer of the value
========================================================================= */
var Multiply;
var Add;
var RetNum;
Multiply = (InputString.slice(0,1)).charCodeAt(0) - 65;
Add = (InputString.slice(1,2)).charCodeAt(0) - 65;
RetNum = Multiply * 26 + Add;
return RetNum;
}
I didn't find any function that makes flooring while maintaining the sign bit. So I built one of my own:
function MakeInteg(Value)
{
/* ======================================================================
function name : MakeInteg
function activity : convert a value to its integer value with the sign
input parameters : float Value - the value to be converted
output parameters: int Return Value - the integer of the value
========================================================================= */
var ReturnValue;
var Sign;
if (Value<0)
Sign=-1;
else
Sign=1
ReturnValue=Math.floor(Math.abs(Value))*Sign;
return ReturnValue;
}
This is the HTML to support the JavaScript:
<form name="LocationToBase26GPSform"
OnSubmit="javascript:test()">
Location to Base26GPS Online Calculator -
<br><br><br>
<table border="0">
<tr><td>
Longitude Input : </td><td><input type="text"
name="LongitudeInput">
</td></tr>
<tr><td>
Latitude Input : </td><td><input type="text"
name="LatitudeInput">
</td></tr>
<tr><td>
</td><td><input type="button"
value="Convert Location " OnClick="javascript:ConvertLocToBase26()">
</td></tr>
<tr><td>
Base26GPS : </td><td><input type="text"
size="30" name="Base26GPSInput">
</td></tr>
<tr><td>
</td><td><input type="button"
value="Convert Base26GPS" OnClick="javascript:ConvertBase26ToLoc()">
</td></tr>
<tr><td>
Longitude Result : </td><td><input type="text"
name="LongitudeTranslate">
</td></tr>
<tr><td>
Latitude Result : </td><td><input type="text"
name="LatitudeTranslate">
</td></tr>
</table>
<br><br>
<!-- Debug = <input type="text" name="DebugText"> -->
<br><br><br>
</form>
These are the JavaScript functions to support the HTML Form:
function ShowLongitude(LongitudeVal)
{
/* ======================================================================
function name : ShowLongitude
function activity : display the Longitude
input parameters : float LongitudeVal - rhe longitude to be displayed
output parameters: null
========================================================================= */
//document.getElementById('LongitudeTranslate').value = LongitudeVal;
document.forms['LocationToBase26GPSform']['LongitudeTranslate'].value = LongitudeVal;
}
function ShowLatitude(LatitudeVal)
{
/* ======================================================================
function name : ShowLatitude
function activity : display the Latitude
input parameters : float LatitudeVal - rhe latitude to be displayed
output parameters: null
========================================================================= */
//document.getElementById('LatitudeTranslate').value = LatitudeVal;
document.forms['LocationToBase26GPSform']['LatitudeTranslate'].value = LatitudeVal;
}
function ShowBase26GPSString(Base26GPSString)
{
/* ======================================================================
function name : ShowBase26String
function activity : display the Base26String
input parameters : string Base26String - rhe string to be displayed
output parameters: null
========================================================================= */
//document.getElementById('Base26GPSInput').value = Base26GPSString;
document.forms['LocationToBase26GPSform']['Base26GPSInput'].value = Base26GPSString;
}
function GetBase26GPS()
{
//return document.getElementById('Base26GPSInput').value;
return document.forms['LocationToBase26GPSform']['Base26GPSInput'].value
}
function GetLongitudeLatitude(){
var LongitudeString;
var LatitudeString;
//LongitudeString = document.getElementById('LongitudeInput').value;
LongitudeString = document.forms['LocationToBase26GPSform']['LongitudeInput'].value;
//LatitudeString = document.getElementById('LatitudeInput').value;
LatitudeString = document.forms['LocationToBase26GPSform']['LatitudeInput'].value;
if (isNaN(parseFloat(LongitudeString)))
{
ShowError('Longitude parameter illegal');
return [0,0,0];
}
if (isNaN(parseFloat(LatitudeString)))
{
ShowError('Longitude parameter illegal');
return [0,0,0];
}
return [1,LongitudeString,LatitudeString];
}
History
- This is the second version of this tip. The first one was in ANSI C.