diff --git a/src/GPSJinni.cpp b/src/GPSJinni.cpp index ca91b43..238fa58 100644 --- a/src/GPSJinni.cpp +++ b/src/GPSJinni.cpp @@ -96,6 +96,7 @@ extern "C" { #include "Speed.h" #include "TimeLine.h" #include "Util.h" +#include "RDS-GPS.h" static long reconnectTime = 10; // Period of time after which we check for disconnection and // trigger reconnection @@ -290,6 +291,7 @@ private: Lum::Model::StringRef time; Lum::Model::StringRef latitude; Lum::Model::StringRef longitude; + Lum::Model::StringRef rds; Lum::Model::StringRef altitude; Lum::Model::DoubleRef speedValue; Lum::Model::StringRef speed; @@ -501,6 +503,7 @@ public: time(new Lum::Model::String(L"")), latitude(new Lum::Model::String(L"")), longitude(new Lum::Model::String(L"")), + rds(new Lum::Model::String(L"")), altitude(new Lum::Model::String(L"")), speedValue(new Lum::Model::Double()), speed(new Lum::Model::String(L"")), @@ -613,6 +616,7 @@ public: label->AddLabel(L"Time:",CreateTextValue(time,24)); // TODO: Measure by example label->AddLabel(L"Latitude:",CreateTextValue(latitude,10)); label->AddLabel(L"Longitude:",CreateTextValue(longitude,10)); + label->AddLabel(L"RDS:",CreateTextValue(rds,10)); label->AddLabel(L"Altitude:",CreateTextValue(altitude,10)); label->AddLabel(L"Speed:",CreateTextValue(speed,10)); label->AddLabel(L"Direction:",CreateTextValue(track,10)); @@ -905,6 +909,19 @@ public: longitude->SetNull(); } + if (data.HasLatitude() && data.HasLongitude()) { + std::wstring l; + GPSPoint gpspoint = GPSPoint(data.GetLatitude(), data.GetLongitude()); + RDSPoint rdspoint = RDSPoint(gpspoint); + l=DoubleToString(rdspoint.getX()/1000.0, 3); + l+=L", "; + l+=DoubleToString(rdspoint.getY()/1000.0, 3); + rds->Set(l); + } + else { + rds->SetNull(); + } + if (data.HasAltitude()) { altitude->Set(GetMetricAndUnitAsString(data.GetAltitude(), data.GetAltitudeDev())); diff --git a/src/LICENSE-RDS-GPS b/src/LICENSE-RDS-GPS new file mode 100644 index 0000000..86a64a9 --- /dev/null +++ b/src/LICENSE-RDS-GPS @@ -0,0 +1,13 @@ +The RDS-GPS library contains a conversion algorithm between WGS84 +(a.k.a. GPS) and RDS (a.k.a. Amersfoort) coordinates. This algorithm +is a direct translation from javascript to C and C++ of the conversion +algorithm found in http://wnimg.nl/static/js/jgis.js. That algorithm +is published at the mentioned URL and does not carry a copyright +notice. + +The theory behind the algorithms may be found in the article +'Rijksdriehoeksstelsel.pdf' (author not mentioned) found at +http://www.johannespostgroep.nl/wp-content/uploads/2008/10/rijksdriehoeksstelsel.pdf. + +The algorithm in its original javascript formulation is also used in +the site http://waarneming.nl, web portal for nature observations. diff --git a/src/Makefile.am b/src/Makefile.am index 7e113a0..4100631 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,7 +14,9 @@ GPSJinni_SOURCES = GPSJinni.cpp \ TimeLine.h \ TimeLine.cpp \ Util.h \ - Util.cpp + Util.cpp \ + RDS-GPS.h \ + RDS-GPS.cpp GPSJinni_CXXFLAGS=-I. \ $(ILLUMINATION_CFLAGS) \ diff --git a/src/RDS-GPS.cpp b/src/RDS-GPS.cpp new file mode 100644 index 0000000..1f8d16f --- /dev/null +++ b/src/RDS-GPS.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2011 Simon Pepping + * + * This file is part of the RDS-GPS library. + * + * The RDS-GPS library 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 2 of + * the License, or (at your option) any later version. + * + * The RDS-GPS library 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 the RDS-GPS library. If not, see + * . + */ + +#include "RDS-GPS.h" +#include +#include + +RDSPoint::RDSPoint(double x, double y) +{ + this->x = x; + this->y = y; +} + +RDSPoint::RDSPoint(GPSPoint gpspoint) +{ + double lat = gpspoint.getLat(); + double lng = gpspoint.getLng(); + + // GPS to bessel + double dlat = lat - 52.0; + double dlng = lng - 5.0; + double latcor = (-96.862 - dlat * 11.714 - dlng * .125) * 1e-5; + double lngcor = (dlat * .329 - 37.902 - dlng * 14.667) * 1e-5; + double latbes = lat - latcor; + double lngbes = lng - lngcor; + + // deg to rad + double phi = latbes / 180.0 * M_PI; + double lambda = lngbes / 180.0 * M_PI; + + // bessel to RDS + double qprime = std::log(std::tan(phi / 2.0 + (M_PI / 4))); + double dq = RDS::e / 2.0 * std::log((RDS::e * std::sin(phi) + 1.0) / (1.0 - RDS::e * std::sin(phi))); + double q = qprime - dq; + double w = RDS::n * q + RDS::m; + double b = std::atan(std::exp(w)) * 2.0 - (M_PI / 2); + double dl = RDS::n * (lambda - RDS::lambda0); + // Computing 2nd power + double d__1 = std::sin((b - RDS::b0) / 2.0); + // Computing 2nd power + double d__2 = std::sin(dl / 2.0); + double s2psihalf = d__1 * d__1 + d__2 * d__2 * std::cos(b) * std::cos(RDS::b0); + double cpsihalf = std::sqrt(1.0 - s2psihalf); + double spsihalf = std::sqrt(s2psihalf); + double tpsihalf = spsihalf / cpsihalf; + double spsi = spsihalf * 2.0 * cpsihalf; + double cpsi = 1.0 - s2psihalf * 2.0; + double sa = std::sin(dl) * std::cos(b) / spsi; + double ca = (std::sin(b) - std::sin(RDS::b0) * cpsi) / (std::cos(RDS::b0) * spsi); + double r = RDS::k * 2.0 * RDS::bigr * tpsihalf; + x = r * sa + RDS::x0; + y = r * ca + RDS::y0; +} + +double RDSPoint::getX() +{ + return x; +} + +double RDSPoint::getY() +{ + return y; +} + +GPSPoint::GPSPoint(double lat, double lng) +{ + this->lat = lat; + this->lng = lng; +} + +GPSPoint::GPSPoint(RDSPoint rdspoint) +{ + double x = rdspoint.getX(); + double y = rdspoint.getY(); + + // RDS to bessel + double d__1 = x - RDS::x0; + double d__2 = y - RDS::y0; + double r = std::sqrt(d__1 * d__1 + d__2 * d__2); + double sa, ca; + if (r) { + sa = (x - RDS::x0) / r; + ca = (y - RDS::y0) / r; + } else { + sa = 0.0; + ca = 0.0; + } + double psi = std::atan2(r, RDS::k * 2. * RDS::bigr) * 2.; + double cpsi = std::cos(psi); + double spsi = std::sin(psi); + double sb = ca * std::cos(RDS::b0) * spsi + std::sin(RDS::b0) * cpsi; + double cb = std::sqrt(1. - sb * sb); + double b = std::acos(cb); + double sdl = sa * spsi / cb; + double dl = std::asin(sdl); + double lambda = dl / RDS::n + RDS::lambda0; + double w = std::log(std::tan(b / 2. + (M_PI / 4))); + double q = (w - RDS::m) / RDS::n; + double phiprime = std::atan(std::exp(q)) * 2. - (M_PI / 2); + double phi; + for (int i = 0; i < 4; ++i) { + double dq = RDS::e / 2. * std::log((RDS::e * std::sin(phiprime) + 1.) / (1. - RDS::e * std::sin(phiprime))); + phi = std::atan(std::exp(q + dq)) * 2. - (M_PI/ 2); + phiprime = phi; + } + + // rad to deg + double latbes = phi / M_PI * 180; + double lngbes = lambda / M_PI * 180; + + // bessel to GPS + double dlat = latbes - 52.0; + double dlng = lngbes - 5.0; + double latcor = (-96.862 - dlat * 11.714 - dlng * .125) * 1e-5; + double lngcor = (dlat * .329 - 37.902 - dlng * 14.667) * 1e-5; + lat = latbes + latcor; + lng = lngbes + lngcor; +} + +double GPSPoint::getLat() +{ + return lat; +} + +double GPSPoint::getLng() +{ + return lng; +} + + diff --git a/src/RDS-GPS.h b/src/RDS-GPS.h new file mode 100644 index 0000000..a349636 --- /dev/null +++ b/src/RDS-GPS.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2011 Simon Pepping + * + * This file is part of the RDS-GPS library. + * + * The RDS-GPS library 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 2 of + * the License, or (at your option) any later version. + * + * The RDS-GPS library 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 the RDS-GPS library. If not, see + * . + */ + +#ifndef RDS_GPS_H +#define RDS_GPS_H + +#include + +class RDS +{ +public: + static const double x0 = 155000.0; + static const double y0 = 463000.0; + static const double k = .9999079; + static const double bigr = 6382644.571; + static const double m = .003773953832; + static const double n = 1.00047585668; + static const double lambda0 = M_PI * .029931327161111111; + static const double phi0 = M_PI * .28975644753333335; + static const double l0 = M_PI * .029931327161111111; + static const double b0 = M_PI * .28956165138333334; + static const double e = .08169683122; + static const double a = 6377397.155; +}; + +class GPSPoint; + +class RDSPoint +{ +private: + double x, y; + +public: + RDSPoint(double x, double y); + RDSPoint(GPSPoint gpspoint); + double getX(); + double getY(); +}; + +class GPSPoint +{ +private: + double lat, lng; + +public: + GPSPoint(double lat, double lng); + GPSPoint(RDSPoint rdspoint); + double getLat(); + double getLng(); +}; + +#endif