Skip to content

Commit 1751489

Browse files
2.1.3 useful routine distanceInMeters added to API and unit test
1 parent c1165f7 commit 1751489

File tree

5 files changed

+81
-26
lines changed

5 files changed

+81
-26
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ decode Mapcodes.
5959

6060
# Release Notes
6161

62+
* 2.1.3
63+
64+
Added useful routine DistanceInMeters to API
65+
6266
* 2.1.2
6367

6468
Rewrote fraction floating points to integer arithmetic

mapcode_library_c.doc

25 KB
Binary file not shown.

mapcodelib/mapcoder.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,6 +1652,34 @@ static int decoderEngine(decodeRec *dec) {
16521652
}
16531653

16541654

1655+
1656+
// PI
1657+
#define _PI 3.14159265358979323846
1658+
1659+
// Radius of Earth.
1660+
#define EARTH_RADIUS_X_METERS 6378137
1661+
#define EARTH_RADIUS_Y_METERS 6356752
1662+
1663+
// Circumference of Earth.
1664+
#define EARTH_CIRCUMFERENCE_X (EARTH_RADIUS_X_METERS * 2 * _PI)
1665+
#define EARTH_CIRCUMFERENCE_Y (EARTH_RADIUS_Y_METERS * 2 * _PI)
1666+
1667+
// Meters per degree latitude is fixed. For longitude: use factor * cos(midpoint of two degree latitudes).
1668+
#define METERS_PER_DEGREE_LAT (EARTH_CIRCUMFERENCE_Y / 360.0)
1669+
#define METERS_PER_DEGREE_LON (EARTH_CIRCUMFERENCE_X / 360.0)
1670+
1671+
double distanceInMeters(double latDeg1, double lonDeg1, double latDeg2, double lonDeg2) {
1672+
if (lonDeg1 < 0 && lonDeg2 > 1) { lonDeg1 += 360; }
1673+
if (lonDeg2 < 0 && lonDeg1 > 1) { lonDeg2 += 360; }
1674+
{
1675+
const double dy = (latDeg2 - latDeg1) * METERS_PER_DEGREE_LAT;
1676+
const double dx = (lonDeg2 - lonDeg1) * METERS_PER_DEGREE_LON * cos((latDeg1 + latDeg2) * _PI / 360.0);
1677+
return sqrt(dx * dx + dy * dy);
1678+
}
1679+
}
1680+
1681+
1682+
16551683
#ifdef SUPPORT_FOREIGN_ALPHABETS
16561684

16571685
// WARNING - these alphabets have NOT yet been released as standard! use at your own risk! check www.mapcode.com for details.

mapcodelib/mapcoder.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
extern "C" {
1919
#endif
2020

21-
#define mapcode_cversion "2.1.2"
21+
#define mapcode_cversion "2.1.3"
2222

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

@@ -224,6 +224,12 @@ int getCountryOrParentCountry(int territoryCode);
224224
*/
225225
int getParentCountryOf(int territoryCode);
226226

227+
/**
228+
* Returns the distance in meters between two coordinates (latitude/longitude pairs)
229+
* CAVEAT: only works for coordinates that are within a few miles from each other.
230+
*/
231+
double distanceInMeters(double latDeg1, double lonDeg1, double latDeg2, double lonDeg2);
232+
227233
/**
228234
* Alphabets:
229235
*/

unitttest/unittest.c

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -98,30 +98,6 @@ static void alphabet_tests() {
9898
}
9999
}
100100

101-
// Returns distance in meters between two coordinates (that are not more than a mile apart)
102-
static double distanceInMeters(double latDeg1, double lonDeg1, double latDeg2, double lonDeg2) {
103-
double dx, dy, worstParallel = 0; // assume equator
104-
if (latDeg1 > latDeg2) {
105-
if (latDeg1 < 0) {
106-
worstParallel = latDeg2;
107-
} else if (latDeg2 > 0) {
108-
worstParallel = latDeg1;
109-
}
110-
}
111-
else {
112-
if (latDeg2 < 0) {
113-
worstParallel = latDeg1;
114-
} else if (latDeg1 > 0) {
115-
worstParallel = latDeg2;
116-
}
117-
}
118-
dy = (latDeg2 - latDeg1);
119-
if (lonDeg1 < 0 && lonDeg2 > 1) { lonDeg1 += 360; }
120-
if (lonDeg2 < 0 && lonDeg1 > 1) { lonDeg2 += 360; }
121-
dx = (lonDeg2 - lonDeg1) * cos((3.141592653589793238462643383279 / 180.0) * worstParallel);
122-
return sqrt(dx * dx + dy * dy) * (1000000.0 / 9);
123-
}
124-
125101

126102
//
127103
static void printGeneratedMapcodes(const Mapcodes *mapcodes) {
@@ -501,16 +477,57 @@ static void re_encode_tests() {
501477
}
502478

503479

480+
void distance_tests()
481+
{
482+
if (strcmp(mapcode_cversion,"2.1.3") >=0) {
483+
int i;
484+
double coordpairs[] = {
485+
// lat1, lon1, lat2, lon2, expected distance * 100000
486+
1,1,1,1,0,
487+
0,0,0,1,11131949079,
488+
89,0,89,1,194279300,
489+
3,0,3,1,11116693130,
490+
-3,0,-3,1,11116693130,
491+
-3,-179.5,-3,179.5,11116693130,
492+
-3,179.5,-3,-179.5,11116693130,
493+
3,8,3,9,11116693130,
494+
3,-8,3,-9,11116693130,
495+
3,-0.5,3,0.5,11116693130,
496+
54,5,54.000001,5,11095,
497+
54,5,54,5.000001,6543,
498+
54,5,54.000001,5.000001,12880,
499+
90,0,90,50,0,
500+
0.11,0.22,0.12,0.2333,185011466,
501+
-1
502+
};
503+
504+
for(i=0;coordpairs[i]!=-1;i+=5) {
505+
const double distance = distanceInMeters(
506+
coordpairs[i],coordpairs[i+1],
507+
coordpairs[i+2],coordpairs[i+3]);
508+
nrTests++;
509+
if ( floor(0.5+(100000.0 * distance)) != coordpairs[i+4] ) {
510+
nrErrors++;
511+
printf("*** ERROR *** distanceInMeters %d failed: %f\n",i,distance);;
512+
}
513+
}
514+
}
515+
}
516+
517+
504518
void main() {
505519
#ifdef XSIDE3
506520
const char *mapcode_dataversion = "undefined";
507521
#endif
508-
printf("Mapcode C Library Unit test 2.1.2\n");
522+
printf("Mapcode C Library Unit test 2.1.3\n");
509523
printf("Library version %s (Data version %s)\n", mapcode_cversion, mapcode_dataversion);
510524

511525
printf("-----------------------------------------------------------\nAlphabet tests\n");
512526
alphabet_tests();
513527

528+
printf("-----------------------------------------------------------\nDistance tests\n");
529+
distance_tests();
530+
514531
printf("-----------------------------------------------------------\nTerritory tests\n");
515532
printf("%d territories\n", MAX_CCODE);
516533
test_territories();

0 commit comments

Comments
 (0)