mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
ScatterDraw: Added functions related to Process dialog as moving average, FFT, ...
git-svn-id: svn://ultimatepp.org/upp/trunk@9647 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
99a8409be4
commit
72659065f8
7 changed files with 414 additions and 42 deletions
|
|
@ -1,27 +1,35 @@
|
|||
#include <plugin/Eigen/Eigen.h>
|
||||
using namespace Eigen;
|
||||
|
||||
#include "ScatterDraw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
|
||||
#define Membercall(fun) (this->*fun)
|
||||
|
||||
double DataSource::Min(Getdatafun getdata) {
|
||||
|
||||
double DataSource::Min(Getdatafun getdata, int64& id) {
|
||||
double minVal = -DOUBLE_NULL;
|
||||
for (int64 i = 0; i < GetCount(); ++i) {
|
||||
double d = Membercall(getdata)(i);
|
||||
if (!IsNull(d) && minVal > d)
|
||||
if (!IsNull(d) && minVal > d) {
|
||||
minVal = d;
|
||||
id = i;
|
||||
}
|
||||
}
|
||||
if (minVal == -DOUBLE_NULL)
|
||||
return Null;
|
||||
return minVal;
|
||||
}
|
||||
|
||||
double DataSource::Max(Getdatafun getdata) {
|
||||
double DataSource::Max(Getdatafun getdata, int64& id) {
|
||||
double maxVal = DOUBLE_NULL;
|
||||
for (int64 i = 0; i < GetCount(); ++i) {
|
||||
double d = Membercall(getdata)(i);
|
||||
if (!IsNull(d) && maxVal < d)
|
||||
if (!IsNull(d) && maxVal < d) {
|
||||
maxVal = d;
|
||||
id = i;
|
||||
}
|
||||
}
|
||||
if (maxVal == DOUBLE_NULL)
|
||||
return Null;
|
||||
|
|
@ -63,8 +71,102 @@ double DataSource::Variance(Getdatafun getdata, double avg) {
|
|||
return ret/(count - 1);
|
||||
}
|
||||
|
||||
Vector<int64> DataSource::Envelope(Getdatafun getdataY, Getdatafun getdataX, double width, bool (*fun)(double a, double b)) {
|
||||
Vector<int64> ret;
|
||||
double width_2 = width/2.;
|
||||
|
||||
for (int i = 0; i < GetCount(); ++i) {
|
||||
double y = Membercall(getdataY)(i);
|
||||
double x = Membercall(getdataX)(i);
|
||||
if (IsNull(x) || IsNull(y))
|
||||
continue;
|
||||
int numComparisons = 0;
|
||||
for (int j = i-1; j >= 0; --j) {
|
||||
double ynext = Membercall(getdataY)(j);
|
||||
double xnext = Membercall(getdataX)(j);
|
||||
if (IsNull(xnext) || IsNull(ynext))
|
||||
continue;
|
||||
if ((x - xnext) > width_2)
|
||||
break;
|
||||
if (!fun(y, ynext)) {
|
||||
numComparisons = Null;
|
||||
break;
|
||||
}
|
||||
numComparisons++;
|
||||
}
|
||||
if (IsNull(numComparisons))
|
||||
continue;
|
||||
for (int j = i+1; j < GetCount(); ++j) {
|
||||
double ynext = Membercall(getdataY)(j);
|
||||
double xnext = Membercall(getdataX)(j);
|
||||
if (IsNull(xnext) || IsNull(ynext))
|
||||
continue;
|
||||
if ((xnext - x) > width_2)
|
||||
break;
|
||||
if (!fun(y, ynext)) {
|
||||
numComparisons = Null;
|
||||
break;
|
||||
}
|
||||
numComparisons++;
|
||||
}
|
||||
if (IsNull(numComparisons))
|
||||
continue;
|
||||
if (numComparisons > 2)
|
||||
ret << i;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool GreaterThan(double a, double b) {return a > b;}
|
||||
bool LowerThan(double a, double b) {return a < b;}
|
||||
|
||||
Vector<int64> DataSource::UpperEnvelope(Getdatafun getdataY, Getdatafun getdataX, double width) {return Envelope(getdataY, getdataX, width, GreaterThan);}
|
||||
Vector<int64> DataSource::LowerEnvelope(Getdatafun getdataY, Getdatafun getdataX, double width) {return Envelope(getdataY, getdataX, width, LowerThan);}
|
||||
|
||||
Vector<Pointf> DataSource::MovingAverage(Getdatafun getdataY, Getdatafun getdataX, double width) {
|
||||
Vector<Pointf> ret;
|
||||
double width_2 = width/2.;
|
||||
|
||||
for (int i = 0; i < GetCount(); ++i) {
|
||||
double y = Membercall(getdataY)(i);
|
||||
double x = Membercall(getdataX)(i);
|
||||
if (IsNull(x) || IsNull(y))
|
||||
continue;
|
||||
int numAvg = 1;
|
||||
double sum = y;
|
||||
int j;
|
||||
for (j = i-1; j >= 0; --j) {
|
||||
double ynext = Membercall(getdataY)(j);
|
||||
double xnext = Membercall(getdataX)(j);
|
||||
if (IsNull(xnext) || IsNull(ynext))
|
||||
continue;
|
||||
if ((x - xnext) > width_2)
|
||||
break;
|
||||
sum += ynext;
|
||||
numAvg++;
|
||||
}
|
||||
if (j < 0)
|
||||
continue;
|
||||
for (j = i+1; j < GetCount(); ++j) {
|
||||
double ynext = Membercall(getdataY)(j);
|
||||
double xnext = Membercall(getdataX)(j);
|
||||
if (IsNull(xnext) || IsNull(ynext))
|
||||
continue;
|
||||
if ((xnext - x) > width_2)
|
||||
break;
|
||||
sum += ynext;
|
||||
numAvg++;
|
||||
}
|
||||
if (j == GetCount())
|
||||
continue;
|
||||
ret << Pointf(x, sum/numAvg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
double DataSource::StdDev(Getdatafun getdata, double avg) {
|
||||
return sqrt(Variance(getdata, avg));
|
||||
double var = Variance(getdata, avg);
|
||||
return IsNull(var) ? Null : sqrt(var);
|
||||
}
|
||||
|
||||
double DataSource::SinEstim_Amplitude(double avg) {
|
||||
|
|
@ -76,13 +178,20 @@ bool DataSource::SinEstim_FreqPhase(double &frequency, double &phase, double avg
|
|||
return false;
|
||||
if (IsNull(avg))
|
||||
avg = AvgY();
|
||||
bool firstIsToPositive = (y(int64(0)) - avg) < 0;
|
||||
int64 firstId;
|
||||
for (firstId = 0; firstId < GetCount(); ++firstId)
|
||||
if (!IsNull(x(firstId)) && !IsNull(y(firstId)))
|
||||
break;
|
||||
bool firstIsToPositive = (y(firstId) - avg) < 0;
|
||||
bool isPossitive = !firstIsToPositive;
|
||||
double T = 0;
|
||||
int numT = 0;
|
||||
double lastZero = Null;
|
||||
double firstZero;
|
||||
for (int64 id = 1; id < GetCount(); ++id) {
|
||||
firstId++;
|
||||
for (int64 id = firstId; id < GetCount(); ++id) {
|
||||
if (IsNull(x(id)) || IsNull(y(id)))
|
||||
continue;
|
||||
if (((y(id) - avg) > 0) != isPossitive) {
|
||||
isPossitive = !isPossitive;
|
||||
double zero = x(id-1) - (y(id-1) - avg)*(x(id) - x(id-1))/(y(id) - y(id-1));
|
||||
|
|
@ -111,4 +220,132 @@ double CArray::znFixed(int n, int64 id) {
|
|||
return Null;
|
||||
}
|
||||
|
||||
|
||||
Vector<Pointf> DataSource::FFT(Getdatafun getdata, double tSample) {
|
||||
int numData = int(GetCount());
|
||||
VectorXd timebuf(numData);
|
||||
int num = 0;
|
||||
for (int i = 0; i < numData; ++i) {
|
||||
double data = Membercall(getdata)(i);
|
||||
if (!IsNull(data)) {
|
||||
timebuf[i] = Membercall(getdata)(i);
|
||||
num++;
|
||||
}
|
||||
}
|
||||
Vector<Pointf> res;
|
||||
if (num < 3)
|
||||
return res;
|
||||
timebuf.resize(num);
|
||||
|
||||
VectorXcd freqbuf;
|
||||
try {
|
||||
Eigen::FFT<double> fft;
|
||||
fft.SetFlag(fft.HalfSpectrum);
|
||||
fft.fwd(freqbuf, timebuf);
|
||||
} catch(...) {
|
||||
return res;
|
||||
}
|
||||
for (int i = 1; i < freqbuf.size(); ++i) {
|
||||
double T = (tSample*numData)/i;
|
||||
res << Pointf(T, 2*std::abs(freqbuf[i])/numData);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool Spline::Load(Vector<double>& xdata, Vector<double>& ydata)
|
||||
{
|
||||
if(!IsInputSane(xdata, ydata))
|
||||
return false;
|
||||
|
||||
int n = xdata.GetCount() - 1;
|
||||
|
||||
Vector<double> h;
|
||||
for(int i = 0; i < n; ++i)
|
||||
h << (xdata[i+1] - xdata[i]);
|
||||
|
||||
Vector<double> alpha;
|
||||
for(int i = 0; i < n; ++i)
|
||||
alpha << (3.*(ydata[i+1] - ydata[i])/h[i] - 3*(ydata[i]-ydata[i-1])/h[i-1]);
|
||||
|
||||
Vector<double> l, mu, z;
|
||||
l.SetCount(n+1);
|
||||
mu.SetCount(n+1);
|
||||
z.SetCount(n+1);
|
||||
l[0] = 1;
|
||||
mu[0] = 0;
|
||||
z[0] = 0;
|
||||
|
||||
for(int i = 1; i < n; ++i) {
|
||||
l[i] = 2.*(xdata[i+1] - xdata[i-1]) - h[i-1]*mu[i-1];
|
||||
mu[i] = h[i]/l[i];
|
||||
z[i] = (alpha[i] - h[i-1]*z[i-1])/l[i];
|
||||
}
|
||||
|
||||
l[n] = 1.;
|
||||
z[n] = 0;
|
||||
|
||||
Vector<double> c;
|
||||
c.SetCount(n+1);
|
||||
c[n] = 0;
|
||||
|
||||
Vector<double> b, d;
|
||||
b.SetCount(n);
|
||||
d.SetCount(n);
|
||||
for(int j = n-1; j >= 0; --j) {
|
||||
c[j] = z[j] - mu[j] * c[j+1];
|
||||
b[j] = (ydata[j+1] - ydata[j])/h[j] - h[j]*(c[j+1] + 2*c[j])/3.;
|
||||
d[j] = (c[j+1] - c[j])/3./h[j];
|
||||
}
|
||||
|
||||
coeff.SetCount(n);
|
||||
for(int i = 0; i < n; ++i) {
|
||||
coeff[i].a = ydata[i];
|
||||
coeff[i].b = b[i];
|
||||
coeff[i].c = c[i];
|
||||
coeff[i].d = d[i];
|
||||
coeff[i].x = xdata[i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
double Spline::GetY(double x)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < coeff.size(); j++) {
|
||||
if(coeff[j].x > x) {
|
||||
if(j == 0)
|
||||
j++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
j--;
|
||||
|
||||
double dx = x - coeff[j].x;
|
||||
return coeff[j].a + coeff[j].b*dx + coeff[j].c*dx*dx + coeff[j].d*dx*dx*dx;
|
||||
}
|
||||
|
||||
bool Spline::IsInputSane(Vector<double>& xdata, Vector<double>& ydata)
|
||||
{
|
||||
if(xdata.IsEmpty() || ydata.IsEmpty())
|
||||
return false;
|
||||
|
||||
if(!IsSorted(xdata))
|
||||
return false;
|
||||
|
||||
bool first = true;
|
||||
double xold;
|
||||
for(double x : xdata) {
|
||||
if(first)
|
||||
xold = x;
|
||||
else {
|
||||
first = false;
|
||||
if( fabs(x - xold) < 1)
|
||||
return false;
|
||||
xold = x;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
@ -3,6 +3,20 @@
|
|||
|
||||
NAMESPACE_UPP
|
||||
|
||||
template <class T>
|
||||
bool IsSorted(T& data) {
|
||||
int num = data.GetCount();
|
||||
if (num == 0)
|
||||
return false;
|
||||
if (num == 1)
|
||||
return 1;
|
||||
for (int i = 1; i < num; ++i) {
|
||||
if (data[i] < data[i - 1])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class DataSource {
|
||||
public:
|
||||
typedef double (DataSource::*Getdatafun)(int64 id);
|
||||
|
|
@ -26,29 +40,79 @@ public:
|
|||
bool IsExplicit() {return isExplicit;}
|
||||
bool IsDeleted() {return key != 111111;}
|
||||
|
||||
virtual double MinY() {return Min(&DataSource::y);}
|
||||
virtual double MinX() {return Min(&DataSource::x);}
|
||||
virtual double MinY(int64& id) {return Min(&DataSource::y, id);}
|
||||
virtual double MinY() {int64 dummy; return Min(&DataSource::y, dummy);}
|
||||
virtual double MinX(int64& id) {return Min(&DataSource::x, id);}
|
||||
virtual double MinX() {int64 dummy; return Min(&DataSource::x, dummy);}
|
||||
|
||||
virtual double MaxY() {return Max(&DataSource::y);}
|
||||
virtual double MaxX() {return Max(&DataSource::x);}
|
||||
virtual double MaxY(int64& id) {return Max(&DataSource::y, id);}
|
||||
virtual double MaxY() {int64 dummy; return Max(&DataSource::y, dummy);}
|
||||
virtual double MaxX(int64& id) {return Max(&DataSource::x, id);}
|
||||
virtual double MaxX() {int64 dummy; return Max(&DataSource::x, dummy);}
|
||||
|
||||
virtual double AvgY() {return Avg(&DataSource::y);}
|
||||
virtual double AvgY() {return Avg(&DataSource::y);}
|
||||
virtual double AvgX() {return Avg(&DataSource::x);}
|
||||
virtual double StdDevY(double avg = Null) {return StdDev(&DataSource::y, avg);}
|
||||
virtual double VarianceY(double avg = Null) {return Variance(&DataSource::y, avg);}
|
||||
virtual Vector<int64> UpperEnvelopeY(double width) {return UpperEnvelope(&DataSource::y, &DataSource::x, width);}
|
||||
virtual Vector<int64> LowerEnvelopeY(double width) {return LowerEnvelope(&DataSource::y, &DataSource::x, width);}
|
||||
virtual Vector<Pointf> MovingAverageY(double width) {return MovingAverage(&DataSource::y, &DataSource::x, width);}
|
||||
|
||||
Upp::Vector<Pointf> FFTY(double tSample) {return FFT(&DataSource::y, tSample);}
|
||||
|
||||
double Min(Getdatafun getdata);
|
||||
double Max(Getdatafun getdata);
|
||||
double Min(Getdatafun getdata, int64& id);
|
||||
double Max(Getdatafun getdata, int64& id);
|
||||
double Avg(Getdatafun getdata);
|
||||
double StdDev(Getdatafun getdata, double avg = Null);
|
||||
double Variance(Getdatafun getdata, double avg = Null);
|
||||
Vector<int64> UpperEnvelope(Getdatafun getdataY, Getdatafun getdataX, double width);
|
||||
Vector<int64> LowerEnvelope(Getdatafun getdataY, Getdatafun getdataX, double width);
|
||||
Vector<Pointf> MovingAverage(Getdatafun getdataY, Getdatafun getdataX, double width);
|
||||
double SinEstim_Amplitude(double avg = Null);
|
||||
bool SinEstim_FreqPhase(double &frequency, double &phase, double avg = Null);
|
||||
Vector<Pointf> FFT(Getdatafun getdata, double tSample);
|
||||
|
||||
protected:
|
||||
bool isParam, isExplicit;
|
||||
|
||||
private:
|
||||
int key;
|
||||
|
||||
Vector<int64> Envelope(Getdatafun getdataY, Getdatafun getdataX, double width, bool (*fun)(double a, double b));
|
||||
};
|
||||
|
||||
class DataSetCond : public DataSource {
|
||||
private:
|
||||
DataSource *data;
|
||||
double xGreater, xLower;
|
||||
|
||||
public:
|
||||
DataSetCond() {data = 0;}
|
||||
DataSetCond(DataSource &_data, double _xGreater, double _xLower) {Init(_data, _xGreater, _xLower);}
|
||||
void Init(DataSource &_data, double _xGreater, double _xLower) {
|
||||
data = &_data;
|
||||
xGreater = _xGreater;
|
||||
xLower = _xLower;
|
||||
}
|
||||
bool Check(int64 id) {
|
||||
double x = data->x(id);
|
||||
if (!IsNull(xGreater) && xGreater > x)
|
||||
return false;
|
||||
if (!IsNull(xLower) && xLower < x)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
virtual inline double y(int64 id) {return Check(id) ? data->y(id) : Null;}
|
||||
virtual inline double x(int64 id) {return Check(id) ? data->x(id) : Null;}
|
||||
virtual inline double x(double t) {
|
||||
double x = data->x(t);
|
||||
if (!IsNull(xGreater) && xGreater > x)
|
||||
return Null;
|
||||
if (!IsNull(xLower) && xLower < x)
|
||||
return Null;
|
||||
return x;
|
||||
}
|
||||
virtual inline int64 GetCount() {return data->GetCount();}
|
||||
};
|
||||
|
||||
class CArray : public DataSource {
|
||||
|
|
@ -338,6 +402,18 @@ public:
|
|||
virtual inline int64 GetCount() {return numPoints;}
|
||||
};
|
||||
|
||||
class Spline {
|
||||
public:
|
||||
bool Load(Vector<double>& xdata, Vector<double>& ydata);
|
||||
double GetY(double x);
|
||||
|
||||
private:
|
||||
struct Coeff{double a, b, c, d, x;};
|
||||
Vector<Coeff> coeff;
|
||||
|
||||
bool IsInputSane(Vector<double>& xdata, Vector<double>& ydata);
|
||||
};
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -64,10 +64,13 @@ ExplicitEquation::FitError ExplicitEquation::Fit(DataSource &series, double &r2)
|
|||
double mean = series.AvgY();
|
||||
double sse = 0, sst = 0;
|
||||
for (int64 i = 0; i < series.GetCount(); ++i) {
|
||||
double res = series.y(i) - f(series.x(i));
|
||||
sse += res*res;
|
||||
double d = series.y(i) - mean;
|
||||
sst += d*d;
|
||||
double y = series.y(i);
|
||||
if (!IsNull(y)) {
|
||||
double res = y - f(series.x(i));
|
||||
sse += res*res;
|
||||
double d = y - mean;
|
||||
sst += d*d;
|
||||
}
|
||||
}
|
||||
r2 = 1 - sse/sst;
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,20 @@ protected:
|
|||
static VectorMap<String, CreateFunc>& classMap() {static VectorMap<String, CreateFunc> cMap; return cMap;}
|
||||
};
|
||||
|
||||
class AvgEquation : public ExplicitEquation {
|
||||
public:
|
||||
AvgEquation() {SetCoeff(0);}
|
||||
AvgEquation(double c0) {SetCoeff(c0);}
|
||||
double f(double x) {return coeff[0];}
|
||||
virtual String GetName() {return t_("Average");}
|
||||
virtual String GetEquation(int numDigits = 3) {
|
||||
String ret = Format("%s", FormatCoeff(0, numDigits));
|
||||
return ret;
|
||||
}
|
||||
void SetDegree(int num) {NEVER();}
|
||||
virtual void GuessCoeff(DataSource &series) {coeff[0] = series.AvgY();}
|
||||
};
|
||||
|
||||
class LinearEquation : public ExplicitEquation {
|
||||
public:
|
||||
LinearEquation() {SetCoeff(0, 0);}
|
||||
|
|
|
|||
|
|
@ -369,9 +369,9 @@ ScatterDraw &ScatterDraw::SetXYMin(double xmin, double ymin, double ymin2) {
|
|||
}
|
||||
|
||||
// Deprecated
|
||||
void ScatterDraw::FitToData(bool vertical, double factor) {
|
||||
/*void ScatterDraw::FitToData(bool vertical, double factor) {
|
||||
ZoomToFit(true, vertical, factor);
|
||||
}
|
||||
}*/
|
||||
|
||||
void ScatterDraw::ZoomToFit(bool horizontal, bool vertical, double factor) {
|
||||
if (linkedMaster) {
|
||||
|
|
@ -689,6 +689,10 @@ ScatterDraw &ScatterDraw::AddSeries(DataSource &data) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
DataSource &ScatterDraw::GetSeries(int index) {
|
||||
return series[index].GetDataSource();
|
||||
}
|
||||
|
||||
ScatterDraw &ScatterDraw::_AddSeries(DataSource *data) {
|
||||
ScatterSeries &s = series.Add();
|
||||
s.Init(series.GetCount()-1);
|
||||
|
|
@ -963,10 +967,11 @@ const String ScatterDraw::GetUnitsY(int index) {
|
|||
return series[index].unitsY;
|
||||
}
|
||||
|
||||
void ScatterDraw::SetDataColor(int index, const Color& color) {
|
||||
ScatterDraw& ScatterDraw::SetDataColor(int index, const Color& color) {
|
||||
ASSERT(IsValid(index));
|
||||
series[index].color = color;
|
||||
Refresh();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color ScatterDraw::GetDataColor(int index) const {
|
||||
|
|
@ -974,10 +979,11 @@ Color ScatterDraw::GetDataColor(int index) const {
|
|||
return series[index].color;
|
||||
}
|
||||
|
||||
void ScatterDraw::SetDataThickness(int index, double thickness) {
|
||||
ScatterDraw& ScatterDraw::SetDataThickness(int index, double thickness) {
|
||||
ASSERT(IsValid(index));
|
||||
series[index].thickness = thickness;
|
||||
Refresh();
|
||||
return *this;
|
||||
}
|
||||
|
||||
double ScatterDraw::GetDataThickness(int index) const {
|
||||
|
|
@ -985,10 +991,11 @@ double ScatterDraw::GetDataThickness(int index) const {
|
|||
return series[index].thickness;
|
||||
}
|
||||
|
||||
void ScatterDraw::SetFillColor(int index, const Color& color) {
|
||||
ScatterDraw& ScatterDraw::SetFillColor(int index, const Color& color) {
|
||||
ASSERT(IsValid(index));
|
||||
series[index].fillColor = color;
|
||||
Refresh();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color ScatterDraw::GetFillColor(int index) const {
|
||||
|
|
@ -1068,6 +1075,15 @@ ScatterDraw &ScatterDraw::SetSequentialX(bool sequential) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool ScatterDraw::GetSequentialX(int index) {
|
||||
ASSERT(IsValid(index));
|
||||
return series[index].sequential;
|
||||
}
|
||||
|
||||
bool ScatterDraw::GetSequentialX() {
|
||||
return GetSequentialX(series.GetCount()-1);
|
||||
}
|
||||
|
||||
ScatterDraw &ScatterDraw::SetSequentialXAll(bool sequential) {
|
||||
for (int i = 0; i < series.GetCount(); ++i)
|
||||
SetSequentialX(i, sequential);
|
||||
|
|
@ -1558,6 +1574,7 @@ ScatterDraw::ScatterDraw() {
|
|||
lastyRange = yRange;
|
||||
highlight_0 = Null;
|
||||
labelsChanged = false;
|
||||
legendAnchor = LEGEND_ANCHOR_RIGHT_TOP;
|
||||
legendPos = Point(5, 5);
|
||||
legendNumCols = 1;
|
||||
legendAnchor = LEGEND_TOP;
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ protected:
|
|||
public:
|
||||
ScatterSeries() {pD = 0;}
|
||||
void SetDataSource(DataSource *pointsData, bool ownsData = true) {pD = pointsData; owns = ownsData;}
|
||||
DataSource &GetDataSource() {return *pD;}
|
||||
inline DataSource *PointsData() {ASSERT_(!pD->IsDeleted(), "DataSource in ScatterCtrl/Draw has been deleted.\nIt has been probably declared in a function."); return pD;}
|
||||
~ScatterSeries() {if(pD && owns) delete pD;}
|
||||
private:
|
||||
|
|
@ -156,8 +157,8 @@ public:
|
|||
LEGEND_ANCHOR_LEFT_BOTTOM,
|
||||
LEGEND_ANCHOR_RIGHT_BOTTOM
|
||||
};
|
||||
ScatterDraw& SetLegendAnchor(int anchor) {legendAnchor = anchor; return *this;}
|
||||
int GetLegendAnchor() {return legendAnchor;}
|
||||
ScatterDraw& SetLegendAnchor(LEGEND_POS anchor) {legendAnchor = anchor; return *this;}
|
||||
LEGEND_POS GetLegendAnchor() {return legendAnchor;}
|
||||
ScatterDraw& SetLegendFillColor(const Color &color) {legendFillColor = color; return *this;}
|
||||
ScatterDraw& SetLegendBorderColor(const Color &color) {legendBorderColor = color; return *this;}
|
||||
Color& GetLegendFillColor() {return legendFillColor;}
|
||||
|
|
@ -171,7 +172,7 @@ public:
|
|||
double GetYMax();
|
||||
double GetYMin();*/
|
||||
|
||||
void FitToData(bool vertical = false, double factor = 0); // Deprecated
|
||||
//void FitToData(bool vertical = false, double factor = 0); // Deprecated
|
||||
void ZoomToFit(bool horizontal = true, bool vertical = false, double factor = 0);
|
||||
void Zoom(double scale, bool hor = true, bool ver = true);
|
||||
void Scroll(double factorX, double factorY);
|
||||
|
|
@ -181,6 +182,9 @@ public:
|
|||
ScatterDraw &SetZoomStyleY(ZoomStyle style = TO_CENTER) {zoomStyleY = style; return *this;}
|
||||
|
||||
ScatterDraw& SetRange(double rx, double ry, double ry2 = 100);
|
||||
double GetRangeX() {return xRange;}
|
||||
double GetRangeY() {return yRange;}
|
||||
double GetRangeY2() {return yRange2;}
|
||||
ScatterDraw& SetRangeLinked(double rx, double ry, double ry2 = 100);
|
||||
double GetXRange()const {return xRange;}
|
||||
double GetYRange()const {return yRange;}
|
||||
|
|
@ -190,6 +194,7 @@ public:
|
|||
ScatterDraw &SetMaxMajorUnits(int maxX, int maxY) {maxMajorUnitsX = maxX; maxMajorUnitsY = maxY; return *this;}
|
||||
double GetMajorUnitsX() {return xMajorUnit;}
|
||||
double GetMajorUnitsY() {return yMajorUnit;}
|
||||
double GetMajorUnitsY2() {return yMajorUnit2;}
|
||||
ScatterDraw& SetMinUnits(double ux, double uy);
|
||||
double GetXMinUnit () const {return xMinUnit;}
|
||||
double GetYMinUnit () const {return yMinUnit;}
|
||||
|
|
@ -272,6 +277,8 @@ public:
|
|||
template <class X, class Y>
|
||||
ScatterDraw &AddSeries(ArrayMap<X, Y> &data) {return _AddSeries(new ArrayMapXY<X, Y>(data));}
|
||||
|
||||
DataSource &GetSeries(int index);
|
||||
|
||||
ScatterDraw &InsertSeries(int index, double *yData, int numData, double x0 = 0, double deltaX = 1);
|
||||
ScatterDraw &InsertSeries(int index, double *xData, double *yData, int numData);
|
||||
ScatterDraw &InsertSeries(int index, Vector<double> &xData, Vector<double> &yData);
|
||||
|
|
@ -375,11 +382,14 @@ public:
|
|||
ScatterDraw& SetDrawYReticle(bool set = true);
|
||||
ScatterDraw& SetDrawY2Reticle(bool set = true);
|
||||
|
||||
void SetDataColor(int index, const Color& pcolor);
|
||||
ScatterDraw &SetDataColor(int index, const Color& pcolor);
|
||||
ScatterDraw &SetDataColor(const Color& pcolor) {return SetDataColor(series.GetCount() - 1, pcolor);}
|
||||
Color GetDataColor (int index) const;
|
||||
void SetDataThickness(int index, double thick);
|
||||
ScatterDraw &SetDataThickness(int index, double thick);
|
||||
ScatterDraw &SetDataThickness(double thick) {return SetDataThickness(series.GetCount() - 1, thick);}
|
||||
double GetDataThickness(int index) const;
|
||||
void SetFillColor(int index, const Color& color);
|
||||
ScatterDraw &SetFillColor(int index, const Color& color);
|
||||
ScatterDraw &SetFillColor(const Color& color) {return SetDataColor(series.GetCount() - 1, color);}
|
||||
Color GetFillColor(int index) const;
|
||||
|
||||
ScatterDraw &SetMarkWidth(int index, double width);
|
||||
|
|
@ -400,7 +410,9 @@ public:
|
|||
void SetSequentialX(int index, bool sequential = true);
|
||||
ScatterDraw &SetSequentialX(bool sequential = true);
|
||||
ScatterDraw &SetSequentialXAll(bool sequential = true);
|
||||
|
||||
bool GetSequentialX(int index);
|
||||
bool GetSequentialX();
|
||||
|
||||
void Show(int index, bool show = true);
|
||||
bool IsVisible(int index);
|
||||
ScatterDraw &ShowAll(bool show = true);
|
||||
|
|
@ -430,6 +442,7 @@ public:
|
|||
ScatterDraw& SetMaxYmax(double val) {maxYmax = val; return *this;}
|
||||
|
||||
ScatterDraw& SetFastViewX(bool set = true) {fastViewX = set; return *this;}
|
||||
bool GetFastViewX() {return fastViewX;}
|
||||
|
||||
double GetXByPoint(double x);
|
||||
double GetYByPoint(double y);
|
||||
|
|
@ -497,7 +510,7 @@ protected:
|
|||
|
||||
Point legendPos;
|
||||
int legendNumCols;
|
||||
int legendAnchor;
|
||||
LEGEND_POS legendAnchor;
|
||||
int legendRowSpacing;
|
||||
Color legendFillColor;
|
||||
Color legendBorderColor;
|
||||
|
|
@ -811,16 +824,16 @@ void ScatterDraw::Plot(T& w, const Size &size, int scale)
|
|||
int64 imin, imax;
|
||||
if (series[j].sequential) {
|
||||
imin = imax = Null;
|
||||
for (int64 i = 1; i < series[j].PointsData()->GetCount() - 1; ++i) {
|
||||
for (int64 i = 0/*1*/; i < series[j].PointsData()->GetCount()/* - 1*/; ++i) {
|
||||
double xx = series[j].PointsData()->x(i);
|
||||
if (IsNull(xx))
|
||||
continue;
|
||||
if (IsNull(imin)) {
|
||||
if (xx >= xMin)
|
||||
imin = i - 1;
|
||||
imin = i;// - 1;
|
||||
} else if (IsNull(imax)) {
|
||||
if (xx >= xMin + xRange)
|
||||
imax = i + 1;
|
||||
imax = i;// + 1;
|
||||
}
|
||||
}
|
||||
if (IsNull(imin))
|
||||
|
|
@ -829,21 +842,23 @@ void ScatterDraw::Plot(T& w, const Size &size, int scale)
|
|||
imax = series[j].PointsData()->GetCount() - 1;
|
||||
} else {
|
||||
imin = 0;
|
||||
imax = series[j].PointsData()->GetCount();
|
||||
imax = series[j].PointsData()->GetCount() - 1;
|
||||
}
|
||||
double dxpix;
|
||||
if (fastViewX)
|
||||
dxpix = (series[j].PointsData()->x(imax) - series[j].PointsData()->x(imin))/plotW;
|
||||
int npix = 1;
|
||||
for (int64 i = imin; i < imax; ) {
|
||||
for (int64 i = imin; i <= imax; ) {
|
||||
double xx, yy;
|
||||
if (fastViewX) {
|
||||
yy = series[j].PointsData()->y(i);
|
||||
if (IsNull(yy))
|
||||
if (IsNull(yy)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
int64 ii;
|
||||
double maxv = dxpix*npix;
|
||||
for (ii = 1; series[j].PointsData()->x(i + ii) < maxv && i + ii < imax; ++ii) {
|
||||
for (ii = 1; i + ii < imax && series[j].PointsData()->x(i + ii) < maxv; ++ii) {
|
||||
double dd = series[j].PointsData()->y(i + ii);
|
||||
if (IsNull(dd))
|
||||
continue;
|
||||
|
|
@ -851,16 +866,20 @@ void ScatterDraw::Plot(T& w, const Size &size, int scale)
|
|||
}
|
||||
yy /= double(ii);
|
||||
xx = series[j].PointsData()->x(i);
|
||||
if (IsNull(xx))
|
||||
if (IsNull(xx)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
i += ii;
|
||||
npix++;
|
||||
} else {
|
||||
xx = series[j].PointsData()->x(i);
|
||||
yy = series[j].PointsData()->y(i);
|
||||
++i;
|
||||
if (IsNull(xx) || IsNull(yy))
|
||||
if (IsNull(xx) || IsNull(yy)) {
|
||||
//++i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
int ix = fround(plotW*(xx - xMin)/xRange);
|
||||
int iy;
|
||||
|
|
|
|||
|
|
@ -27,9 +27,15 @@ frFR("")
|
|||
|
||||
// Equation.h
|
||||
|
||||
T_("Average")
|
||||
caES("")
|
||||
esES("Promedio")
|
||||
euES("")
|
||||
frFR("")
|
||||
|
||||
T_("Linear")
|
||||
caES("Recta")
|
||||
esES("Recta")
|
||||
esES("Lineal")
|
||||
euES("Zuzen")
|
||||
frFR("Droite")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue