Skip to content

Commit

Permalink
Merge pull request #23 from mapcode-foundation/dev
Browse files Browse the repository at this point in the history
2.1.5 Much stricter unit test
  • Loading branch information
mapcodefoundation committed Sep 2, 2015
2 parents 3f1532a + dda1ea9 commit 9d8d020
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 31 deletions.
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

0 comments on commit 9d8d020

Please sign in to comment.