I've implemented couple of wxMathPlot layers (bar chart and point layer), and I think I will do logarithm scale too . Also I'm developing some kind of gpPanel which use wxMathPlot library. Maybe someday in this year, when it's almost ready, I publish it.. :)
-JuPe
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
For those who are interested in logarithmic scales, maybe this function will get you started:
typedef enum
{
mpLOG_TYPE_1_2_5,
mpLOG_TYPE_1_3_10,
mpLOG_TYPE_10n,
mpLOG_TYPE_2DIGITS
} scaleType;
typedef struct
{
double min, max, min_exp, max_exp, delta, vals [10];
wxString label [10];
size_t num_labels;
scaleType type;
} scaleStruct_t;
// Configure a logarithm scale labels. NUM_TICKS labels will be assigned to
// the scale if scale.type == mpLOG_TYPES_2DIGITS; otherwise, the scale will
// have [1, 2, 5, 10, 20, ...], [1, 3, 10, 30, 100, ...], or even powers of
// ten (whichever fits the data best). For '2DIGITS' type the scale will be
// divided evenly and the labels' mantissae will keep two significant digits.
// If scale.type is assigned a different type prior to configuring the scale,
// the function will choose which of the remaining three types fit the data
// best and return this type in scale.type.
// Before calling this function, the program must search the data for the
// maximum value and the minimum value to be plotted and it must assign these
// to scale.max and scale.min, respectively.
// config_log_scale will assign the remaining scaleStruct_t entries:
// scale.min and scale.max will be unchanged
// scale.type will contain the type of interval chosen
// scale.num_labels will contain the number of labels needed to fill
// the entire length of the scale
// scale.vals will contain all of the chosen label values
// scale.labels will contain the text needed to draw the labels
#define NUM_TICKS 7.0
void LogScaleFrame::config_log_scale (scaleStruct_t & scale)
{
wxASSERT (scale.max > scale.min && scale.min > 0.0)
if (scale.type == mpLOG_TYPE_2DIGITS)
{
double a = log10 (scale.max / scale.min) / NUM_TICKS;
for (size_t i=0; i<=NUM_TICKS; i++)
{
scale.vals [i] = scale.min * pow (10.0, a * i);
scale.label [i].Printf (wxT("%2.1e"), scale.vals [i]);
}
scale.num_labels = NUM_TICKS;
}
else if (scale.max < 5.0e2 * scale.min) // 1, 2, 5, ... labels
{
scale.min_exp = floor (3.0 * log10 (scale.min)) / 3.0;
scale.max_exp = ceil (3.0 * log10 (scale.max)) / 3.0;
scale.delta = 1.0 / 3.0;
scale.type = mpLOG_TYPE_1_2_5;
}
else if (scale.max < 1.0e4 * scale.min) // 1, 3, 10, ... labels
{
scale.min_exp = floor (2.0 * log10 (scale.min)) / 2.0;
scale.max_exp = ceil (2.0 * log10 (scale.max)) / 2.0;
scale.delta = 1.0 / 2.0;
scale.type = mpLOG_TYPE_1_3_10;
}
else // exp10 (i, n+i, 2n+i, ... ) labels
{
scale.min_exp = floor (log10 (scale.min));
scale.max_exp = ceil (log10 (scale.max));
scale.delta = 1.0;
while (scale.max > pow (10.0, 7.0 * scale.delta) * scale.min)
scale.delta += 1.0;
scale.type = mpLOG_TYPE_10n;
}
int n=0;
for (double i=scale.min_exp; i<=scale.max_exp; i += scale.delta)
{
scale.vals [n] = pow (10.0, i);
int exp = 0;
while (scale.vals [n] < 1.0) scale.vals [n]= 10.0, exp--;
while (scale.vals [n] >= 10.0) scale.vals [n] /= 10.0, exp++;
scale.vals [n] = round (scale.vals [n]) * pow (10.0, exp);
n++;
}
scale.num_labels = n;
for (int n=0; n<scale.num_labels; n++)="" {="" wxASSERT="" (scale.vals="" <span="">[n] > 0.0);
double mantissa = scale.vals [n];
int exponent = 0;
while (mantissa < 10.0) mantissa = 10.0, exponent--;
while (mantissa >= 10.0) mantissa /= 10.0, exponent++;
if (mpLOG_TYPE_10n == scale.type)
scale.label[n].Printf (wxT("1e%+2d"), exponent);
else
scale.label[n].Printf (wxT("%de%+2d"), (int) round (mantissa), exponent);
wxString temp;
temp.Printf (wxT("config_log_scale - label [%d]: %s"), n, scale.label [n].c_str());
err.LogText(temp);
}
}
Hi everybody,
It could be nice to change the linear scale of the axes for non linear as Logarithmic.
Is it difficult ti implement ?
Thanks a lot
Rémy
Hi!
I've implemented couple of wxMathPlot layers (bar chart and point layer), and I think I will do logarithm scale too . Also I'm developing some kind of gpPanel which use wxMathPlot library. Maybe someday in this year, when it's almost ready, I publish it.. :)
-JuPe
For those who are interested in logarithmic scales, maybe this function will get you started:
typedef enum
{
mpLOG_TYPE_1_2_5,
mpLOG_TYPE_1_3_10,
mpLOG_TYPE_10n,
mpLOG_TYPE_2DIGITS
} scaleType;
typedef struct
{
double min, max, min_exp, max_exp, delta, vals [10];
wxString label [10];
size_t num_labels;
scaleType type;
} scaleStruct_t;
// Configure a logarithm scale labels. NUM_TICKS labels will be assigned to
// the scale if scale.type == mpLOG_TYPES_2DIGITS; otherwise, the scale will
// have [1, 2, 5, 10, 20, ...], [1, 3, 10, 30, 100, ...], or even powers of
// ten (whichever fits the data best). For '2DIGITS' type the scale will be
// divided evenly and the labels' mantissae will keep two significant digits.
// If scale.type is assigned a different type prior to configuring the scale,
// the function will choose which of the remaining three types fit the data
// best and return this type in scale.type.
// Before calling this function, the program must search the data for the
// maximum value and the minimum value to be plotted and it must assign these
// to scale.max and scale.min, respectively.
// config_log_scale will assign the remaining scaleStruct_t entries:
// scale.min and scale.max will be unchanged
// scale.type will contain the type of interval chosen
// scale.num_labels will contain the number of labels needed to fill
// the entire length of the scale
// scale.vals will contain all of the chosen label values
// scale.labels will contain the text needed to draw the labels
#define NUM_TICKS 7.0
void LogScaleFrame::config_log_scale (scaleStruct_t & scale)
{
wxASSERT (scale.max > scale.min && scale.min > 0.0)
if (scale.type == mpLOG_TYPE_2DIGITS)
{
double a = log10 (scale.max / scale.min) / NUM_TICKS;
for (size_t i=0; i<=NUM_TICKS; i++)
{
scale.vals [i] = scale.min * pow (10.0, a * i);
scale.label [i].Printf (wxT("%2.1e"), scale.vals [i]);
}
scale.num_labels = NUM_TICKS;
}
else if (scale.max < 5.0e2 * scale.min) // 1, 2, 5, ... labels
{
scale.min_exp = floor (3.0 * log10 (scale.min)) / 3.0;
scale.max_exp = ceil (3.0 * log10 (scale.max)) / 3.0;
scale.delta = 1.0 / 3.0;
scale.type = mpLOG_TYPE_1_2_5;
}
else if (scale.max < 1.0e4 * scale.min) // 1, 3, 10, ... labels
{
scale.min_exp = floor (2.0 * log10 (scale.min)) / 2.0;
scale.max_exp = ceil (2.0 * log10 (scale.max)) / 2.0;
scale.delta = 1.0 / 2.0;
scale.type = mpLOG_TYPE_1_3_10;
}
else // exp10 (i, n+i, 2n+i, ... ) labels
{
scale.min_exp = floor (log10 (scale.min));
scale.max_exp = ceil (log10 (scale.max));
scale.delta = 1.0;
while (scale.max > pow (10.0, 7.0 * scale.delta) * scale.min)
scale.delta += 1.0;
scale.type = mpLOG_TYPE_10n;
}
int n=0;
for (double i=scale.min_exp; i<=scale.max_exp; i += scale.delta)
{
scale.vals [n] = pow (10.0, i);
int exp = 0;
while (scale.vals [n] < 1.0) scale.vals [n] = 10.0, exp--;
while (scale.vals [n] >= 10.0) scale.vals [n] /= 10.0, exp++;
scale.vals [n] = round (scale.vals [n]) * pow (10.0, exp);
n++;
}
scale.num_labels = n;
for (int n=0; n<scale.num_labels; n++)="" {="" wxASSERT="" (scale.vals="" <span="">[n] > 0.0);
double mantissa = scale.vals [n];
int exponent = 0;
while (mantissa < 10.0) mantissa = 10.0, exponent--;
while (mantissa >= 10.0) mantissa /= 10.0, exponent++;
if (mpLOG_TYPE_10n == scale.type)
scale.label[n].Printf (wxT("1e%+2d"), exponent);
else
scale.label[n].Printf (wxT("%de%+2d"), (int) round (mantissa), exponent);
wxString temp;
temp.Printf (wxT("config_log_scale - label [%d]: %s"), n, scale.label [n].c_str());
err.LogText(temp);
}
}
Last edit: Byron 2014-10-02