Skip to content

2.1.5 Much stricter unit test #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 2, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ decode Mapcodes.

# Release Notes

* 2.1.4
* 2.1.5

Added stricter unit tests

Added isInsideTerritory to API;
* 2.1.4

Added maxErrorinMeters to API;

Expand Down
74 changes: 47 additions & 27 deletions mapcodelib/mapcoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,14 @@ static int isInRange(int x, const int minx, int const maxx) // returns nonzero i
return 0;
}

static int fitsInside(const point32 *coord32, const int m) {
const mminforec *b = boundaries(m);
static int fitsInsideBoundaries(const point32 *coord32, const mminforec *b) {
return (b->miny <= coord32->lat && coord32->lat < b->maxy && isInRange(coord32->lon, b->minx, b->maxx));
}

static int fitsInside(const point32 *coord32, const int m) {
return fitsInsideBoundaries(coord32,boundaries(m));
}

static int xDivider4(const int miny, const int maxy) {
if (miny >= 0) { // both above equator? then miny is closest
return xdivider19[(miny) >> 19];
Expand All @@ -197,6 +200,22 @@ static int xDivider4(const int miny, const int maxy) {
return xdivider19[(-maxy) >> 19]; // both negative, so maxy is closest to equator
}

static mminforec *getExtendedBoundaries(mminforec *target, const mminforec *source, int deltaLat, int deltaLon) {
target->miny = source->miny - deltaLat;
target->minx = source->minx - deltaLon;
target->maxy = source->maxy + deltaLat;
target->maxx = source->maxx + deltaLon;
return target;
}

static int isNearBorderOf(const point32 *coord32, int m) {
mminforec tmp;
const mminforec *b=boundaries(m);
int xdiv8 = xDivider4(b->miny, b->maxy) / 6; // should be /8 but there's some extra margin
return (fitsInsideBoundaries(coord32, getExtendedBoundaries(&tmp,boundaries(m),+60,+xdiv8)) &&
(! fitsInsideBoundaries(coord32, getExtendedBoundaries(&tmp,boundaries(m),-60,-xdiv8))));
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Lowlevel ccode, iso, and disambiguation
Expand Down Expand Up @@ -1311,7 +1330,8 @@ static void encoderEngine(const int ccode, const encodeRec *enc, const int stop_
from = firstrec(ccode);
upto = lastrec(ccode);

if (ccode != ccode_earth) {
if (ccode != ccode_earth) // @@@ why?
{
if (!fitsInside(&enc->coord32, upto)) {
return;
}
Expand All @@ -1334,9 +1354,7 @@ static void encoderEngine(const int ccode, const encodeRec *enc, const int stop_
else if (recType(i) > 1) {
encodeAutoHeader(result, enc, i, extraDigits);
}
else if (i == upto && isRestricted(i) &&
isSubdivision(ccode)) // if the last item is a reference to a state's country
{
else if ((i == upto) && isSubdivision(ccode)) {
// *** do a recursive call for the parent ***
encoderEngine(ParentTerritoryOf(ccode), enc, stop_with_one_result, extraDigits, requiredEncoder, ccode);
return; /**/
Expand Down Expand Up @@ -2290,33 +2308,35 @@ double maxErrorInMeters(int extraDigits) {
return maxErrorInMetersForDigits[extraDigits];
}

// returns nonzero if coordinate is inside territory
int isInsideTerritory(double lat, double lon, int territoryCode) {
// returns nonzero if coordinate is near more than one territory border
int multipleBordersNearby(double lat, double lon, int territoryCode) {
const int ccode = territoryCode - 1;
if ((lat < -90) || (lat > 90) || (ccode < 0) || (ccode > ccode_earth)) {
return 0; // invalid arguments!
}
else {
int m;
point32 coord32;
const int from = firstrec(ccode);
const int upto = lastrec(ccode);
convertCoordsToMicrosAndFractions(&coord32, NULL, NULL, lat, lon);
if (fitsInside(&coord32, upto)) {
if ((ccode >= 0) && (ccode < ccode_earth)) { // valid territory, not earth
const int parentTerritoryCode = getParentCountryOf(territoryCode);
if (parentTerritoryCode >= 0) {
// there is a parent! check its borders as well...
if (multipleBordersNearby(lat, lon, parentTerritoryCode)) {
return 1;
}
}
{
int m;
int nrFound = 0;
const int from = firstrec(ccode);
const int upto = lastrec(ccode);
point32 coord32;
convertCoordsToMicrosAndFractions(&coord32, NULL, NULL, lat, lon);
for (m = upto; m >= from; m--) {
if (!isRestricted(m)) {
if (fitsInside(&coord32, m)) {
return 1;
if (isNearBorderOf(&coord32, m)) {
nrFound++;
if (nrFound > 1) {
return 1;
}
}
}
}
}
}
return 0;
}

// Check if a point is inside a territory and (if it has a parent) also inside its parent territory
int isFullyInsideTerritory(double lat, double lon, int territoryCode) {
return (isInsideTerritory(lat, lon, territoryCode) &&
((getParentCountryOf(territoryCode) < 0) || isInsideTerritory(lat, lon, getParentCountryOf(territoryCode))));
return 0;
}
2 changes: 1 addition & 1 deletion mapcodelib/mapcoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
extern "C" {
#endif

#define mapcode_cversion "2.1.4"
#define mapcode_cversion "2.1.5"

#define UWORD unsigned short int // 2-byte unsigned integer.

Expand Down
2 changes: 2 additions & 0 deletions unitttest/decode_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ typedef struct {

static const encode_test_record encode_test[] = {

{39.730401, -79.9541635, 0, 0, ""},
{39.730391, -79.954152, 0, 0, ""},
{5.60872800 , -10.17926200, 0, 0, ""},
{1.86496200 , 9.47899500, 0, 0, ""},
{33.864759999999997, 75, 0, 0, ""},
Expand Down
64 changes: 63 additions & 1 deletion unitttest/unittest.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ static void testEncodeAndDecode(const char *str, double y, double x, int localso
}

if (!found) { // within 7.5 meters, but not reproduced!
if ( isFullyInsideTerritory(lat, lon, tc2) ) { // but SHOULD be reproduced!
if ( ! multipleBordersNearby(lat, lon, tc2) ) { // but SHOULD be reproduced!
nrErrors++;
printf("*** ERROR *** %s does not re-encode (%0.15f,%0.15f) from (%0.15f,%0.15f)\n", str, lat, lon, y, x);
printGeneratedMapcodes("Global ", &mapcodes);
Expand Down Expand Up @@ -520,6 +520,67 @@ void distance_tests()
}


void test_territory_insides() {
if (strcmp(mapcode_cversion,"2.1.5") >=0) {
int i;
struct {
const char *territory;
double lat;
double lon;
int nearborders;
} iTestData[] = {
{"AAA", 0, 0,0},
{"AAA", 0, 999,0},
{"AAA", 90, 0,0},
{"AAA", -90, 0,0},
{"AAA", 0, 180,0},
{"AAA", 0, -180,0},
{"ATA", -90, 0,0},
{"ATA", -70, 0,0},

{"USA", 31, -70,0}, // interational waters (not in state)
{"MEX", 19,-115,0}, // interational waters (not in state)
{"MEX", 18.358525, -114.722672,0}, // Isla Clarion, not in a state
{"MX-ROO", 20, -87,0}, // just in ROO
{"MX-ROO", 20,-87.3,0}, // in ROO because in MEX
{"MEX", 20,-87.3,0}, // in ROO because in MEX

{"IND", 19, 87, 0},

{"NLD", 52.6, 4.8,0},
{"US-WV", 40.18, -80.87,0},
{"USA", 40.18, -80.87,0},
{"US-FL", 24.7, -82.7,0},
{"USA", 24.7, -82.7,0},
{"IN-TG", 16.13, 78.75,0},
{"IN-AP", 16.13, 78.75,0},
{"IN-MH", 16.13, 78.75,0},
{"IN-PY", 16.13, 78.75,0},
{"IND", 16.13, 78.75,0},
{"USA", 40.7, -74,0},

{"US-NY", 40.7, -74,1},
{"MEX", 20.252060, -89.779821,1},
{"NLD", 52.467314, 4.494037,1},
{"MEX",21.431778909671 , -89.779828861356,1},
{"MEX",21.431788272457 , -89.779820144176,1},

{NULL}
};

for (i = 0; iTestData[i].territory != NULL; i++) {
int territory = convertTerritoryIsoNameToCode(iTestData[i].territory,0);
nrTests++;
if (multipleBordersNearby(iTestData[i].lat, iTestData[i].lon, territory) != iTestData[i].nearborders) {
nrErrors++;
printf("*** ERROR *** multipleBordersNearby(%+18.13f,%+18.13f, \"%s\") not %d\n",
iTestData[i].lat, iTestData[i].lon, iTestData[i].territory, iTestData[i].nearborders);
}
}
}
}


void main() {
#ifdef XSIDE3
const char *mapcode_dataversion = "undefined";
Expand All @@ -536,6 +597,7 @@ void main() {
printf("-----------------------------------------------------------\nTerritory tests\n");
printf("%d territories\n", MAX_CCODE);
test_territories();
test_territory_insides();

printf("-----------------------------------------------------------\nFailing decode tests\n");
test_failing_decodes();
Expand Down