public static double Median(double[] angles)
{
double[] dm = new double[angles.Length];
for (int i = 0; i < angles.Length; i++)
{
double cosx = Math.Cos(angles[i]);
double sinx = Math.Sin(angles[i]);
for (int j = i + 1; j < angles.Length; j++)
{
double cosy = Math.Cos(angles[j]);
double siny = Math.Sin(angles[j]);
double den = (cosy * cosy + siny * siny);
double e = (cosx * cosy + sinx * siny) / den;
double f = (sinx * cosy - cosx * siny) / den;
double d = Math.Atan2(f, e);
if (d > 0)
{
dm[j] += 1;
dm[i] -= 1;
}
else if (d < 0)
{
dm[j] -= 1;
dm[i] += 1;
}
}
}
for (int i = 0; i < dm.Length; i++)
dm[i] = Math.Abs(dm[i]);
int imin = 0;
double dmin = dm[0];
for (int i = 1; i < dm.Length; i++)
{
if (dm[i] < dmin)
{
dmin = dm[i];
imin = i;
}
}
double md;
if (dm.Length % 2 != 0)
{
// is odd
md = angles[imin];
}
else
{
// is even
int count = 0;
double cos = 0, sin = 0;
for (int i = 0; i < dm.Length; i++)
{
if (dm[i] == dmin)
{
cos += Math.Cos(angles[i]);
sin += Math.Sin(angles[i]);
count++;
}
}
md = Math.Atan2(sin / count, cos / count);
}
double mean = Mean(angles);
double d1 = Distance(mean, md);
double d2 = Distance(mean, md + Math.PI);
if (Math.Abs(d1) > Math.Abs(d2))
md = Accord.Math.Tools.Mod(md + Math.PI, 2 * Math.PI);
return md;
}