diff --git a/uppsrc/ScatterDraw/DataSource.h b/uppsrc/ScatterDraw/DataSource.h index dbf1fce33..cf49c37cb 100644 --- a/uppsrc/ScatterDraw/DataSource.h +++ b/uppsrc/ScatterDraw/DataSource.h @@ -1,234 +1,238 @@ -#ifndef _DataSource_DataSource_h_ -#define _DataSource_DataSource_h_ - -class DataSource { -public: - typedef double (DataSource::*Getdatafun)(int id); - - DataSource() : isParam(false) {} - virtual ~DataSource() {}; - virtual double z(int id){return Null;}; - virtual double y(int id){return Null;}; - virtual double x(int id){return Null;}; - virtual int GetCount() {return Null;}; - bool IsParam() {return isParam;}; - - virtual double MinX() {return Min(&DataSource::x);} - virtual double MinY() {return Min(&DataSource::y);} - virtual double MinZ() {return Min(&DataSource::z);} - - virtual double MaxX() {return Max(&DataSource::x);} - virtual double MaxY() {return Max(&DataSource::y);} - virtual double MaxZ() {return Max(&DataSource::z);} - - virtual double AvgX() {return Avg(&DataSource::x);} - virtual double AvgY() {return Avg(&DataSource::y);} - virtual double AvgZ() {return Avg(&DataSource::z);} - -protected: - bool isParam; - - virtual double Min(Getdatafun getdata); - virtual double Max(Getdatafun getdata); - virtual double Avg(Getdatafun getdata); -}; - -class CArray : public DataSource { -private: - double *xData, *yData, *zData; - int numData; - double x0, deltaX; - -public: - CArray(double *yData, int numData, double x0, double deltaX) : yData(yData), numData(numData), x0(x0), deltaX(deltaX) { xData = NULL; }; - CArray(double *xData, double *yData, int numData) : xData(xData), yData(yData), numData(numData) { zData = NULL; x0 = deltaX = 0; }; - CArray(double *xData, double *yData, double *zData, int numData) : xData(xData), yData(yData), zData(zData), numData(numData) { x0 = deltaX = 0; }; - virtual inline double z(int id) {ASSERT(zData); return zData[id];}; - virtual inline double y(int id) {return yData[id];}; - virtual inline double x(int id) {return xData ? xData[id] : id*deltaX + x0;}; - virtual inline int GetCount() {return numData;}; -}; - -template -class VectorY : public DataSource { -private: - Vector *yData; - -public: - VectorY(Vector &yData) : yData(&yData) {}; - virtual inline double y(int id) {return (*yData)[id];}; - virtual inline double x(int id) {return id;}; - virtual inline int GetCount() {return yData->GetCount();}; -}; - -template -class ArrayY : public DataSource { -private: - Upp::Array *yData; - -public: - ArrayY(Upp::Array &yData) : yData(&yData) {}; - virtual inline double y(int id) {return (*yData)[id];}; - virtual inline double x(int id) {return id;}; - virtual inline int GetCount() {return yData->GetCount();}; -}; - -class VectorDouble : public DataSource { -private: - const Vector *xData, *yData; - -public: - VectorDouble(const Vector &xData, Vector &yData) : xData(&xData), yData(&yData) {}; - virtual inline double y(int id) {return (*yData)[id];}; - virtual inline double x(int id) {return (*xData)[id];}; - virtual inline int GetCount() {return xData->GetCount();}; -}; - -class ArrayDouble : public DataSource { -private: - const Upp::Array *xData, *yData; - -public: - ArrayDouble(const Upp::Array &xData, Upp::Array &yData) : xData(&xData), yData(&yData) {}; - virtual inline double y(int id) {return (*yData)[id];}; - virtual inline double x(int id) {return (*xData)[id];}; - virtual inline int GetCount() {return xData->GetCount();}; -}; - -class VectorPointf : public DataSource { -private: - const Vector *data; - -public: - VectorPointf(const Vector &data) : data(&data) {}; - VectorPointf(Vector *data) : data(data) {}; - virtual inline double y(int id) {return (*data)[id].y;}; - virtual inline double x(int id) {return (*data)[id].x;}; - virtual inline int GetCount() {return data->GetCount();}; -}; - -class ArrayPointf : public DataSource { -private: - Upp::Array *data; - -public: - ArrayPointf(Upp::Array &data) : data(&data) {}; - virtual inline double y(int id) {return (*data)[id].y;}; - virtual inline double x(int id) {return (*data)[id].x;}; - virtual inline int GetCount() {return data->GetCount();}; -}; - -template -class VectorMapXY : public DataSource { -private: - VectorMap *data; - -public: - VectorMapXY(VectorMap &data) : data(&data) {}; - virtual inline double y(int id) {return (*data)[id];}; - virtual inline double x(int id) {return (*data).GetKey(id);}; - virtual inline int GetCount() {return data->GetCount();}; -}; - -template -class ArrayMapXY : public DataSource { -private: - ArrayMap *data; - -public: - ArrayMapXY(ArrayMap &data) : data(&data) {}; - virtual inline double y(int id) {return (*data)[id];}; - virtual inline double x(int id) {return (*data).GetKey(id);}; - virtual inline int GetCount() {return data->GetCount();}; -}; - -class FuncSource : public DataSource { -private: - double (*function)(double); - -public: - FuncSource(double (*function)(double)) : function(function) {}; - virtual inline double y(int t) {return function(t);}; - virtual inline double x(int t) {return t;}; - virtual inline int GetCount() {return Null;}; -}; - -class FuncSourcePara : public DataSource { -private: - Pointf (*function)(double); - Pointf lastPointf; - double lastT; - int numPoints; - double minT, maxT; - -public: - FuncSourcePara(Pointf (*function)(double), int np, double from, double to) : - function(function), numPoints(np), minT(from), maxT(to) { - lastT = Null; - isParam = true; - } - virtual inline double y(int t) { - if (IsNull(lastT) || t != lastT) { - lastPointf = function(minT + t*(maxT-minT)/numPoints); - lastT = t; - } - return lastPointf.y; - } - virtual inline double x(int t) { - if (IsNull(lastT) || t != lastT) { - lastPointf = function(minT + t*(maxT-minT)/numPoints); - lastT = t; - } - return lastPointf.x; - } - virtual inline int GetCount() {return numPoints;}; -}; - -typedef Callback2 PlotFunc; -typedef Callback2 PlotParamFunc; - -class PlotFuncSource : public DataSource { -private: - PlotFunc function; - -public: - PlotFuncSource() {}; - PlotFuncSource(PlotFunc &function) : function(function) {}; - virtual inline double y(int t) {double y; function(y, t); return y;}; - virtual inline double x(int t) {return t;}; - virtual inline int GetCount() {return Null;}; -}; - -class PlotParamFuncSource : public DataSource { -private: - PlotParamFunc function; - Pointf lastPointf; - double lastT; - int numPoints; - double minT, maxT; - -public: - PlotParamFuncSource(PlotParamFunc function, int np, double from, double to) : - function(function), numPoints(np), minT(from), maxT(to) { - lastT = Null; - isParam = true; - } - inline double y(int t) { - if (IsNull(lastT) || t != lastT) { - function(lastPointf, minT + t*(maxT-minT)/numPoints); - lastT = t; - } - return lastPointf.y; - } - - inline double x(int t) { - if (IsNull(lastT) || t != lastT) { - function(lastPointf, minT + t*(maxT-minT)/numPoints); - lastT = t; - } - return lastPointf.x; - } - virtual inline int GetCount() {return numPoints;}; -}; - -#endif +#ifndef _ScatterDraw_DataSource_h_ +#define _ScatterDraw_DataSource_h_ + +NAMESPACE_UPP + +class DataSource { +public: + typedef double (DataSource::*Getdatafun)(int id); + + DataSource() : isParam(false) {} + virtual ~DataSource() {}; + virtual double z(int id){return Null;}; + virtual double y(int id){return Null;}; + virtual double x(int id){return Null;}; + virtual int GetCount() {return Null;}; + bool IsParam() {return isParam;}; + + virtual double MinX() {return Min(&DataSource::x);} + virtual double MinY() {return Min(&DataSource::y);} + virtual double MinZ() {return Min(&DataSource::z);} + + virtual double MaxX() {return Max(&DataSource::x);} + virtual double MaxY() {return Max(&DataSource::y);} + virtual double MaxZ() {return Max(&DataSource::z);} + + virtual double AvgX() {return Avg(&DataSource::x);} + virtual double AvgY() {return Avg(&DataSource::y);} + virtual double AvgZ() {return Avg(&DataSource::z);} + +protected: + bool isParam; + + virtual double Min(Getdatafun getdata); + virtual double Max(Getdatafun getdata); + virtual double Avg(Getdatafun getdata); +}; + +class CArray : public DataSource { +private: + double *xData, *yData, *zData; + int numData; + double x0, deltaX; + +public: + CArray(double *yData, int numData, double x0, double deltaX) : yData(yData), numData(numData), x0(x0), deltaX(deltaX) { xData = NULL; }; + CArray(double *xData, double *yData, int numData) : xData(xData), yData(yData), numData(numData) { zData = NULL; x0 = deltaX = 0; }; + CArray(double *xData, double *yData, double *zData, int numData) : xData(xData), yData(yData), zData(zData), numData(numData) { x0 = deltaX = 0; }; + virtual inline double z(int id) {ASSERT(zData); return zData[id];}; + virtual inline double y(int id) {return yData[id];}; + virtual inline double x(int id) {return xData ? xData[id] : id*deltaX + x0;}; + virtual inline int GetCount() {return numData;}; +}; + +template +class VectorY : public DataSource { +private: + Vector *yData; + +public: + VectorY(Vector &yData) : yData(&yData) {}; + virtual inline double y(int id) {return (*yData)[id];}; + virtual inline double x(int id) {return id;}; + virtual inline int GetCount() {return yData->GetCount();}; +}; + +template +class ArrayY : public DataSource { +private: + Upp::Array *yData; + +public: + ArrayY(Upp::Array &yData) : yData(&yData) {}; + virtual inline double y(int id) {return (*yData)[id];}; + virtual inline double x(int id) {return id;}; + virtual inline int GetCount() {return yData->GetCount();}; +}; + +class VectorDouble : public DataSource { +private: + const Vector *xData, *yData; + +public: + VectorDouble(const Vector &xData, Vector &yData) : xData(&xData), yData(&yData) {}; + virtual inline double y(int id) {return (*yData)[id];}; + virtual inline double x(int id) {return (*xData)[id];}; + virtual inline int GetCount() {return xData->GetCount();}; +}; + +class ArrayDouble : public DataSource { +private: + const Upp::Array *xData, *yData; + +public: + ArrayDouble(const Upp::Array &xData, Upp::Array &yData) : xData(&xData), yData(&yData) {}; + virtual inline double y(int id) {return (*yData)[id];}; + virtual inline double x(int id) {return (*xData)[id];}; + virtual inline int GetCount() {return xData->GetCount();}; +}; + +class VectorPointf : public DataSource { +private: + const Vector *data; + +public: + VectorPointf(const Vector &data) : data(&data) {}; + VectorPointf(Vector *data) : data(data) {}; + virtual inline double y(int id) {return (*data)[id].y;}; + virtual inline double x(int id) {return (*data)[id].x;}; + virtual inline int GetCount() {return data->GetCount();}; +}; + +class ArrayPointf : public DataSource { +private: + Upp::Array *data; + +public: + ArrayPointf(Upp::Array &data) : data(&data) {}; + virtual inline double y(int id) {return (*data)[id].y;}; + virtual inline double x(int id) {return (*data)[id].x;}; + virtual inline int GetCount() {return data->GetCount();}; +}; + +template +class VectorMapXY : public DataSource { +private: + VectorMap *data; + +public: + VectorMapXY(VectorMap &data) : data(&data) {}; + virtual inline double y(int id) {return (*data)[id];}; + virtual inline double x(int id) {return (*data).GetKey(id);}; + virtual inline int GetCount() {return data->GetCount();}; +}; + +template +class ArrayMapXY : public DataSource { +private: + ArrayMap *data; + +public: + ArrayMapXY(ArrayMap &data) : data(&data) {}; + virtual inline double y(int id) {return (*data)[id];}; + virtual inline double x(int id) {return (*data).GetKey(id);}; + virtual inline int GetCount() {return data->GetCount();}; +}; + +class FuncSource : public DataSource { +private: + double (*function)(double); + +public: + FuncSource(double (*function)(double)) : function(function) {}; + virtual inline double y(int t) {return function(t);}; + virtual inline double x(int t) {return t;}; + virtual inline int GetCount() {return Null;}; +}; + +class FuncSourcePara : public DataSource { +private: + Pointf (*function)(double); + Pointf lastPointf; + double lastT; + int numPoints; + double minT, maxT; + +public: + FuncSourcePara(Pointf (*function)(double), int np, double from, double to) : + function(function), numPoints(np), minT(from), maxT(to) { + lastT = Null; + isParam = true; + } + virtual inline double y(int t) { + if (IsNull(lastT) || t != lastT) { + lastPointf = function(minT + t*(maxT-minT)/numPoints); + lastT = t; + } + return lastPointf.y; + } + virtual inline double x(int t) { + if (IsNull(lastT) || t != lastT) { + lastPointf = function(minT + t*(maxT-minT)/numPoints); + lastT = t; + } + return lastPointf.x; + } + virtual inline int GetCount() {return numPoints;}; +}; + +typedef Callback2 PlotFunc; +typedef Callback2 PlotParamFunc; + +class PlotFuncSource : public DataSource { +private: + PlotFunc function; + +public: + PlotFuncSource() {}; + PlotFuncSource(PlotFunc &function) : function(function) {}; + virtual inline double y(int t) {double y; function(y, t); return y;}; + virtual inline double x(int t) {return t;}; + virtual inline int GetCount() {return Null;}; +}; + +class PlotParamFuncSource : public DataSource { +private: + PlotParamFunc function; + Pointf lastPointf; + double lastT; + int numPoints; + double minT, maxT; + +public: + PlotParamFuncSource(PlotParamFunc function, int np, double from, double to) : + function(function), numPoints(np), minT(from), maxT(to) { + lastT = Null; + isParam = true; + } + inline double y(int t) { + if (IsNull(lastT) || t != lastT) { + function(lastPointf, minT + t*(maxT-minT)/numPoints); + lastT = t; + } + return lastPointf.y; + } + + inline double x(int t) { + if (IsNull(lastT) || t != lastT) { + function(lastPointf, minT + t*(maxT-minT)/numPoints); + lastT = t; + } + return lastPointf.x; + } + virtual inline int GetCount() {return numPoints;}; +}; + +END_UPP_NAMESPACE + +#endif diff --git a/uppsrc/ScatterDraw/ScatterDraw.h b/uppsrc/ScatterDraw/ScatterDraw.h index 127f41159..94e98c282 100644 --- a/uppsrc/ScatterDraw/ScatterDraw.h +++ b/uppsrc/ScatterDraw/ScatterDraw.h @@ -1,648 +1,646 @@ -#ifndef _ScatterDraw_ScatterDraw_h -#define _ScatterDraw_ScatterDraw_h - -#include -#include - -#include - -NAMESPACE_UPP - -#include "DataSource.h" -#include "DrawingFunctions.h" -#include "SeriesPlot.h" -#include "MarkPlot.h" - -Color GetOpaqueColor(const Color &color, const Color &background, const double opacity); - -class ScatterDraw { -public: - typedef ScatterDraw CLASSNAME; - ScatterDraw(); - - enum Formats { - EXP, - MON, - DY, - CUSTOM - }; - enum { - MD_DRAW = -1, - MD_ANTIALIASED = MODE_ANTIALIASED, - MD_NOAA = MODE_NOAA, - MD_SUBPIXEL = MODE_SUBPIXEL - }; - - #define LINE_DOTTED "4 10" - #define LINE_DOTTED_SEP "4 20" - #define LINE_DASHED "12 12" - #define LINE_DASH_DOT "20 10 5 10" - #define LINE_SOLID "" - -protected: - class ScatterBasicSeries { - public: - ScatterBasicSeries(); - void Init(int id); - - bool primaryY; - bool sequential; - - One seriesPlot; - double thickness; - Color color; - String dash; - - One markPlot; - double markWidth; - Color markColor; - - Color fillColor; - - String legend; - - double opacity; - - int id; - - bool trendLine; - //double trend - }; - - class ScatterSeries : public Moveable, public ScatterBasicSeries { - public: - ScatterSeries() {pD = 0;} - void SetDataSource(DataSource *pointsData, bool ownsData = true) {pD = pointsData; owns = ownsData;} - inline DataSource *PointsData() {return pD;} - ~ScatterSeries() {if(pD && owns) delete pD;} - private: - DataSource *pD; - bool owns; - }; - - static Color GetNewColor(int id); - static String GetNewDash(int id); - static MarkPlot *GetNewMarkPlot(int id); - -public: - Callback3 cbModifFormatX, cbModifFormatDeltaX; - Callback3 cbModifFormatY, cbModifFormatDeltaY; - Callback3 cbModifFormatY2, cbModifFormatDeltaY2; - - Callback WhenZoomScroll; - Callback WhenSetRange; - Callback WhenSetXYMin; - - ScatterDraw& SetSize(Size sz) {size = sz; return *this;}; - virtual Size GetSize() const {return size;}; - - ScatterDraw& SetColor(const Color& _color); - ScatterDraw& SetTitle(const String& _title); - ScatterDraw& SetTitleFont(const Font& fontTitle); - ScatterDraw& SetTitleColor(const Color& colorTitle); - - void SetLabels(const String& _xLabel, const String& _yLabel, const String& _yLabel2 = ""); - ScatterDraw& SetLabelX(const String& _xLabel); - ScatterDraw& SetLabelY(const String& _yLabel); - ScatterDraw& SetLabelY2(const String& _yLabel); - ScatterDraw& SetLabelsFont(const Font& fontLabels); - Font GetLabelsFont() {return labelsFont;}; - ScatterDraw& SetLabelsColor(const Color& colorLabels); - - ScatterDraw& SetPlotAreaMargin(const int hLeft, const int hRight, const int vTop, const int vBottom); - ScatterDraw& SetPlotAreaLeftMargin(const int margin); - ScatterDraw& SetPlotAreaRightMargin(const int margin); - ScatterDraw& SetPlotAreaTopMargin(const int margin); - ScatterDraw& SetPlotAreaBottomMargin(const int margin); - - ScatterDraw& SetPlotAreaColor(const Color& p_a_color); - - ScatterDraw& SetAxisColor(const Color& axis_color); - ScatterDraw& SetAxisWidth(const int& axis_width); - - ScatterDraw& SetGridColor(const Color& grid_color); - ScatterDraw& SetGridWidth(const int& grid_width); - ScatterDraw& ShowVGrid(const bool& show); - ScatterDraw& ShowHGrid(const bool& show); - - ScatterDraw& ShowLegend(const bool& show=true); - ScatterDraw& SetLegendWeight(const int& weight); - - ScatterDraw& SetMode(int _mode = MD_ANTIALIASED) {mode = _mode; Refresh(); return *this;}; - int GetMode() {return mode;}; - - void FitToData(bool Y = false); - void Zoom(double scale, bool hor = true, bool ver = true); - void Scroll(double factorX, double factorY); - - enum ZoomStyle {TO_CENTER, FROM_BASE}; - ScatterDraw &SetZoomStyleX(ZoomStyle style = TO_CENTER) {zoomStyleX = style; return *this;} - ScatterDraw &SetZoomStyleY(ZoomStyle style = TO_CENTER) {zoomStyleY = style; return *this;} - - ScatterDraw& SetRange(double rx, double ry, double ry2 = 100); - double GetXRange()const {return xRange;} - double GetYRange()const {return yRange;} - double GetY2Range()const {return yRange2;} - ScatterDraw &SetMajorUnits(double ux, double uy); - ScatterDraw &SetMajorUnitsNum(int nx, int ny); - ScatterDraw &SetMaxMajorUnitsX(int maxX, int maxY) {maxMajorUnitsX = maxX; maxMajorUnitsY = maxY; return *this;} - double GetMajorUnitsX() {return xMajorUnit;} - double GetMajorUnitsY() {return yMajorUnit;} - ScatterDraw& SetMinUnits(double ux, double uy); - double GetXMinUnit () const {return xMinUnit;} - double GetYMinUnit () const {return yMinUnit;} - - ScatterDraw& SetXYMin(double xmin,double ymin,double ymin2 = 0); - double GetXMin () const {return xMin;} - double GetYMin () const {return yMin;} - double GetYMin2 () const {return yMin2;} - - ScatterDraw &Graduation_FormatX(Formats fi); - ScatterDraw &Graduation_FormatY(Formats fi); - ScatterDraw &Graduation_FormatY2(Formats fi); - - ScatterDraw &AddSeries(double *yData, int numData, double x0 = 0, double deltaX = 1); - ScatterDraw &AddSeries(double *xData, double *yData, int numData); - ScatterDraw &AddSeries(Vector &xData, Vector &yData); - ScatterDraw &AddSeries(Upp::Array &xData, Upp::Array &yData); - ScatterDraw &AddSeries(Vector &points); - ScatterDraw &AddSeries(Upp::Array &points); - ScatterDraw &AddSeries(double (*function)(double)); - ScatterDraw &AddSeries(Pointf (*function)(double), int np, double from = 0, double to = 1); - ScatterDraw &AddSeries(PlotFunc &function); - ScatterDraw &AddSeries(PlotParamFunc function, int np, double from = 0, double to = 1); - ScatterDraw &_AddSeries(DataSource *data); - ScatterDraw &AddSeries(DataSource &data); - - template - ScatterDraw &AddSeries() {return _AddSeries(new C());} - template - ScatterDraw &AddSeries(T1 &arg1) - {return _AddSeries(new C(arg1));} - template - ScatterDraw &AddSeries(T1 &arg1, T2 &arg2) - {return _AddSeries(new C(arg1, arg2));} - template - ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3) - {return _AddSeries(new C(arg1, arg2, arg3));} - template - ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4) - {return _AddSeries(new C(arg1, arg2, arg3, arg4));} - template - ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5) - {return _AddSeries(new C(arg1, arg2, arg3, arg4, arg5));} - template - ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5, T6 &arg6) - {return _AddSeries(new C(arg1, arg2, arg3, arg4, arg5, arg6));} - - template - ScatterDraw &AddSeries(Vector &yData) {return _AddSeries(new VectorY(yData));} - template - ScatterDraw &AddSeries(Upp::Array &yData) {return _AddSeries(new ArrayY(yData));} - template - ScatterDraw &AddSeries(VectorMap &data) {return _AddSeries(new VectorMapXY(data));} - template - ScatterDraw &AddSeries(ArrayMap &data) {return _AddSeries(new ArrayMapXY(data));} - - void InsertSeries(int id, double *yData, int numData, double x0 = 0, double deltaX = 1); - void InsertSeries(int id, double *xData, double *yData, int numData); - void InsertSeries(int id, Vector &xData, Vector &yData); - void InsertSeries(int id, Upp::Array &xData, Upp::Array &yData); - void InsertSeries(int id, Vector &points); - void InsertSeries(int id, Upp::Array &points); - void InsertSeries(int id, double (*function)(double)); - void InsertSeries(int id, Pointf (*function)(double), int np, double from = 0, double to = 1); - void InsertSeries(int id, PlotFunc &function); - void InsertSeries(int id, PlotParamFunc function, int np, double from = 0, double to = 1); - void _InsertSeries(int id, DataSource *data); - - template - void InsertSeries(int id) {_InsertSeries(id, new C());} - template - void InsertSeries(int id, T1 &arg1) - {_InsertSeries(id, new C(arg1));} - template - void InsertSeries(int id, T1 &arg1, T2 &arg2) - {_InsertSeries(id, new C(arg1, arg2));} - template - void InsertSeries(int id, T1 &arg1, T2 &arg2, T3 &arg3) - {_InsertSeries(id, new C(arg1, arg2, arg3));} - template - void InsertSeries(int id, T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4) - {_InsertSeries(id, new C(arg1, arg2, arg3, arg4));} - template - void InsertSeries(int id, T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5) - {_InsertSeries(id, new C(arg1, arg2, arg3, arg4, arg5));} - template - void InsertSeries(int id, T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5, T6 &arg6) - {_InsertSeries(id, new C(arg1, arg2, arg3, arg4, arg5, arg6));} - - template - void InsertSeries(int id, Vector &yData) {_InsertSeries(id, new VectorY(yData));} - template - void InsertSeries(int id, Upp::Array &yData) {_InsertSeries(id, new ArrayY(yData));} - template - void InsertSeries(int id, VectorMap &data){_InsertSeries(id, new VectorMapXY(data));} - template - void InsertSeries(int id, ArrayMap &data) {_InsertSeries(id, new ArrayMapXY(data));} - - ScatterDraw &PlotStyle() {return PlotStyle(0);}; - template - ScatterDraw &PlotStyle() {return PlotStyle(new C());}; - template - ScatterDraw &PlotStyle(T1 &arg1) {return PlotStyle(new C(arg1));}; - template - ScatterDraw &PlotStyle(T1 &arg1, T2 &arg2) {return PlotStyle(new C(arg1, arg2));}; - template - ScatterDraw &PlotStyle(T1 &arg1, T2 &arg2, T3 &arg3) {return PlotStyle(new C(arg1, arg2, arg3));}; - ScatterDraw &PlotStyle(SeriesPlot *data); - - ScatterDraw &NoPlot() {return PlotStyle();}; - - ScatterDraw &MarkStyle() {return MarkStyle(0);}; - template - ScatterDraw &MarkStyle() {return MarkStyle(new C());}; - template - ScatterDraw &MarkStyle(T1 &arg1) {return MarkStyle(new C(arg1));}; - template - ScatterDraw &MarkStyle(T1 &arg1, T2 &arg2) {return MarkStyle(new C(arg1, arg2));}; - template - ScatterDraw &MarkStyle(T1 &arg1, T2 &arg2, T3 &arg3) {return MarkStyle(new C(arg1, arg2, arg3));}; - ScatterDraw &MarkStyle(MarkPlot *data); - - ScatterDraw &NoMark() {return MarkStyle();}; - - ScatterDraw &Stroke(double thickness = 3, Color color = Null); - ScatterDraw &Dash(const char *dash); - ScatterDraw &Fill(Color color = Null); - ScatterDraw &MarkColor(Color color = Null); - ScatterDraw &MarkWidth(const double& markWidth = 8); - ScatterDraw &Hide() {series[series.GetCount() - 1].opacity = 0; return *this;} - - ScatterDraw &Opacity(double opacity = 1) {series[series.GetCount() - 1].opacity = opacity; return *this;} - ScatterDraw &Legend(const String legend); - - inline bool IsValid(const int& j) const {return (j >= 0 && j < series.GetCount());} - - ScatterDraw& SetDrawXReticle(bool set = true); - ScatterDraw& SetDrawYReticle(bool set = true); - ScatterDraw& SetDrawY2Reticle(bool set = true); - - void SetDataColor(const int& j,const Color& pcolor); - Color GetDataColor (const int& j) const; - void SetDataThickness(const int& j, const double& thick); - double GetDataThickness(const int& j) const; - void SetFillColor(const int& j, const Color& color); - Color GetFillColor(const int& j) const; - - ScatterDraw &SetMarkWidth(const int& j, const double& width); - double GetMarkWidth(const int& j) const; - void SetMarkColor(const int& j, const Color& pcolor); - Color GetMarkColor (const int& j) const; - void NoMark(const int& j); - bool IsShowMark(const int& j) const throw (Exc); - - void SetDataPrimaryY(const int& j, const bool& primary=true); - ScatterDraw &SetDataPrimaryY(const bool& primary); - bool IsDataPrimaryY(const int& j) const throw (Exc); - - void SetSequentialX(const int& j, const bool& sequential = true); - ScatterDraw &SetSequentialX(const bool& sequential = true); - ScatterDraw &SetSequentialXAll(const bool& sequential = true); - - void Show(const int& j, const bool& show = true); - bool IsVisible(const int& j); - ScatterDraw &ShowAll(const bool& show = true); - - void RemoveSeries(const int& j); - void RemoveAllSeries(); - - ScatterDraw& Id(int id); - ScatterDraw& Id(const int& j, int id); - int GetId(const int& j); - - Drawing GetDrawing(); - Image GetImage(const int& scale = 1); - - #ifdef PLATFORM_WIN32 - void SaveAsMetafile(const char* file) const; - #endif - - ScatterDraw& LogX(const bool& logx=true) {logX=logx; return *this;} - ScatterDraw& LogY(const bool& logy=true) {logY=logy; return *this;} - ScatterDraw& LogY2(const bool& logy=true) {logY2=logy; return *this;} - - ScatterDraw& SetMinZoom(double x, double y = -1) {minXZoom = x; minYZoom = y; return *this;}; - ScatterDraw& SetMaxZoom(double x, double y = -1) {maxXZoom = x; maxYZoom = y; return *this;}; - - ScatterDraw& SetFastViewX(bool set = true) {fastViewX = set; return *this;}; - - Font& GetTitleFont() {return titleFont;}; - - double GetXByPoint(const int x); - double GetYByPoint(const int y); - double GetY2ByPoint(const int y); - double GetXPointByValue(const double x); - double GetYPointByValue(const double y); - - int GetCount() {return series.GetCount();} - bool IsEmpty() {return series.IsEmpty();} - - virtual void Refresh() {}; - -protected: - int mode; - Color graphColor; - String title; - Font titleFont; - Color titleColor; - - String xLabel, yLabel, yLabel2; - Font labelsFont; - Color labelsColor; - - int hPlotLeft, hPlotRight, vPlotTop, vPlotBottom; - Color plotAreaColor; - - bool fastViewX, sequentialXAll; - - Color axisColor; - int axisWidth; - - double xRange, yRange, yRange2; - double xMin, yMin, yMin2; - double xMajorUnit, yMajorUnit, yMajorUnit2; - double xMinUnit, yMinUnit, yMinUnit2; - double minXZoom, maxXZoom, minYZoom, maxYZoom; - bool drawXReticle, drawYReticle, drawY2Reticle; - - int maxMajorUnitsX, maxMajorUnitsY; - - Color gridColor; - int gridWidth; - bool drawVGrid, drawHGrid; - - int butDownX, butDownY; - bool isScrolling, isLabelPopUp; - ZoomStyle zoomStyleX, zoomStyleY; - - Vector series; - - bool showLegend; - int legendWeight; - - void DrawLegend(Draw& w,const int& scale) const; - - void Scrolling(bool down, Point &pt, bool isOut = false); - - void ExpFormat(String& s, int i, double d) {s = FormatDoubleExp(d,1);} - void MonFormat(String& s, int i, double d) {s = Format("%Mon",int(d));} - void DyFormat(String& s, int i, double d) {s = Format("%Dy",int(d));} - - static String VariableFormat(double range, double d) - { - if (fabs(d) <= 1e-15) - d = 0; - if (0.001<=range && range<0.01) return FormatDouble(d,5); - else if (0.01<=range && range<0.1) return FormatDouble(d,4); - else if (0.1<=range && range<1) return FormatDouble(d,3); - else if (1<=range && range<10) return FormatDouble(d,2); - else if (10<=range && range<100) return FormatDouble(d,1); - else if (100<=range && range<100000) return FormatDouble(d,0); - else return FormatDoubleExp(d,2); - - } - String VariableFormatX(const double& d) const {return VariableFormat(xRange, d);} - String VariableFormatY(const double& d) const {return VariableFormat(yRange, d);} - String VariableFormatY2(const double& d) const {return VariableFormat(yRange2, d);} - - template - void SetDrawing(T& w, const int& scale); - template - void Plot(T& w, const int& scale,const int& l,const int& h); - - void AdjustMinUnitX(); - void AdjustMinUnitY(); - void AdjustMinUnitY2(); - - bool logX, logY, logY2; - -private: - Size size; - static void ParseTextMultiline(const String &text, Font fnt, - Upp::Array &texts, Upp::Array &sizes); -}; - -template -void ScatterDraw::SetDrawing(T& w, const int& scale) -{ - if (GetSize().cx == 0 || GetSize().cy == 0) - return; - - w.DrawRect(scale*GetSize(), graphColor); - - if (typeid(T) == typeid(BufferPainter)) { - Painter &p = (Painter &)w; - p.Translate(0, 0.5); - } - - Size sz(0, 0); - - int titleHeight = !title.IsEmpty() ? scale*titleFont.GetHeight() : 0; - - if(titleHeight > 0) { - Font fontTitle6; - fontTitle6 = titleFont; - fontTitle6.Height(titleHeight); - fontTitle6.Width(scale*titleFont.GetWidth()); - sz = GetTextSize(title, fontTitle6); - DrawText(w, (scale*GetSize().cx - sz.cx)/2., scale*2., 0, title, fontTitle6, titleColor); - } - - w.Offset(Point(scale*hPlotLeft, scale*vPlotTop + titleHeight)); - if(showLegend) - DrawLegend(w, scale); - - int plotW = scale*(GetSize().cx - (hPlotLeft + hPlotRight)); - int plotH = scale*(GetSize().cy - (vPlotTop + vPlotBottom)) - titleHeight; - - Font fontLabel; - fontLabel = labelsFont; - fontLabel.Height(scale*labelsFont.GetHeight()); - - Size lx = GetTextSize(xLabel, fontLabel); - Size ly = GetTextSize(yLabel, fontLabel); - Size ly2 = GetTextSize(yLabel2, fontLabel); - DrawText(w, (plotW - lx.cx)/2., scale*GetSize().cy - lx.cy - 70*scale, 0, xLabel, fontLabel, labelsColor); - DrawText(w, scale*2. - scale*hPlotLeft, (plotH + ly.cx)/2., 900, yLabel, fontLabel, labelsColor); - DrawText(w, scale*GetSize().cx - ly2.cy - 42*scale, (plotH + ly2.cx)/2., 900, yLabel2, fontLabel, labelsColor); - - if (typeid(T) == typeid(BufferPainter)) { - Painter &p = (Painter &)w; - p.Translate(0.5, 0); - } - - if (drawXReticle) - for(int i = 0; xMinUnit + i*xMajorUnit <= xRange; i++){ - w.DrawLine(fround(plotW*xMinUnit/xRange + i*plotW/(xRange/xMajorUnit)), plotH, - fround(plotW*xMinUnit/xRange + i*plotW/(xRange/xMajorUnit)), plotH + scale*4, - fround(gridWidth*scale), axisColor); - Font standard6; - standard6.Height(scale*StdFont().GetHeight()); - double gridX = xMinUnit + i*xMajorUnit + xMin; - String gridLabelX; - if (cbModifFormatX) - cbModifFormatX(gridLabelX, i, gridX); - else - gridLabelX = VariableFormatX(gridX); - - Array texts; - Array sizes; - ParseTextMultiline(gridLabelX, StdFont(), texts, sizes); - for (int ii = 0; ii < texts.GetCount(); ++ii) { - int cy = ii == 0 ? 0 : sizes[ii - 1].cy; - DrawText(w, plotW*xMinUnit/xRange + i*plotW/(xRange/xMajorUnit) - scale*sizes[ii].cx/2., - plotH + scale*(4 + ii*cy), 0, texts[ii], standard6, axisColor); - } - } - - if (drawYReticle) - for(int i = 0; yMinUnit + i*yMajorUnit <= yRange; i++){ - w.DrawLine(-(scale*4), fround(-plotH*yMinUnit/yRange + plotH - i*plotH/(yRange/yMajorUnit)), - 0, fround(-plotH*yMinUnit/yRange + plotH - i*plotH/(yRange/yMajorUnit)), - fround(gridWidth*scale), axisColor); - double gridY = yMinUnit + i*yMajorUnit + yMin; - String gridLabelY; - if (cbModifFormatY) - cbModifFormatY(gridLabelY, i, gridY); - else - gridLabelY = VariableFormatY(gridY); - int dx=scale*GetTextSize(gridLabelY,StdFont()).cx; - Font Standard6; - Standard6.Height(scale*StdFont().GetHeight()); - DrawText(w, -dx - scale*6, fround(-plotH*yMinUnit/yRange + plotH - i*plotH/(yRange/yMajorUnit)) - scale*8, - 0, gridLabelY, Standard6, axisColor); - } - - if (drawY2Reticle) - for(int i = 0; yMinUnit + i*yMajorUnit <= yRange; i++){ - w.DrawLine(plotW + (scale*4), fround(-plotH*yMinUnit2/yRange2 + plotH - i*plotH/(yRange/yMajorUnit)), - plotW, fround(-plotH*yMinUnit2/yRange2 + plotH - i*plotH/(yRange/yMajorUnit)), - fround(gridWidth*scale), axisColor); - double gridY2 = yMinUnit2 + i*yMajorUnit2 + yMin2; - String gridLabelY2; - if (cbModifFormatY2) - cbModifFormatY2(gridLabelY2, i, gridY2); - else - gridLabelY2 = VariableFormatY2(gridY2); - Font standard6; - standard6.Height(scale*StdFont().GetHeight()); - DrawText(w, plotW + scale*10, fround(-plotH*yMinUnit2/yRange2 + plotH - i*plotH/(yRange/yMajorUnit)) - scale*8, 0, - gridLabelY2, standard6, axisColor); - } - - Plot(w, scale, plotW, plotH); - ClipEnd(w); -} - -template -void ScatterDraw::Plot(T& w, const int& scale, const int& plotW, const int& plotH) -{ - double d1 = xRange/xMajorUnit; - double d2 = yRange/yMajorUnit; - - w.DrawRect(1, 1, plotW - 2, plotH - 1, plotAreaColor); - - if (drawVGrid) - for(int i = 0; xMinUnit + i*xMajorUnit < xRange; i++) - DrawLineOpa(w, fround(plotW*xMinUnit/xRange + i*plotW/d1), 0, fround(plotW*xMinUnit/xRange + i*plotW/d1), plotH, - 1, 1, gridWidth, gridColor, "2 2"); - - if (drawHGrid) - for(int i = 0; yMinUnit + i*yMajorUnit < yRange; i++) - DrawLineOpa(w, 0, fround(-plotH*yMinUnit/yRange + plotH - i*plotH/d2), plotW, fround(-plotH*yMinUnit/yRange + plotH - i*plotH/d2), - 1, 1, gridWidth, gridColor, "2 2"); - - w.DrawLine(0, plotH, plotW, plotH, fround(gridWidth*scale), Black); - w.DrawLine(0, 0, plotW, 0, fround(gridWidth*scale), Black); - w.DrawLine(0, 0, 0, plotH, fround(gridWidth*scale), Black); - w.DrawLine(plotW, 0, plotW, plotH + 1, fround(gridWidth*scale), Black); - - Clip(w, 0, 0, plotW, plotH); - - if (!series.IsEmpty()) { - for (int j = 0; j < series.GetCount(); j++) { - if (series[j].opacity == 0 || (!series[j].seriesPlot && !series[j].markPlot)) - continue; - Vector p1; - int imin, imax; - if (series[j].sequential) { - imin = imax = Null; - for (int i = 1; i < series[j].PointsData()->GetCount() - 1; ++i) { - if (IsNull(imin)) { - if (series[j].PointsData()->x(i) >= xMin) - imin = i - 1; - } else if (IsNull(imax)) { - if (series[j].PointsData()->x(i) >= xMin + xRange) - imax = i + 1; - } - } - if (IsNull(imin)) - imin = 0; - if (IsNull(imax)) - imax = series[j].PointsData()->GetCount(); - } else if (series[j].PointsData()->IsParam()) { // It is a param function - imin = 0; - imax = series[j].PointsData()->GetCount(); - } else if (IsNull(series[j].PointsData()->GetCount())) { // It is a function - imin = fround(xMin) - 1; - imax = fround(xMin + xRange) + 1; - } else { - imin = 0; - imax = series[j].PointsData()->GetCount(); - } - int numV; - if (fastViewX) - numV = 1 + (imax - imin)/plotW; - else - numV = 1; - for (int i = imin; i < imax; i += numV) { - double xx, yy; - if (fastViewX && numV > 1) { - yy = 0; - int ii; - for (ii = 0; ii < numV && i + ii < imax; ++ii) - yy += series[j].PointsData()->y(i + ii); - yy /= double(ii); - xx = (series[j].PointsData()->x(i) + series[j].PointsData()->x(i + ii - 1))/2; - } else { - xx = series[j].PointsData()->x(i); - yy = series[j].PointsData()->y(i); - } - int ix, iy; - ix = fround(plotW*(xx - xMin)/xRange); - if (series[j].primaryY) - iy = fround(plotH*(yy - yMin)/yRange); - else - iy = fround(plotH*(yy - yMin2)/yRange2); - p1 << Point(ix, plotH - iy); - } - if (!p1.IsEmpty()) - series[j].seriesPlot->Paint(w, p1, scale, series[j].opacity, - fround(series[j].thickness), series[j].color, - series[j].dash, plotAreaColor, series[j].fillColor, plotW/xRange, plotH/yRange, - int(plotH*(1 + yMin/yRange))); - - if (series[j].markWidth >= 1 && series[j].markPlot) { - for (int i = 0; i < (imax - imin)/numV; i++) - series[j].markPlot->Paint(w, scale, p1[i], series[j].markWidth, series[j].markColor); - } - } - } - w.End(); -} - -END_UPP_NAMESPACE - -#endif - +#ifndef _ScatterDraw_ScatterDraw_h +#define _ScatterDraw_ScatterDraw_h + +#include +#include +#include "DataSource.h" + +NAMESPACE_UPP + +#include "DrawingFunctions.h" +#include "SeriesPlot.h" +#include "MarkPlot.h" + +Color GetOpaqueColor(const Color &color, const Color &background, const double opacity); + +class ScatterDraw { +public: + typedef ScatterDraw CLASSNAME; + ScatterDraw(); + + enum Formats { + EXP, + MON, + DY, + CUSTOM + }; + enum { + MD_DRAW = -1, + MD_ANTIALIASED = MODE_ANTIALIASED, + MD_NOAA = MODE_NOAA, + MD_SUBPIXEL = MODE_SUBPIXEL + }; + + #define LINE_DOTTED "4 10" + #define LINE_DOTTED_SEP "4 20" + #define LINE_DASHED "12 12" + #define LINE_DASH_DOT "20 10 5 10" + #define LINE_SOLID "" + +protected: + class ScatterBasicSeries { + public: + ScatterBasicSeries(); + void Init(int id); + + bool primaryY; + bool sequential; + + One seriesPlot; + double thickness; + Color color; + String dash; + + One markPlot; + double markWidth; + Color markColor; + + Color fillColor; + + String legend; + + double opacity; + + int id; + + bool trendLine; + //double trend + }; + + class ScatterSeries : public Moveable, public ScatterBasicSeries { + public: + ScatterSeries() {pD = 0;} + void SetDataSource(DataSource *pointsData, bool ownsData = true) {pD = pointsData; owns = ownsData;} + inline DataSource *PointsData() {return pD;} + ~ScatterSeries() {if(pD && owns) delete pD;} + private: + DataSource *pD; + bool owns; + }; + + static Color GetNewColor(int id); + static String GetNewDash(int id); + static MarkPlot *GetNewMarkPlot(int id); + +public: + Callback3 cbModifFormatX, cbModifFormatDeltaX; + Callback3 cbModifFormatY, cbModifFormatDeltaY; + Callback3 cbModifFormatY2, cbModifFormatDeltaY2; + + Callback WhenZoomScroll; + Callback WhenSetRange; + Callback WhenSetXYMin; + + ScatterDraw& SetSize(Size sz) {size = sz; return *this;}; + virtual Size GetSize() const {return size;}; + + ScatterDraw& SetColor(const Color& _color); + ScatterDraw& SetTitle(const String& _title); + ScatterDraw& SetTitleFont(const Font& fontTitle); + ScatterDraw& SetTitleColor(const Color& colorTitle); + + void SetLabels(const String& _xLabel, const String& _yLabel, const String& _yLabel2 = ""); + ScatterDraw& SetLabelX(const String& _xLabel); + ScatterDraw& SetLabelY(const String& _yLabel); + ScatterDraw& SetLabelY2(const String& _yLabel); + ScatterDraw& SetLabelsFont(const Font& fontLabels); + Font GetLabelsFont() {return labelsFont;}; + ScatterDraw& SetLabelsColor(const Color& colorLabels); + + ScatterDraw& SetPlotAreaMargin(const int hLeft, const int hRight, const int vTop, const int vBottom); + ScatterDraw& SetPlotAreaLeftMargin(const int margin); + ScatterDraw& SetPlotAreaRightMargin(const int margin); + ScatterDraw& SetPlotAreaTopMargin(const int margin); + ScatterDraw& SetPlotAreaBottomMargin(const int margin); + + ScatterDraw& SetPlotAreaColor(const Color& p_a_color); + + ScatterDraw& SetAxisColor(const Color& axis_color); + ScatterDraw& SetAxisWidth(const int& axis_width); + + ScatterDraw& SetGridColor(const Color& grid_color); + ScatterDraw& SetGridWidth(const int& grid_width); + ScatterDraw& ShowVGrid(const bool& show); + ScatterDraw& ShowHGrid(const bool& show); + + ScatterDraw& ShowLegend(const bool& show=true); + ScatterDraw& SetLegendWeight(const int& weight); + + ScatterDraw& SetMode(int _mode = MD_ANTIALIASED) {mode = _mode; Refresh(); return *this;}; + int GetMode() {return mode;}; + + void FitToData(bool Y = false); + void Zoom(double scale, bool hor = true, bool ver = true); + void Scroll(double factorX, double factorY); + + enum ZoomStyle {TO_CENTER, FROM_BASE}; + ScatterDraw &SetZoomStyleX(ZoomStyle style = TO_CENTER) {zoomStyleX = style; return *this;} + ScatterDraw &SetZoomStyleY(ZoomStyle style = TO_CENTER) {zoomStyleY = style; return *this;} + + ScatterDraw& SetRange(double rx, double ry, double ry2 = 100); + double GetXRange()const {return xRange;} + double GetYRange()const {return yRange;} + double GetY2Range()const {return yRange2;} + ScatterDraw &SetMajorUnits(double ux, double uy); + ScatterDraw &SetMajorUnitsNum(int nx, int ny); + ScatterDraw &SetMaxMajorUnitsX(int maxX, int maxY) {maxMajorUnitsX = maxX; maxMajorUnitsY = maxY; return *this;} + double GetMajorUnitsX() {return xMajorUnit;} + double GetMajorUnitsY() {return yMajorUnit;} + ScatterDraw& SetMinUnits(double ux, double uy); + double GetXMinUnit () const {return xMinUnit;} + double GetYMinUnit () const {return yMinUnit;} + + ScatterDraw& SetXYMin(double xmin,double ymin,double ymin2 = 0); + double GetXMin () const {return xMin;} + double GetYMin () const {return yMin;} + double GetYMin2 () const {return yMin2;} + + ScatterDraw &Graduation_FormatX(Formats fi); + ScatterDraw &Graduation_FormatY(Formats fi); + ScatterDraw &Graduation_FormatY2(Formats fi); + + ScatterDraw &AddSeries(double *yData, int numData, double x0 = 0, double deltaX = 1); + ScatterDraw &AddSeries(double *xData, double *yData, int numData); + ScatterDraw &AddSeries(Vector &xData, Vector &yData); + ScatterDraw &AddSeries(Upp::Array &xData, Upp::Array &yData); + ScatterDraw &AddSeries(Vector &points); + ScatterDraw &AddSeries(Upp::Array &points); + ScatterDraw &AddSeries(double (*function)(double)); + ScatterDraw &AddSeries(Pointf (*function)(double), int np, double from = 0, double to = 1); + ScatterDraw &AddSeries(PlotFunc &function); + ScatterDraw &AddSeries(PlotParamFunc function, int np, double from = 0, double to = 1); + ScatterDraw &_AddSeries(DataSource *data); + ScatterDraw &AddSeries(DataSource &data); + + template + ScatterDraw &AddSeries() {return _AddSeries(new C());} + template + ScatterDraw &AddSeries(T1 &arg1) + {return _AddSeries(new C(arg1));} + template + ScatterDraw &AddSeries(T1 &arg1, T2 &arg2) + {return _AddSeries(new C(arg1, arg2));} + template + ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3) + {return _AddSeries(new C(arg1, arg2, arg3));} + template + ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4) + {return _AddSeries(new C(arg1, arg2, arg3, arg4));} + template + ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5) + {return _AddSeries(new C(arg1, arg2, arg3, arg4, arg5));} + template + ScatterDraw &AddSeries(T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5, T6 &arg6) + {return _AddSeries(new C(arg1, arg2, arg3, arg4, arg5, arg6));} + + template + ScatterDraw &AddSeries(Vector &yData) {return _AddSeries(new VectorY(yData));} + template + ScatterDraw &AddSeries(Upp::Array &yData) {return _AddSeries(new ArrayY(yData));} + template + ScatterDraw &AddSeries(VectorMap &data) {return _AddSeries(new VectorMapXY(data));} + template + ScatterDraw &AddSeries(ArrayMap &data) {return _AddSeries(new ArrayMapXY(data));} + + void InsertSeries(int id, double *yData, int numData, double x0 = 0, double deltaX = 1); + void InsertSeries(int id, double *xData, double *yData, int numData); + void InsertSeries(int id, Vector &xData, Vector &yData); + void InsertSeries(int id, Upp::Array &xData, Upp::Array &yData); + void InsertSeries(int id, Vector &points); + void InsertSeries(int id, Upp::Array &points); + void InsertSeries(int id, double (*function)(double)); + void InsertSeries(int id, Pointf (*function)(double), int np, double from = 0, double to = 1); + void InsertSeries(int id, PlotFunc &function); + void InsertSeries(int id, PlotParamFunc function, int np, double from = 0, double to = 1); + void _InsertSeries(int id, DataSource *data); + + template + void InsertSeries(int id) {_InsertSeries(id, new C());} + template + void InsertSeries(int id, T1 &arg1) + {_InsertSeries(id, new C(arg1));} + template + void InsertSeries(int id, T1 &arg1, T2 &arg2) + {_InsertSeries(id, new C(arg1, arg2));} + template + void InsertSeries(int id, T1 &arg1, T2 &arg2, T3 &arg3) + {_InsertSeries(id, new C(arg1, arg2, arg3));} + template + void InsertSeries(int id, T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4) + {_InsertSeries(id, new C(arg1, arg2, arg3, arg4));} + template + void InsertSeries(int id, T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5) + {_InsertSeries(id, new C(arg1, arg2, arg3, arg4, arg5));} + template + void InsertSeries(int id, T1 &arg1, T2 &arg2, T3 &arg3, T4 &arg4, T5 &arg5, T6 &arg6) + {_InsertSeries(id, new C(arg1, arg2, arg3, arg4, arg5, arg6));} + + template + void InsertSeries(int id, Vector &yData) {_InsertSeries(id, new VectorY(yData));} + template + void InsertSeries(int id, Upp::Array &yData) {_InsertSeries(id, new ArrayY(yData));} + template + void InsertSeries(int id, VectorMap &data){_InsertSeries(id, new VectorMapXY(data));} + template + void InsertSeries(int id, ArrayMap &data) {_InsertSeries(id, new ArrayMapXY(data));} + + ScatterDraw &PlotStyle() {return PlotStyle(0);}; + template + ScatterDraw &PlotStyle() {return PlotStyle(new C());}; + template + ScatterDraw &PlotStyle(T1 &arg1) {return PlotStyle(new C(arg1));}; + template + ScatterDraw &PlotStyle(T1 &arg1, T2 &arg2) {return PlotStyle(new C(arg1, arg2));}; + template + ScatterDraw &PlotStyle(T1 &arg1, T2 &arg2, T3 &arg3) {return PlotStyle(new C(arg1, arg2, arg3));}; + ScatterDraw &PlotStyle(SeriesPlot *data); + + ScatterDraw &NoPlot() {return PlotStyle();}; + + ScatterDraw &MarkStyle() {return MarkStyle(0);}; + template + ScatterDraw &MarkStyle() {return MarkStyle(new C());}; + template + ScatterDraw &MarkStyle(T1 &arg1) {return MarkStyle(new C(arg1));}; + template + ScatterDraw &MarkStyle(T1 &arg1, T2 &arg2) {return MarkStyle(new C(arg1, arg2));}; + template + ScatterDraw &MarkStyle(T1 &arg1, T2 &arg2, T3 &arg3) {return MarkStyle(new C(arg1, arg2, arg3));}; + ScatterDraw &MarkStyle(MarkPlot *data); + + ScatterDraw &NoMark() {return MarkStyle();}; + + ScatterDraw &Stroke(double thickness = 3, Color color = Null); + ScatterDraw &Dash(const char *dash); + ScatterDraw &Fill(Color color = Null); + ScatterDraw &MarkColor(Color color = Null); + ScatterDraw &MarkWidth(const double& markWidth = 8); + ScatterDraw &Hide() {series[series.GetCount() - 1].opacity = 0; return *this;} + + ScatterDraw &Opacity(double opacity = 1) {series[series.GetCount() - 1].opacity = opacity; return *this;} + ScatterDraw &Legend(const String legend); + + inline bool IsValid(const int& j) const {return (j >= 0 && j < series.GetCount());} + + ScatterDraw& SetDrawXReticle(bool set = true); + ScatterDraw& SetDrawYReticle(bool set = true); + ScatterDraw& SetDrawY2Reticle(bool set = true); + + void SetDataColor(const int& j,const Color& pcolor); + Color GetDataColor (const int& j) const; + void SetDataThickness(const int& j, const double& thick); + double GetDataThickness(const int& j) const; + void SetFillColor(const int& j, const Color& color); + Color GetFillColor(const int& j) const; + + ScatterDraw &SetMarkWidth(const int& j, const double& width); + double GetMarkWidth(const int& j) const; + void SetMarkColor(const int& j, const Color& pcolor); + Color GetMarkColor (const int& j) const; + void NoMark(const int& j); + bool IsShowMark(const int& j) const throw (Exc); + + void SetDataPrimaryY(const int& j, const bool& primary=true); + ScatterDraw &SetDataPrimaryY(const bool& primary); + bool IsDataPrimaryY(const int& j) const throw (Exc); + + void SetSequentialX(const int& j, const bool& sequential = true); + ScatterDraw &SetSequentialX(const bool& sequential = true); + ScatterDraw &SetSequentialXAll(const bool& sequential = true); + + void Show(const int& j, const bool& show = true); + bool IsVisible(const int& j); + ScatterDraw &ShowAll(const bool& show = true); + + void RemoveSeries(const int& j); + void RemoveAllSeries(); + + ScatterDraw& Id(int id); + ScatterDraw& Id(const int& j, int id); + int GetId(const int& j); + + Drawing GetDrawing(); + Image GetImage(const int& scale = 1); + + #ifdef PLATFORM_WIN32 + void SaveAsMetafile(const char* file) const; + #endif + + ScatterDraw& LogX(const bool& logx=true) {logX=logx; return *this;} + ScatterDraw& LogY(const bool& logy=true) {logY=logy; return *this;} + ScatterDraw& LogY2(const bool& logy=true) {logY2=logy; return *this;} + + ScatterDraw& SetMinZoom(double x, double y = -1) {minXZoom = x; minYZoom = y; return *this;}; + ScatterDraw& SetMaxZoom(double x, double y = -1) {maxXZoom = x; maxYZoom = y; return *this;}; + + ScatterDraw& SetFastViewX(bool set = true) {fastViewX = set; return *this;}; + + Font& GetTitleFont() {return titleFont;}; + + double GetXByPoint(const int x); + double GetYByPoint(const int y); + double GetY2ByPoint(const int y); + double GetXPointByValue(const double x); + double GetYPointByValue(const double y); + + int GetCount() {return series.GetCount();} + bool IsEmpty() {return series.IsEmpty();} + + virtual void Refresh() {}; + +protected: + int mode; + Color graphColor; + String title; + Font titleFont; + Color titleColor; + + String xLabel, yLabel, yLabel2; + Font labelsFont; + Color labelsColor; + + int hPlotLeft, hPlotRight, vPlotTop, vPlotBottom; + Color plotAreaColor; + + bool fastViewX, sequentialXAll; + + Color axisColor; + int axisWidth; + + double xRange, yRange, yRange2; + double xMin, yMin, yMin2; + double xMajorUnit, yMajorUnit, yMajorUnit2; + double xMinUnit, yMinUnit, yMinUnit2; + double minXZoom, maxXZoom, minYZoom, maxYZoom; + bool drawXReticle, drawYReticle, drawY2Reticle; + + int maxMajorUnitsX, maxMajorUnitsY; + + Color gridColor; + int gridWidth; + bool drawVGrid, drawHGrid; + + int butDownX, butDownY; + bool isScrolling, isLabelPopUp; + ZoomStyle zoomStyleX, zoomStyleY; + + Vector series; + + bool showLegend; + int legendWeight; + + void DrawLegend(Draw& w,const int& scale) const; + + void Scrolling(bool down, Point &pt, bool isOut = false); + + void ExpFormat(String& s, int i, double d) {s = FormatDoubleExp(d,1);} + void MonFormat(String& s, int i, double d) {s = Format("%Mon",int(d));} + void DyFormat(String& s, int i, double d) {s = Format("%Dy",int(d));} + + static String VariableFormat(double range, double d) + { + if (fabs(d) <= 1e-15) + d = 0; + if (0.001<=range && range<0.01) return FormatDouble(d,5); + else if (0.01<=range && range<0.1) return FormatDouble(d,4); + else if (0.1<=range && range<1) return FormatDouble(d,3); + else if (1<=range && range<10) return FormatDouble(d,2); + else if (10<=range && range<100) return FormatDouble(d,1); + else if (100<=range && range<100000) return FormatDouble(d,0); + else return FormatDoubleExp(d,2); + + } + String VariableFormatX(const double& d) const {return VariableFormat(xRange, d);} + String VariableFormatY(const double& d) const {return VariableFormat(yRange, d);} + String VariableFormatY2(const double& d) const {return VariableFormat(yRange2, d);} + + template + void SetDrawing(T& w, const int& scale); + template + void Plot(T& w, const int& scale,const int& l,const int& h); + + void AdjustMinUnitX(); + void AdjustMinUnitY(); + void AdjustMinUnitY2(); + + bool logX, logY, logY2; + +private: + Size size; + static void ParseTextMultiline(const String &text, Font fnt, + Upp::Array &texts, Upp::Array &sizes); +}; + +template +void ScatterDraw::SetDrawing(T& w, const int& scale) +{ + if (GetSize().cx == 0 || GetSize().cy == 0) + return; + + w.DrawRect(scale*GetSize(), graphColor); + + if (typeid(T) == typeid(BufferPainter)) { + Painter &p = (Painter &)w; + p.Translate(0, 0.5); + } + + Size sz(0, 0); + + int titleHeight = !title.IsEmpty() ? scale*titleFont.GetHeight() : 0; + + if(titleHeight > 0) { + Font fontTitle6; + fontTitle6 = titleFont; + fontTitle6.Height(titleHeight); + fontTitle6.Width(scale*titleFont.GetWidth()); + sz = GetTextSize(title, fontTitle6); + DrawText(w, (scale*GetSize().cx - sz.cx)/2., scale*2., 0, title, fontTitle6, titleColor); + } + + w.Offset(Point(scale*hPlotLeft, scale*vPlotTop + titleHeight)); + if(showLegend) + DrawLegend(w, scale); + + int plotW = scale*(GetSize().cx - (hPlotLeft + hPlotRight)); + int plotH = scale*(GetSize().cy - (vPlotTop + vPlotBottom)) - titleHeight; + + Font fontLabel; + fontLabel = labelsFont; + fontLabel.Height(scale*labelsFont.GetHeight()); + + Size lx = GetTextSize(xLabel, fontLabel); + Size ly = GetTextSize(yLabel, fontLabel); + Size ly2 = GetTextSize(yLabel2, fontLabel); + DrawText(w, (plotW - lx.cx)/2., scale*GetSize().cy - lx.cy - 70*scale, 0, xLabel, fontLabel, labelsColor); + DrawText(w, scale*2. - scale*hPlotLeft, (plotH + ly.cx)/2., 900, yLabel, fontLabel, labelsColor); + DrawText(w, scale*GetSize().cx - ly2.cy - 42*scale, (plotH + ly2.cx)/2., 900, yLabel2, fontLabel, labelsColor); + + if (typeid(T) == typeid(BufferPainter)) { + Painter &p = (Painter &)w; + p.Translate(0.5, 0); + } + + if (drawXReticle) + for(int i = 0; xMinUnit + i*xMajorUnit <= xRange; i++){ + w.DrawLine(fround(plotW*xMinUnit/xRange + i*plotW/(xRange/xMajorUnit)), plotH, + fround(plotW*xMinUnit/xRange + i*plotW/(xRange/xMajorUnit)), plotH + scale*4, + fround(gridWidth*scale), axisColor); + Font standard6; + standard6.Height(scale*StdFont().GetHeight()); + double gridX = xMinUnit + i*xMajorUnit + xMin; + String gridLabelX; + if (cbModifFormatX) + cbModifFormatX(gridLabelX, i, gridX); + else + gridLabelX = VariableFormatX(gridX); + + Array texts; + Array sizes; + ParseTextMultiline(gridLabelX, StdFont(), texts, sizes); + for (int ii = 0; ii < texts.GetCount(); ++ii) { + int cy = ii == 0 ? 0 : sizes[ii - 1].cy; + DrawText(w, plotW*xMinUnit/xRange + i*plotW/(xRange/xMajorUnit) - scale*sizes[ii].cx/2., + plotH + scale*(4 + ii*cy), 0, texts[ii], standard6, axisColor); + } + } + + if (drawYReticle) + for(int i = 0; yMinUnit + i*yMajorUnit <= yRange; i++){ + w.DrawLine(-(scale*4), fround(-plotH*yMinUnit/yRange + plotH - i*plotH/(yRange/yMajorUnit)), + 0, fround(-plotH*yMinUnit/yRange + plotH - i*plotH/(yRange/yMajorUnit)), + fround(gridWidth*scale), axisColor); + double gridY = yMinUnit + i*yMajorUnit + yMin; + String gridLabelY; + if (cbModifFormatY) + cbModifFormatY(gridLabelY, i, gridY); + else + gridLabelY = VariableFormatY(gridY); + int dx=scale*GetTextSize(gridLabelY,StdFont()).cx; + Font Standard6; + Standard6.Height(scale*StdFont().GetHeight()); + DrawText(w, -dx - scale*6, fround(-plotH*yMinUnit/yRange + plotH - i*plotH/(yRange/yMajorUnit)) - scale*8, + 0, gridLabelY, Standard6, axisColor); + } + + if (drawY2Reticle) + for(int i = 0; yMinUnit + i*yMajorUnit <= yRange; i++){ + w.DrawLine(plotW + (scale*4), fround(-plotH*yMinUnit2/yRange2 + plotH - i*plotH/(yRange/yMajorUnit)), + plotW, fround(-plotH*yMinUnit2/yRange2 + plotH - i*plotH/(yRange/yMajorUnit)), + fround(gridWidth*scale), axisColor); + double gridY2 = yMinUnit2 + i*yMajorUnit2 + yMin2; + String gridLabelY2; + if (cbModifFormatY2) + cbModifFormatY2(gridLabelY2, i, gridY2); + else + gridLabelY2 = VariableFormatY2(gridY2); + Font standard6; + standard6.Height(scale*StdFont().GetHeight()); + DrawText(w, plotW + scale*10, fround(-plotH*yMinUnit2/yRange2 + plotH - i*plotH/(yRange/yMajorUnit)) - scale*8, 0, + gridLabelY2, standard6, axisColor); + } + + Plot(w, scale, plotW, plotH); + ClipEnd(w); +} + +template +void ScatterDraw::Plot(T& w, const int& scale, const int& plotW, const int& plotH) +{ + double d1 = xRange/xMajorUnit; + double d2 = yRange/yMajorUnit; + + w.DrawRect(1, 1, plotW - 2, plotH - 1, plotAreaColor); + + if (drawVGrid) + for(int i = 0; xMinUnit + i*xMajorUnit < xRange; i++) + DrawLineOpa(w, fround(plotW*xMinUnit/xRange + i*plotW/d1), 0, fround(plotW*xMinUnit/xRange + i*plotW/d1), plotH, + 1, 1, gridWidth, gridColor, "2 2"); + + if (drawHGrid) + for(int i = 0; yMinUnit + i*yMajorUnit < yRange; i++) + DrawLineOpa(w, 0, fround(-plotH*yMinUnit/yRange + plotH - i*plotH/d2), plotW, fround(-plotH*yMinUnit/yRange + plotH - i*plotH/d2), + 1, 1, gridWidth, gridColor, "2 2"); + + w.DrawLine(0, plotH, plotW, plotH, fround(gridWidth*scale), Black); + w.DrawLine(0, 0, plotW, 0, fround(gridWidth*scale), Black); + w.DrawLine(0, 0, 0, plotH, fround(gridWidth*scale), Black); + w.DrawLine(plotW, 0, plotW, plotH + 1, fround(gridWidth*scale), Black); + + Clip(w, 0, 0, plotW, plotH); + + if (!series.IsEmpty()) { + for (int j = 0; j < series.GetCount(); j++) { + if (series[j].opacity == 0 || (!series[j].seriesPlot && !series[j].markPlot)) + continue; + Vector p1; + int imin, imax; + if (series[j].sequential) { + imin = imax = Null; + for (int i = 1; i < series[j].PointsData()->GetCount() - 1; ++i) { + if (IsNull(imin)) { + if (series[j].PointsData()->x(i) >= xMin) + imin = i - 1; + } else if (IsNull(imax)) { + if (series[j].PointsData()->x(i) >= xMin + xRange) + imax = i + 1; + } + } + if (IsNull(imin)) + imin = 0; + if (IsNull(imax)) + imax = series[j].PointsData()->GetCount(); + } else if (series[j].PointsData()->IsParam()) { // It is a param function + imin = 0; + imax = series[j].PointsData()->GetCount(); + } else if (IsNull(series[j].PointsData()->GetCount())) { // It is a function + imin = fround(xMin) - 1; + imax = fround(xMin + xRange) + 1; + } else { + imin = 0; + imax = series[j].PointsData()->GetCount(); + } + int numV; + if (fastViewX) + numV = 1 + (imax - imin)/plotW; + else + numV = 1; + for (int i = imin; i < imax; i += numV) { + double xx, yy; + if (fastViewX && numV > 1) { + yy = 0; + int ii; + for (ii = 0; ii < numV && i + ii < imax; ++ii) + yy += series[j].PointsData()->y(i + ii); + yy /= double(ii); + xx = (series[j].PointsData()->x(i) + series[j].PointsData()->x(i + ii - 1))/2; + } else { + xx = series[j].PointsData()->x(i); + yy = series[j].PointsData()->y(i); + } + int ix, iy; + ix = fround(plotW*(xx - xMin)/xRange); + if (series[j].primaryY) + iy = fround(plotH*(yy - yMin)/yRange); + else + iy = fround(plotH*(yy - yMin2)/yRange2); + p1 << Point(ix, plotH - iy); + } + if (!p1.IsEmpty()) + series[j].seriesPlot->Paint(w, p1, scale, series[j].opacity, + fround(series[j].thickness), series[j].color, + series[j].dash, plotAreaColor, series[j].fillColor, plotW/xRange, plotH/yRange, + int(plotH*(1 + yMin/yRange))); + + if (series[j].markWidth >= 1 && series[j].markPlot) { + for (int i = 0; i < (imax - imin)/numV; i++) + series[j].markPlot->Paint(w, scale, p1[i], series[j].markWidth, series[j].markColor); + } + } + } + w.End(); +} + +END_UPP_NAMESPACE + +#endif +