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:
koldo 2016-03-28 10:05:27 +00:00
parent 99a8409be4
commit 72659065f8
7 changed files with 414 additions and 42 deletions

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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);}

View file

@ -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;

View file

@ -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;

View file

@ -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")