static int EmptyPoly() { struct geod_geodesic g; struct geod_polygon p; double perim, area; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_polygon_init(&p, 0); geod_polygon_testpoint(&g, &p, 1, 1, 0, 1, &area, &perim); result += area == 0 ? 0 : 1; result += perim == 0 ? 0 : 1; geod_polygon_testedge(&g, &p, 90, 1000, 0, 1, &area, &perim); result += checkNaN(area); result += checkNaN(perim); geod_polygon_compute(&g, &p, 0, 1, &area, &perim); result += area == 0 ? 0 : 1; result += perim == 0 ? 0 : 1; geod_polygon_init(&p, 1); geod_polygon_testpoint(&g, &p, 1, 1, 0, 1, nullptr, &perim); result += perim == 0 ? 0 : 1; geod_polygon_testedge(&g, &p, 90, 1000, 0, 1, nullptr, &perim); result += checkNaN(perim); geod_polygon_compute(&g, &p, 0, 1, nullptr, &perim); result += perim == 0 ? 0 : 1; geod_polygon_addpoint(&g, &p, 1, 1); geod_polygon_testedge(&g, &p, 90, 1000, 0, 1, nullptr, &perim); result += checkEquals(perim, 1000, 1e-10); geod_polygon_testpoint(&g, &p, 2, 2, 0, 1, nullptr, &perim); result += checkEquals(perim, 156876.149, 0.5e-3); return result; }
static int Planimeter19() { /* Coverage tests, includes Planimeter19 - Planimeter20 (degenerate polygons) + extra cases. */ struct geod_geodesic g; struct geod_polygon p; double area, perim; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_polygon_init(&p, 0); geod_polygon_compute(&g, &p, 0, 1, &area, &perim); result += area == 0 ? 0 : 1; result += perim == 0 ? 0 : 1; geod_polygon_testpoint(&g, &p, 1, 1, 0, 1, &area, &perim); result += area == 0 ? 0 : 1; result += perim == 0 ? 0 : 1; geod_polygon_testedge(&g, &p, 90, 1000, 0, 1, &area, &perim); result += checkNaN(area); result += checkNaN(perim); geod_polygon_addpoint(&g, &p, 1, 1); geod_polygon_compute(&g, &p, 0, 1, &area, &perim); result += area == 0 ? 0 : 1; result += perim == 0 ? 0 : 1; geod_polygon_init(&p, 1); geod_polygon_compute(&g, &p, 0, 1, nullptr, &perim); result += perim == 0 ? 0 : 1; geod_polygon_testpoint(&g, &p, 1, 1, 0, 1, nullptr, &perim); result += perim == 0 ? 0 : 1; geod_polygon_testedge(&g, &p, 90, 1000, 0, 1, nullptr, &perim); result += checkNaN(perim); geod_polygon_addpoint(&g, &p, 1, 1); geod_polygon_compute(&g, &p, 0, 1, nullptr, &perim); result += perim == 0 ? 0 : 1; return result; }
static int Planimeter21() { /* Some test to add code coverage: multiple circlings of pole (includes Planimeter21 - Planimeter28) + invocations via testpoint and testedge. Some of the results for i = 4 in the loop are wrong because we don't reduce the area to the allowed range correctly. However these cases are not "simple" polygons, so we'll defer fixing the problem for now. */ struct geod_geodesic g; struct geod_polygon p; double area, lat = 45, a = 39.2144607176828184218, s = 8420705.40957178156285, r = 39433884866571.4277, /* Area for one circuit */ a0 = 510065621724088.5093; /* Ellipsoid area */ int result = 0, i; geod_init(&g, wgs84_a, wgs84_f); geod_polygon_init(&p, 0); geod_polygon_addpoint(&g, &p, lat, 60); geod_polygon_addpoint(&g, &p, lat, 180); geod_polygon_addpoint(&g, &p, lat, -60); geod_polygon_addpoint(&g, &p, lat, 60); geod_polygon_addpoint(&g, &p, lat, 180); geod_polygon_addpoint(&g, &p, lat, -60); for (i = 3; i <= 4; ++i) { geod_polygon_addpoint(&g, &p, lat, 60); geod_polygon_addpoint(&g, &p, lat, 180); geod_polygon_testpoint(&g, &p, lat, -60, 0, 1, &area, nullptr); if (i != 4) result += checkEquals(area, i*r, 0.5); geod_polygon_testpoint(&g, &p, lat, -60, 0, 0, &area, nullptr); if (i != 4) result += checkEquals(area, i*r, 0.5); geod_polygon_testpoint(&g, &p, lat, -60, 1, 1, &area, nullptr); if (i != 4) result += checkEquals(area, -i*r, 0.5); geod_polygon_testpoint(&g, &p, lat, -60, 1, 0, &area, nullptr); result += checkEquals(area, -i*r + a0, 0.5); geod_polygon_testedge(&g, &p, a, s, 0, 1, &area, nullptr); if (i != 4) result += checkEquals(area, i*r, 0.5); geod_polygon_testedge(&g, &p, a, s, 0, 0, &area, nullptr); if (i != 4) result += checkEquals(area, i*r, 0.5); geod_polygon_testedge(&g, &p, a, s, 1, 1, &area, nullptr); if (i != 4) result += checkEquals(area, -i*r, 0.5); geod_polygon_testedge(&g, &p, a, s, 1, 0, &area, nullptr); result += checkEquals(area, -i*r + a0, 0.5); geod_polygon_addpoint(&g, &p, lat, -60); geod_polygon_compute(&g, &p, 0, 1, &area, nullptr); if (i != 4) result += checkEquals(area, i*r, 0.5); geod_polygon_compute(&g, &p, 0, 0, &area, nullptr); if (i != 4) result += checkEquals(area, i*r, 0.5); geod_polygon_compute(&g, &p, 1, 1, &area, nullptr); if (i != 4) result += checkEquals(area, -i*r, 0.5); geod_polygon_compute(&g, &p, 1, 0, &area, nullptr); result += checkEquals(area, -i*r + a0, 0.5); } return result; }
SEXP polygonarea(SEXP longitude, SEXP latitude, SEXP pa, SEXP pf) { PROTECT(latitude = coerceVector(latitude, REALSXP)); PROTECT(longitude = coerceVector(longitude, REALSXP)); double *lat, *lon, *xr; lat = REAL(latitude); lon = REAL(longitude); double a = REAL(pa)[0]; double f = REAL(pf)[0]; double A, P; int i; struct geod_geodesic g; struct geod_polygon p; geod_init(&g, a, f); geod_polygon_init(&p, 0); for (i=0; i<length(latitude); i++) { geod_polygon_addpoint(&g, &p, lat[i], lon[i]); } geod_polygon_compute(&g, &p, 0, 1, &A, &P); SEXP r; PROTECT( r = allocVector(REALSXP, 1) ); xr = REAL(r); xr[0] = A; UNPROTECT(3); return(r); }
static int Planimeter15() { /* Coverage tests, includes Planimeter15 - Planimeter18 (combinations of reverse and sign) + calls to testpoint, testedge, geod_polygonarea. */ struct geod_geodesic g; struct geod_polygon p; double lat[] = {2, 1, 3}, lon[] = {1, 2, 3}; double area, s12, azi1; double r = 18454562325.45119, a0 = 510065621724088.5093; /* ellipsoid area */ int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_polygon_init(&p, 0); geod_polygon_addpoint(&g, &p, lat[0], lon[0]); geod_polygon_addpoint(&g, &p, lat[1], lon[1]); geod_polygon_testpoint(&g, &p, lat[2], lon[2], 0, 1, &area, nullptr); result += checkEquals(area, r, 0.5); geod_polygon_testpoint(&g, &p, lat[2], lon[2], 0, 0, &area, nullptr); result += checkEquals(area, r, 0.5); geod_polygon_testpoint(&g, &p, lat[2], lon[2], 1, 1, &area, nullptr); result += checkEquals(area, -r, 0.5); geod_polygon_testpoint(&g, &p, lat[2], lon[2], 1, 0, &area, nullptr); result += checkEquals(area, a0-r, 0.5); geod_inverse(&g, lat[1], lon[1], lat[2], lon[2], &s12, &azi1, nullptr); geod_polygon_testedge(&g, &p, azi1, s12, 0, 1, &area, nullptr); result += checkEquals(area, r, 0.5); geod_polygon_testedge(&g, &p, azi1, s12, 0, 0, &area, nullptr); result += checkEquals(area, r, 0.5); geod_polygon_testedge(&g, &p, azi1, s12, 1, 1, &area, nullptr); result += checkEquals(area, -r, 0.5); geod_polygon_testedge(&g, &p, azi1, s12, 1, 0, &area, nullptr); result += checkEquals(area, a0-r, 0.5); geod_polygon_addpoint(&g, &p, lat[2], lon[2]); geod_polygon_compute(&g, &p, 0, 1, &area, nullptr); result += checkEquals(area, r, 0.5); geod_polygon_compute(&g, &p, 0, 0, &area, nullptr); result += checkEquals(area, r, 0.5); geod_polygon_compute(&g, &p, 1, 1, &area, nullptr); result += checkEquals(area, -r, 0.5); geod_polygon_compute(&g, &p, 1, 0, &area, nullptr); result += checkEquals(area, a0-r, 0.5); geod_polygonarea(&g, lat, lon, 3, &area, nullptr); result += checkEquals(area, r, 0.5); return result; }
static void polylength(const struct geod_geodesic* g, double points[][2], int N, double* perimeter) { struct geod_polygon p; int i; geod_polygon_init(&p, 1); for (i = 0; i < N; ++i) geod_polygon_addpoint(g, &p, points[i][0], points[i][1]); geod_polygon_compute(g, &p, 0, 1, nullptr, perimeter); }
static void planimeter(const struct geod_geodesic* g, double points[][2], int N, double* perimeter, double* area) { struct geod_polygon p; int i; geod_polygon_init(&p, 0); for (i = 0; i < N; ++i) geod_polygon_addpoint(g, &p, points[i][0], points[i][1]); geod_polygon_compute(g, &p, 0, 1, area, perimeter); }
static int AddEdge1() { /* Check fix to transitdirect vs transit zero handling inconsistency */ struct geod_geodesic g; struct geod_polygon p; double area; int result = 0; geod_init(&g, wgs84_a, wgs84_f); geod_polygon_init(&p, 0); geod_polygon_addpoint(&g, &p, 0, 0); geod_polygon_addedge(&g, &p, 90, 1000); geod_polygon_addedge(&g, &p, 0, 1000); geod_polygon_addedge(&g, &p, -90, 1000); geod_polygon_compute(&g, &p, 0, 1, &area, nullptr); result += checkEquals(area, 1000000.0, 0.01); return result; }