Extension talk:MathFunctions

From MediaWiki.org
Jump to navigation Jump to search

Adding a distance calculator function[edit]

Perhaps we could add a distance calculator, which would have as inputs the longitude and latitude of two points and would output the distance along the earth's surface. It would be straight-forward to code and I think very useful.
It would be helpful if it were compatible with the results returned by the geocode function.
For example suppose we have Point1: ( x1, y1)
where x1 is the degrees north ( if it is south then it will be negative )
y1 is the degrees east ( if it is west, then it will be negative )
and Point2: ( x2, y2 )

We first convert them to radians, ( x degrees = x * pi / 180 radians).
We assume that the sin and cos functions, which we use below, use radians, as is the case with most implementations of those functions.
We'll use capital letters for the points that have been converted to radians: ( X1, Y1 ) and ( X2, Y2)

Then the straight line distance through the earth between the two points is:

D_through = R * sqrt { (cos(X1)*sin(Y1) - cos(X2)*sin(Y2))^2 + (cos(X1)*cos(Y1) - cos(X2)*cos(Y2))^2 + ( sin(X1) - sin(X2))^2 } 

and the distance along the surface

D_surface = 2 * R * asin ( D_through / [ 2 * R ] ) 

where the radius of the earth R = [20,000 / pi] km ( i.e. 10,000 km from the equator to pole ).
For those who have not yet got used to modern units such as km, which have only been in common usage since 1793, we could possibly also allow a conversion a to miles (1.609344 km = 1 mile ). That would require another parameter specifying the units required.

  • The mathematical functions are available in the Math Functions Extension
  • To derive the equation above, convert polar coordinates to cartesian coordinates and then use Pythagorous.
  • We're ignoring the fact that the earth is not a perfect sphere, i.e. slightly flattened at the poles.
  • We also ignore altitude.
  • So the distance quoted is the distance along the surface of the earth at sea-level.

The code in C++ might look something like:

struct geo_cord
    double north_degrees;  // for points south of the equator this will be negative
    double east_degrees;   // for points west of greenwich meridian, this will be negative

const double degree_to_radian_factor = pi() / 180;
const double radius_of_earth_km      = 20000 / pi();

// The following function takes as input two geo-cordinates, 
// and returns the distance, in km, between them along the surface of the earth at sea level
// We assume a spherical earth and ignore altitude.
double distance( const geo_cord* pos1, const geo_cord* pos2)
   double north_radian_1 = pos1->north_degrees * degree_to_radian_factor;
   double north_radian_2 = pos2->north_degrees * degree_to_radian_factor;

   double east_radian_1  = pos1->east_degrees  * degree_to_radian_factor;
   double east_radian_2  = pos2->east_degrees  * degree_to_radian_factor;
   double cos_north1      = cos(north_radian_1);  // in case the compiler isn't clever enough to spot it, we calc
   double cos_north2      = cos(north_radian_2);  // the sin and cos first, to prevent repeated calls to the same function

   double sin_north1      = sin(north_radian_1);
   double sin_north2      = sin(north_radian_2);

   double cos_east1       = cos(east_radian_1);
   double cos_east2       = cos(east_radian_2);

   double sin_east1       = sin(east_radian_1);
   double sin_east2       = sin(east_radian_2);

   double term1           = cos_north1 * sin_east1 - cos_north2 * sin_east2; // we want to use term1 * term1 rather than term1 ^ 2 for speed
   double term2           = cos_north1 * cos_east1 - cos_north2 * cos_east2; // (though a clever compiler may well do that for us anyway)
   double term3           = sin_north1             - sin_north2;             // we certainly don't want to calc term1 twice,
                                                                             // that is why we do it here rather than below.
   // The stright-line distance between two points that sit on the surface of a unit circle. 
   double dist_thru_squared = term1 * term1 + term2 * term2 + term3 * term3;

   double surface_distance  = 2 * radius_of_earth * asin( sqrt( dist_thru_squared ) / 2 );  

   return surface_distance;
This looks interesting. I might implement it somehow in the code.  mgrabovský | talk  (DJ Jeri)  Tournesol.pngMW Support Team 16:39, 21 October 2008 (UTC)
Well, I've implemented it and now I'm testing it. I could post it here tomorrow.  mgrabovský | talk  (DJ Jeri)  Tournesol.pngMW Support Team 18:23, 21 October 2008 (UTC)

That's fast. Pnelnik 11:20, 22 October 2008 (UTC)

How did the testing go? I did some checking of the formula myself and it seemed fine. Here are simple test cases:

  • Distance ( ( 90, e1 ) , ( 0, e2 ) ) = 10,000 (km), no matter what e1 and e2 are, fixed distance from pole to equator.
  • Distance ( ( n1, e1 ) , ( n1, e1 ) ) = 0 (km), the distance from a point to itself is zero
  • Distance ( (-90, e1 ) , (-90, e2 ) ) = 0 (km), when you're on the south pole, the longitude doesn't matter
  • Distance ( ( n1, e1 ) , (-n1, e1 - 180 ) ) = 20,000 (km) the furthest point away on the globe

Pnelnik 22:14, 22 October 2008 (UTC)

Done, thanks :)  mgrabovský | talk  (DJ Jeri)  Tournesol.pngMW Support Team 13:03, 29 October 2008 (UTC)

math typing[edit]

Dos this extension include the typing of mathematical formulas (which is absent in the standard version and should be arranged manually)? Does it include the support of references templates (necessary to cite the description of the functions used)? Tori 09:14, 1 March 2011 (UTC)

No, it doesn't support such features. —Matěj Grabovský 17:17, 5 March 2011 (UTC)