I've asked this once before without my understanding what to do but I
thought that I would try again. Someone has written a routine in C
Sharp which is used as a library for the Android RAD Basic4android: I
have successfully used this library with a Basic4android app that I have
written. I would like to be able to use this library in Gambas. Is this
possible with just a small amount of changes to the code (which I have
attached)? If so, could someone give me the steps (which must be easy as
I have no knowledge of C or how to 'integrate' a C 'program' into a
Gambas app?
//version: 1.2
/***********************************************************************
* GPStoOSGB *
* http://www.codeproject.com/KB/cs/NMEAtoOSG.aspx *
* A class to generate Ordinance Survey Grid References *
* Lat, Lon from a GPS based on the WGS84 elipsoid *
* calculations were derived (i.e. copied) from the work of *
* Roger Muggleton (http://www.carabus.co.uk/) *
***********************************************************************/
using System;
namespace GPS
{
public class GPStoOSGB
{
private static double deg2rad = Math.PI / 180;
private static double rad2deg = 180.0 / Math.PI;
private double deciAlt;
private double deciLat;
private double deciLon;
private double easting;
private double northing;
// constructor
public GPStoOSGB()
{
}
// convert Northing and Easting to NGR
public String NEtoNGR(double easting, double northing)
{
return NE2NGR(easting, northing);
}
// converts OS national grid reference to OSGB36 lat and long
// also converts to Northing and Easting
public String NGRtoOSGB36(String ngr)
{
ngr = ngr.Replace(" ", "");
if (ngr.Length > 12 || ngr.Length <= 4 || ngr.Length % 2 != 0
|| !Char.IsLetter(ngr[0]) || !Char.IsLetter(ngr[1]))
throw new Exception("Invalid grid reference");
int digits = (ngr.Length -2) / 2 ;
double metres = Math.Pow(10, 5 - digits);
double north = double.Parse(ngr.Substring(2 + digits, digits)) * metres;
double east = double.Parse(ngr.Substring(2, digits)) * metres;
double t1 = Char.ToUpper(ngr[0]) - 65;
if (t1 > 8)
t1 = t1 - 1;
double t2 = Math.Floor(t1 / 5);
north = north + 500000 * (3 - t2);
east = east + 500000 * (t1 - 5 * t2 - 2);
t1 = Char.ToUpper(ngr[1]) - 65;
if (t1 > 8)
t1 = t1 - 1;
t2 = Math.Floor(t1 / 5);
north = north + 100000 * (4 - t2);
east = east + 100000 * (t1 - 5 * t2);
easting = east;
northing = north;
// converts NGR easting and nothing to lat, lon.
// input metres, output radians
double nX = north;
double eX = east;
double a = 6377563.396; // OSGB semi-major
double b = 6356256.91; // OSGB semi-minor
double e0 = 400000; // OSGB easting of false origin
double n0 = -100000; // OSGB northing of false origin
double f0 = 0.9996012717; // OSGB scale factor on central meridian
double e2 = 0.0066705397616; // OSGB eccentricity squared
double lam0 = -0.034906585039886591; // OSGB false east
double phi0 = 0.85521133347722145; // OSGB false north
double af0 = a * f0;
double bf0 = b * f0;
double n = (af0 - bf0) / (af0 + bf0);
double Et = east - e0;
double phid = InitialLat(north, n0, af0, phi0, n, bf0);
double nu = af0 / (Math.Sqrt(1 - (e2 * (Math.Sin(phid) * Math.Sin(phid)))));
double rho = (nu * (1 - e2)) / (1 - (e2 * (Math.Sin(phid)) * (Math.Sin(phid))));
double eta2 = (nu / rho) - 1;
double tlat2 = Math.Tan(phid) * Math.Tan(phid);
double tlat4 = Math.Pow(Math.Tan(phid), 4);
double tlat6 = Math.Pow(Math.Tan(phid), 6);
double clatm1 = Math.Pow(Math.Cos(phid), -1);
double VII = Math.Tan(phid) / (2 * rho * nu);
double VIII = (Math.Tan(phid) / (24 * rho * (nu * nu * nu))) * (5 + (3 * tlat2) + eta2 - (9 * eta2 * tlat2));
double IX = ((Math.Tan(phid)) / (720 * rho * Math.Pow(nu, 5))) * (61 + (90 * tlat2) + (45 * Math.Pow(Math.Tan(phid), 4) ));
double phip = (phid - ((Et * Et) * VII) + (Math.Pow(Et, 4) * VIII) - (Math.Pow(Et, 6) * IX));
double X = Math.Pow(Math.Cos(phid), -1) / nu;
double XI = (clatm1 / (6 * (nu * nu * nu))) * ((nu / rho) + (2 * (tlat2)));
double XII = (clatm1 / (120 * Math.Pow(nu, 5))) * (5 + (28 * tlat2) + (24 * tlat4));
double XIIA = clatm1 / (5040 * Math.Pow(nu, 7)) * (61 + (662 * tlat2) + (1320 * tlat4) + (720 * tlat6));
double lambdap = (lam0 + (Et * X) - ((Et * Et * Et) * XI) + (Math.Pow(Et, 5) * XII) - (Math.Pow(Et, 7) * XIIA));
phip = phip * rad2deg;
lambdap = lambdap * rad2deg;
deciLat = phip;
deciLon = lambdap;
return phip.ToString() + ',' + lambdap.ToString();;
}
// converts OSGB36/ODN lat,long and alt to WGS84 with S and W as -ve
public String OSGB36toWGS84(double OSGBlat, double OSGBlong, double OSGBalt)
{
//first off convert to radians
double radWGlat = OSGBlat * deg2rad;
double radWGlon = OSGBlong * deg2rad;
/* these calculations were derived from the work of
* Roger Muggleton (http://www.carabus.co.uk/) */
/* quoting Roger Muggleton :-
* There are many ways to convert data from one system to another, the most accurate
* being the most complex! For this example I shall use a 7 parameter Helmert
* transformation.
* The process is in three parts:
* (1) Convert latitude and longitude to Cartesian coordinates (these also include height
* data, and have three parameters, X, Y and Z).
* (2) Transform to the new system by applying the 7 parameters and using a little maths.
* (3) Convert back to latitude and longitude.
* For the example we shall transform a GRS80 location to Airy, e.g. a GPS reading to
* the Airy spheroid.
* The following code converts latitude and longitude to Cartesian coordinates. The
* input parameters are: WGS84 latitude and longitude, axis is the GRS80/WGS84 major
* axis in metres, ecc is the eccentricity, and height is the height above the
* ellipsoid.
* v = axis / (Math.sqrt (1 - ecc * (Math.pow (Math.sin(lat), 2))));
* x = (v + height) * Math.cos(lat) * Math.cos(lon);
* y = (v + height) * Math.cos(lat) * Math.sin(lon);
* z = ((1 - ecc) * v + height) * Math.sin(lat);
* The transformation requires the 7 parameters: xp, yp and zp correct the coordinate
* origin, xr, yr and zr correct the orientation of the axes, and sf deals with the
* changing scale factors. */
//these are the values for OSGB36(Airy)/ODN to WGS86(GRS80)
double a2 = 6378137; // WGS84_AXIS
double e2 = 0.00669438037928458; // WGS84_ECCENTRIC
double h = OSGBalt; // height above datum (from GPS GGA sentence)
double a = 6377563.396; //OSGB_AXIS
double e = 0.0066705397616; // OSGB_ECCENTRIC
double xp = 446.448;
double yp = -125.157;
double zp = 542.06;
double xr = 0.1502;
double yr = 0.247;
double zr = 0.8421;
double s = -20.4894;
// convert to cartesian; lat, lon are radians
double sf = s * 0.000001;
double v = a / (Math.Sqrt(1 - (e * (Math.Sin(radWGlat) * Math.Sin(radWGlat)))));
double x = (v + h) * Math.Cos(radWGlat) * Math.Cos(radWGlon);
double y = (v + h) * Math.Cos(radWGlat) * Math.Sin(radWGlon);
double z = ((1 - e) * v + h) * Math.Sin(radWGlat);
// transform cartesian
double xrot = (xr / 3600) * deg2rad;
double yrot = (yr / 3600) * deg2rad;
double zrot = (zr / 3600) * deg2rad;
double hx = x + (x * sf) - (y * zrot) + (z * yrot) + xp;
double hy = (x * zrot) + y + (y * sf) - (z * xrot) + yp;
double hz = (-1 * x * yrot) + (y * xrot) + z + (z * sf) + zp;
// Convert back to lat, lon
double newLon = Math.Atan(hy / hx);
double p = Math.Sqrt((hx * hx) + (hy * hy));
double newLat = Math.Atan(hz / (p * (1 - e2)));
v = a2 / (Math.Sqrt(1 - e2 * (Math.Sin(newLat) * Math.Sin(newLat))));
double errvalue = 1.0;
double lat0 = 0;
while (errvalue > 0.001)
{
lat0 = Math.Atan((hz + e2 * v * Math.Sin(newLat)) / p);
errvalue = Math.Abs(lat0 - newLat);
newLat = lat0;
}
deciAlt = p / Math.Cos(lat0) - v;
//convert back to degrees
newLat = newLat * rad2deg;
deciLat = newLat;
newLon = newLon * rad2deg;
deciLon = newLon;
return deciLat.ToString() + ',' + deciLon.ToString();
}
//converts OSGB36 lat and long to OS national grid reference
public String OSGB36toNGR(double OSGBlat, double OSGBlong)
{
deciLat = OSGBlat;
deciLon = OSGBlong;
double phi = OSGBlat * deg2rad; // convert latitude to radians
double lam = OSGBlong * deg2rad; // convert longitude to radians
double a = 6377563.396; // OSGB semi-major axis
double b = 6356256.91; // OSGB semi-minor axis
double e0 = 400000; // easting of false origin
double n0 = -100000; // northing of false origin
double f0 = 0.9996012717; // OSGB scale factor on central meridian
double e2 = 0.0066705397616; // OSGB eccentricity squared
double lam0 = -0.034906585039886591; // OSGB false east
double phi0 = 0.85521133347722145; // OSGB false north
double af0 = a * f0;
double bf0 = b * f0;
// easting
double slat2 = Math.Sin(phi) * Math.Sin(phi);
double nu = af0 / (Math.Sqrt(1 - (e2 * (slat2))));
double rho = (nu * (1 - e2)) / (1 - (e2 * slat2));
double eta2 = (nu / rho) - 1;
double p = lam - lam0;
double IV = nu * Math.Cos(phi);
double clat3 = Math.Pow(Math.Cos(phi), 3);
double tlat2 = Math.Tan(phi) * Math.Tan(phi);
double V = (nu / 6) * clat3 * ((nu / rho) - tlat2);
double clat5 = Math.Pow(Math.Cos(phi), 5);
double tlat4 = Math.Pow(Math.Tan(phi), 4);
double VI = (nu / 120) * clat5 * ((5 - (18 * tlat2)) + tlat4 + (14 * eta2) - (58 * tlat2 * eta2));
double east = e0 + (p * IV) + (Math.Pow(p, 3) * V) + (Math.Pow(p, 5) * VI);
// northing
double n = (af0 - bf0) / (af0 + bf0);
double M = Marc(bf0, n, phi0, phi);
double I = M + (n0);
double II = (nu / 2) * Math.Sin(phi) * Math.Cos(phi);
double III = ((nu / 24) * Math.Sin(phi) * Math.Pow(Math.Cos(phi), 3)) * (5 - Math.Pow(Math.Tan(phi), 2) + (9 * eta2));
double IIIA = ((nu / 720) * Math.Sin(phi) * clat5) * (61 - (58 * tlat2) + tlat4);
double north = I + ((p * p) * II) + (Math.Pow(p, 4) * III) + (Math.Pow(p, 6) * IIIA);
// make whole number values
east = Math.Round(east); // round to whole number
north = Math.Round(north); // round to whole number
easting = east;
northing = north;
// convert to nat grid ref
return NE2NGR(east, north);
}
// converts WGS84 lat, long and alt to OSGB36/ODN with S and W as -ve
public String WGS84toOSGB36(double WGSlat, double WGSlong, double WGSalt)
{
//first off convert to radians
double radWGlat = WGSlat * deg2rad;
double radWGlon = WGSlong * deg2rad;
/* these calculations were derived from the work of
* Roger Muggleton (http://www.carabus.co.uk/) */
/* quoting Roger Muggleton :-
* There are many ways to convert data from one system to another, the most accurate
* being the most complex! For this example I shall use a 7 parameter Helmert
* transformation.
* The process is in three parts:
* (1) Convert latitude and longitude to Cartesian coordinates (these also include height
* data, and have three parameters, X, Y and Z).
* (2) Transform to the new system by applying the 7 parameters and using a little maths.
* (3) Convert back to latitude and longitude.
* For the example we shall transform a GRS80 location to Airy, e.g. a GPS reading to
* the Airy spheroid.
* The following code converts latitude and longitude to Cartesian coordinates. The
* input parameters are: WGS84 latitude and longitude, axis is the GRS80/WGS84 major
* axis in metres, ecc is the eccentricity, and height is the height above the
* ellipsoid.
* v = axis / (Math.sqrt (1 - ecc * (Math.pow (Math.sin(lat), 2))));
* x = (v + height) * Math.cos(lat) * Math.cos(lon);
* y = (v + height) * Math.cos(lat) * Math.sin(lon);
* z = ((1 - ecc) * v + height) * Math.sin(lat);
* The transformation requires the 7 parameters: xp, yp and zp correct the coordinate
* origin, xr, yr and zr correct the orientation of the axes, and sf deals with the
* changing scale factors. */
//these are the values for WGS86(GRS80) to OSGB36(Airy)/ODN
double a = 6378137; // WGS84_AXIS
double e = 0.00669438037928458; // WGS84_ECCENTRIC
double h = WGSalt; // height above datum (from GPS GGA sentence)
double a2 = 6377563.396; //OSGB_AXIS
double e2 = 0.0066705397616; // OSGB_ECCENTRIC
double xp = -446.448;
double yp = 125.157;
double zp = -542.06;
double xr = -0.1502;
double yr = -0.247;
double zr = -0.8421;
double s = 20.4894;
// convert to cartesian; lat, lon are radians
double sf = s * 0.000001;
double v = a / (Math.Sqrt(1 - (e * (Math.Sin(radWGlat) * Math.Sin(radWGlat)))));
double x = (v + h) * Math.Cos(radWGlat) * Math.Cos(radWGlon);
double y = (v + h) * Math.Cos(radWGlat) * Math.Sin(radWGlon);
double z = ((1 - e) * v + h) * Math.Sin(radWGlat);
// transform cartesian
double xrot = (xr / 3600) * deg2rad;
double yrot = (yr / 3600) * deg2rad;
double zrot = (zr / 3600) * deg2rad;
double hx = x + (x * sf) - (y * zrot) + (z * yrot) + xp;
double hy = (x * zrot) + y + (y * sf) - (z * xrot) + yp;
double hz = (-1 * x * yrot) + (y * xrot) + z + (z * sf) + zp;
// Convert back to lat, lon
double newLon = Math.Atan(hy / hx);
double p = Math.Sqrt((hx * hx) + (hy * hy));
double newLat = Math.Atan(hz / (p * (1 - e2)));
v = a2 / (Math.Sqrt(1 - e2 * (Math.Sin(newLat) * Math.Sin(newLat))));
double errvalue = 1.0;
double lat0 = 0;
while (errvalue > 0.001)
{
lat0 = Math.Atan((hz + e2 * v * Math.Sin(newLat)) / p);
errvalue = Math.Abs(lat0 - newLat);
newLat = lat0;
}
deciAlt = p / Math.Cos(lat0) - v;
//convert back to degrees
newLat = newLat * rad2deg;
deciLat = newLat;
newLon = newLon * rad2deg;
deciLon = newLon;
return deciLat.ToString() + ',' + deciLon.ToString();
}
// public properties
// 1.1 added Easting and Northing properties
// removed error on square SV due to string < 5 characters in NE2NGR
// allowed lower case for grid references in NGRtoOSGB36
// 1.2 added Altitude to the ellipsoid conversions
// addded NEtoNGR method and NewAltitude property
public double DllVersion
{ get { return 1.2; } }
public double Easting
{ get { return easting; } }
public double NewAltitude
{ get { return deciAlt; } }
public double NewLatitude
{ get { return deciLat; } }
public double NewLongitude
{ get { return deciLon; } }
public double Northing
{ get { return northing; } }
// a function used in NGR to OSGB36
private double InitialLat(double north, double n0, double af0, double phi0, double n, double bf0)
{
double phi1 = ((north - n0) / af0) + phi0;
double M = Marc(bf0, n, phi0, phi1);
double phi2 = ((north - n0 - M) / af0) + phi1;
double ind = 0;
while ((Math.Abs(north - n0 - M) > 0.00001) && (ind < 20)) // max 20 iterations in case of error
{
ind = ind + 1;
phi2 = ((north - n0 - M) / af0) + phi1;
M = Marc(bf0, n, phi0, phi2);
phi1 = phi2;
}
return(phi2);
}
// a function used in OSGB36toNGR and NGR to OSGB36
private double Marc(double bf0, double n, double phi0, double phi)
{
return bf0 * (((1 + n + ((5 / 4) * (n * n)) + ((5 / 4) * (n * n * n))) * (phi - phi0))
- (((3 * n) + (3 * (n * n)) + ((21 / 8) * (n * n * n))) * (Math.Sin(phi - phi0)) * (Math.Cos(phi + phi0)))
+ ((((15 / 8) * (n * n)) + ((15 / 8) * (n * n * n))) * (Math.Sin(2 * (phi - phi0))) * (Math.Cos(2 * (phi + phi0))))
- (((35 / 24) * (n * n * n)) * (Math.Sin(3 * (phi - phi0))) * (Math.Cos(3 * (phi + phi0)))));
}
//convert 12 (6e & 6n) figure numeric to letter and number grid system
private String NE2NGR(double east, double north)
{
double eX = east / 500000;
double nX = north / 500000;
double tmp = Math.Floor(eX) - 5.0 * Math.Floor(nX) + 17.0; //Math.Floor Returns the largest integer less than or equal to the specified number.
nX = 5 * (nX - Math.Floor(nX));
eX = 20 - 5.0 * Math.Floor(nX) + Math.Floor(5.0 * (eX - Math.Floor(eX)));
if (eX > 7.5) eX = eX + 1;
if (tmp > 7.5) tmp = tmp + 1;
string eing = "0000" + Convert.ToString(east);
string ning = "0000" + Convert.ToString(north);
// padding ensures minimum length of 5 characters
int lnth = eing.Length;
eing = eing.Substring(lnth - 5);
lnth = ning.Length;
ning = ning.Substring(lnth - 5);
return Convert.ToString((char)(tmp + 65)) + Convert.ToString((char)(eX + 65)) + eing + ning;
}
}
}
------------------------------------------------------------------------------
Flow-based real-time traffic analytics software. Cisco certified tool.
Monitor traffic, SLAs, QoS, Medianet, WAAS etc. with NetFlow Analyzer
Customize your own dashboards, set traffic alerts and generate reports.
Network behavioral analysis & security monitoring. All-in-one tool.
http://pubads.g.doubleclick.net/gampad/clk?id=126839071&iu=/4140/ostg.clktrk
_______________________________________________
Gambas-user mailing list
Gambas-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/gambas-user