#include <iostream>
#include <limits>
#include <string>
#include <GeographicLib/Math.hpp>
#include <GeographicLib/Utility.hpp>
#include <GeographicLib/DMS.hpp>
#include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/GeodesicExact.hpp>
#include <GeographicLib/UTMUPS.hpp>
#include <GeographicLib/MGRS.hpp>
#include <GeographicLib/PolygonArea.hpp>
using namespace std;
using namespace GeographicLib;
typedef Math::real T;
static int checkEquals(T x, T y, T d) {
if (fabs(x - y) <= d)
return 0;
cout << "checkEquals fails: " << x << " != " << y << " +/- " << d << "\n";
return 1;
}
static int checkNaN(T x) {
using std::isnan; if (isnan(x))
return 0;
cout << "checkNaN fails\n";
return 1;
}
static int Planimeter15() {
const Geodesic& g = Geodesic::WGS84();
PolygonArea polygon(g);
T lat[] = {2, 1, 3}, lon[] = {1, 2, 3};
T perim, area, s12, azi1, azi2;
T r = 18454562325.45119,
a0 = 510065621724088.5093; int result = 0;
polygon.AddPoint(lat[0], lon[0]);
polygon.AddPoint(lat[1], lon[1]);
polygon.TestPoint(lat[2], lon[2], false, true, perim, area);
result += checkEquals(area, r, 0.5);
polygon.TestPoint(lat[2], lon[2], false, false, perim, area);
result += checkEquals(area, r, 0.5);
polygon.TestPoint(lat[2], lon[2], true, true, perim, area);
result += checkEquals(area, -r, 0.5);
polygon.TestPoint(lat[2], lon[2], true, false, perim, area);
result += checkEquals(area, a0-r, 0.5);
g.Inverse(lat[1], lon[1], lat[2], lon[2], s12, azi1, azi2);
polygon.TestEdge(azi1, s12, false, true, perim, area);
result += checkEquals(area, r, 0.5);
polygon.TestEdge(azi1, s12, false, false, perim, area);
result += checkEquals(area, r, 0.5);
polygon.TestEdge(azi1, s12, true, true, perim, area);
result += checkEquals(area, -r, 0.5);
polygon.TestEdge(azi1, s12, true, false, perim, area);
result += checkEquals(area, a0-r, 0.5);
polygon.AddPoint(lat[2], lon[2]);
polygon.Compute(false, true, perim, area);
result += checkEquals(area, r, 0.5);
polygon.Compute(false, false, perim, area);
result += checkEquals(area, r, 0.5);
polygon.Compute(true, true, perim, area);
result += checkEquals(area, -r, 0.5);
polygon.Compute(true, false, perim, area);
result += checkEquals(area, a0-r, 0.5);
return result;
}
static int Planimeter19() {
const Geodesic& g = Geodesic::WGS84();
PolygonArea polygon(g, false);
PolygonArea polyline(g, true);
T perim, area;
int result = 0;
polygon.Compute(false, true, perim, area);
result += checkEquals(area, 0, 0);
result += checkEquals(perim, 0, 0);
polygon.TestPoint(1, 1, false, true, perim, area);
result += checkEquals(area, 0, 0);
result += checkEquals(perim, 0, 0);
polygon.TestEdge(90, 1000, false, true, perim, area);
result += checkNaN(area);
result += checkNaN(perim);
polygon.AddPoint(1, 1);
polygon.Compute(false, true, perim, area);
result += checkEquals(area, 0, 0);
result += checkEquals(perim, 0, 0);
polyline.Compute(false, true, perim, area);
result += checkEquals(perim, 0, 0);
polyline.TestPoint(1, 1, false, true, perim, area);
result += checkEquals(perim, 0, 0);
polyline.TestEdge(90, 1000, false, true, perim, area);
result += checkNaN(perim);
polyline.AddPoint(1, 1);
polyline.Compute(false, true, perim, area);
result += checkEquals(perim, 0, 0);
polyline.AddPoint(1, 1);
polyline.TestEdge(90, 1000, false, true, perim, area);
result += checkEquals(perim, 1000, 1e-10);
polyline.TestPoint(2, 2, false, true, perim, area);
result += checkEquals(perim, 156876.149, 0.5e-3);
return result;
}
static int Planimeter21() {
const Geodesic& g = Geodesic::WGS84();
PolygonArea polygon(g);
T perim, area, lat = 45,
a = 39.2144607176828184218, s = 8420705.40957178156285,
r = 39433884866571.4277, a0 = 510065621724088.5093; int result = 0, i;
polygon.AddPoint(lat, 60);
polygon.AddPoint(lat, 180);
polygon.AddPoint(lat, -60);
polygon.AddPoint(lat, 60);
polygon.AddPoint(lat, 180);
polygon.AddPoint(lat, -60);
for (i = 3; i <= 4; ++i) {
polygon.AddPoint(lat, 60);
polygon.AddPoint(lat, 180);
polygon.TestPoint(lat, -60, false, true, perim, area);
result += checkEquals(area, i*r, 0.5);
polygon.TestPoint(lat, -60, false, false, perim, area);
result += checkEquals(area, i*r, 0.5);
polygon.TestPoint(lat, -60, true, true, perim, area);
result += checkEquals(area, -i*r, 0.5);
polygon.TestPoint(lat, -60, true, false, perim, area);
result += checkEquals(area, -i*r + a0, 0.5);
polygon.TestEdge(a, s, false, true, perim, area);
result += checkEquals(area, i*r, 0.5);
polygon.TestEdge(a, s, false, false, perim, area);
result += checkEquals(area, i*r, 0.5);
polygon.TestEdge(a, s, true, true, perim, area);
result += checkEquals(area, -i*r, 0.5);
polygon.TestEdge(a, s, true, false, perim, area);
result += checkEquals(area, -i*r + a0, 0.5);
polygon.AddPoint(lat, -60);
polygon.Compute(false, true, perim, area);
result += checkEquals(area, i*r, 0.5);
polygon.Compute(false, false, perim, area);
result += checkEquals(area, i*r, 0.5);
polygon.Compute(true, true, perim, area);
result += checkEquals(area, -i*r, 0.5);
polygon.Compute(true, false, perim, area);
result += checkEquals(area, -i*r + a0, 0.5);
}
return result;
}
static int Planimeter29() {
const Geodesic& g = Geodesic::WGS84();
PolygonArea polygon(g);
T perim, area;
int result = 0;
polygon.AddPoint(0, 0);
polygon.AddEdge( 90, 1000);
polygon.AddEdge( 0, 1000);
polygon.AddEdge(-90, 1000);
polygon.Compute(false, true, perim, area);
result += checkEquals(area, 1000000.0, 0.01);
return result;
}
int main() {
Utility::set_digits();
int n = 0, i;
i = Planimeter15(); n += i;
if (i)
cout << "Planimeter15 failure\n";
i = Planimeter19(); n += i;
if (i)
cout << "Planimeter19 failure\n";
i = Planimeter21(); n += i;
if (i)
cout << "Planimeter21 failure\n";
i = Planimeter29(); n += i;
if (i)
cout << "Planimeter29 failure\n";
if (n) {
cout << n << " failure" << (n > 1 ? "s" : "") << "\n";
return 1;
}
}