From 72659065f80f1cde32251085a8769c8bbba04e90 Mon Sep 17 00:00:00 2001 From: koldo Date: Mon, 28 Mar 2016 10:05:27 +0000 Subject: [PATCH] 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 --- uppsrc/ScatterDraw/DataSource.cpp | 253 ++++++++++++++++++++++++++++- uppsrc/ScatterDraw/DataSource.h | 90 +++++++++- uppsrc/ScatterDraw/Equation.cpp | 11 +- uppsrc/ScatterDraw/Equation.h | 14 ++ uppsrc/ScatterDraw/ScatterDraw.cpp | 27 ++- uppsrc/ScatterDraw/ScatterDraw.h | 53 ++++-- uppsrc/ScatterDraw/ScatterDraw.t | 8 +- 7 files changed, 414 insertions(+), 42 deletions(-) diff --git a/uppsrc/ScatterDraw/DataSource.cpp b/uppsrc/ScatterDraw/DataSource.cpp index d76ab3b8c..251e052b5 100644 --- a/uppsrc/ScatterDraw/DataSource.cpp +++ b/uppsrc/ScatterDraw/DataSource.cpp @@ -1,27 +1,35 @@ +#include +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 DataSource::Envelope(Getdatafun getdataY, Getdatafun getdataX, double width, bool (*fun)(double a, double b)) { + Vector 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 DataSource::UpperEnvelope(Getdatafun getdataY, Getdatafun getdataX, double width) {return Envelope(getdataY, getdataX, width, GreaterThan);} +Vector DataSource::LowerEnvelope(Getdatafun getdataY, Getdatafun getdataX, double width) {return Envelope(getdataY, getdataX, width, LowerThan);} + +Vector DataSource::MovingAverage(Getdatafun getdataY, Getdatafun getdataX, double width) { + Vector 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 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 res; + if (num < 3) + return res; + timebuf.resize(num); + + VectorXcd freqbuf; + try { + Eigen::FFT 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& xdata, Vector& ydata) +{ + if(!IsInputSane(xdata, ydata)) + return false; + + int n = xdata.GetCount() - 1; + + Vector h; + for(int i = 0; i < n; ++i) + h << (xdata[i+1] - xdata[i]); + + Vector 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 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 c; + c.SetCount(n+1); + c[n] = 0; + + Vector 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& xdata, Vector& 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 \ No newline at end of file diff --git a/uppsrc/ScatterDraw/DataSource.h b/uppsrc/ScatterDraw/DataSource.h index 865db3f70..038081c96 100644 --- a/uppsrc/ScatterDraw/DataSource.h +++ b/uppsrc/ScatterDraw/DataSource.h @@ -3,6 +3,20 @@ NAMESPACE_UPP +template +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 UpperEnvelopeY(double width) {return UpperEnvelope(&DataSource::y, &DataSource::x, width);} + virtual Vector LowerEnvelopeY(double width) {return LowerEnvelope(&DataSource::y, &DataSource::x, width);} + virtual Vector MovingAverageY(double width) {return MovingAverage(&DataSource::y, &DataSource::x, width);} + + Upp::Vector 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 UpperEnvelope(Getdatafun getdataY, Getdatafun getdataX, double width); + Vector LowerEnvelope(Getdatafun getdataY, Getdatafun getdataX, double width); + Vector MovingAverage(Getdatafun getdataY, Getdatafun getdataX, double width); double SinEstim_Amplitude(double avg = Null); bool SinEstim_FreqPhase(double &frequency, double &phase, double avg = Null); + Vector FFT(Getdatafun getdata, double tSample); protected: bool isParam, isExplicit; private: int key; + + Vector 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& xdata, Vector& ydata); + double GetY(double x); + +private: + struct Coeff{double a, b, c, d, x;}; + Vector coeff; + + bool IsInputSane(Vector& xdata, Vector& ydata); +}; + END_UPP_NAMESPACE #endif diff --git a/uppsrc/ScatterDraw/Equation.cpp b/uppsrc/ScatterDraw/Equation.cpp index e97e9b689..635e6b093 100644 --- a/uppsrc/ScatterDraw/Equation.cpp +++ b/uppsrc/ScatterDraw/Equation.cpp @@ -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; diff --git a/uppsrc/ScatterDraw/Equation.h b/uppsrc/ScatterDraw/Equation.h index 82f4426eb..e46db2e09 100644 --- a/uppsrc/ScatterDraw/Equation.h +++ b/uppsrc/ScatterDraw/Equation.h @@ -72,6 +72,20 @@ protected: static VectorMap& classMap() {static VectorMap 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);} diff --git a/uppsrc/ScatterDraw/ScatterDraw.cpp b/uppsrc/ScatterDraw/ScatterDraw.cpp index e082fc844..9922ca3a6 100644 --- a/uppsrc/ScatterDraw/ScatterDraw.cpp +++ b/uppsrc/ScatterDraw/ScatterDraw.cpp @@ -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; diff --git a/uppsrc/ScatterDraw/ScatterDraw.h b/uppsrc/ScatterDraw/ScatterDraw.h index c73984850..a1faa5af0 100644 --- a/uppsrc/ScatterDraw/ScatterDraw.h +++ b/uppsrc/ScatterDraw/ScatterDraw.h @@ -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 ScatterDraw &AddSeries(ArrayMap &data) {return _AddSeries(new ArrayMapXY(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 &xData, Vector &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; diff --git a/uppsrc/ScatterDraw/ScatterDraw.t b/uppsrc/ScatterDraw/ScatterDraw.t index e6b228586..902fc4a3a 100644 --- a/uppsrc/ScatterDraw/ScatterDraw.t +++ b/uppsrc/ScatterDraw/ScatterDraw.t @@ -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")