//+------------------------------------------------------------------+ //| Curve.mqh | //| Copyright 2000-2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include #include //--- forward declaration class CGraphic; //--- fucntion for represent custom plot method typedef void(*PlotFucntion)(double &x[],double &y[],int size,CGraphic *graphic,CCanvas *canvas,void *cbdata); //--- function for represent curve typedef double(*CurveFunction)(double); //--- drawing type enum ENUM_CURVE_TYPE { CURVE_POINTS, CURVE_LINES, CURVE_POINTS_AND_LINES, CURVE_STEPS, CURVE_HISTOGRAM, CURVE_CUSTOM, CURVE_NONE }; //--- type for the various point shapes that are available enum ENUM_POINT_TYPE { POINT_CIRCLE, POINT_SQUARE, POINT_DIAMOND, POINT_TRIANGLE, POINT_TRIANGLE_DOWN, POINT_X_CROSS, POINT_PLUS, POINT_STAR, POINT_HORIZONTAL_DASH, POINT_VERTICAL_DASH }; //+------------------------------------------------------------------+ //| Structure CPoint2D | //| Usage: 2d point on graphic in Cartesian coordinates | //+------------------------------------------------------------------+ struct CPoint2D { double x; double y; }; //+------------------------------------------------------------------+ //| Class CCurve | //| Usage: class to represent the one-dimensional curve | //+------------------------------------------------------------------+ class CCurve : public CObject { private: uint m_clr; double m_x[]; double m_y[]; double m_xmin; double m_xmax; double m_ymin; double m_ymax; int m_size; ENUM_CURVE_TYPE m_type; string m_name; //--- lines ENUM_LINE_STYLE m_lines_style; ENUM_LINE_END m_lines_end_style; int m_lines_width; bool m_lines_smooth; double m_lines_tension; double m_lines_step; //--- points int m_points_size; ENUM_POINT_TYPE m_points_type; bool m_points_fill; uint m_points_clr; //--- steps int m_steps_dimension; //--- histogram int m_hisogram_width; //--- custom PlotFucntion m_custom_plot_func; void *m_custom_plot_cbdata; //--- general property bool m_visible; //--- trend line property uint m_trend_clr; bool m_trend_visible; protected: bool m_trend_calc; double m_trend_coeff[]; public: CCurve(const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name); CCurve(const double &x[],const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name); CCurve(const CPoint2D &points[],const uint clr,ENUM_CURVE_TYPE type,const string name); CCurve(CurveFunction function,const double from,const double to,const double step,const uint clr,ENUM_CURVE_TYPE type,const string name); ~CCurve(void); //--- gets the general properties void GetX(double &x[]) const { ArrayCopy(x,m_x); } void GetY(double &y[]) const { ArrayCopy(y,m_y); } double XMax(void) const { return(m_xmax); } double XMin(void) const { return(m_xmin); } double YMax(void) const { return(m_ymax); } double YMin(void) const { return(m_ymin); } int Size(void) const { return(m_size); } //--- update void Update(const double &y[]); void Update(const double &x[],const double &y[]); void Update(const CPoint2D &points[]); void Update(CurveFunction function,const double from,const double to,const double step); //--- gets or sets general options uint Color(void) const { return(m_clr); } int Type(void) const { return(m_type); } string Name(void) const { return(m_name); } bool Visible(void) const { return(m_visible); } void Color(const uint clr) { m_clr=clr; } void Type(const int type) { m_type=(ENUM_CURVE_TYPE)type; } void Name(const string name) { m_name=name; } void Visible(const bool visible) { m_visible=visible; } //--- gets or sets the lines properties ENUM_LINE_STYLE LinesStyle(void) const { return(m_lines_style); } ENUM_LINE_END LinesEndStyle(void) const { return(m_lines_end_style); } int LinesWidth(void) const { return(m_lines_width); } bool LinesSmooth(void) const { return(m_lines_smooth); } double LinesSmoothTension(void) const { return(m_lines_tension); } double LinesSmoothStep(void) const { return(m_lines_step); } void LinesStyle(ENUM_LINE_STYLE style) { m_lines_style=style; } void LinesEndStyle(ENUM_LINE_END end_style) { m_lines_end_style=end_style; } void LinesWidth(const int width) { m_lines_width=width; } void LinesSmooth(const bool smooth) { m_lines_smooth=smooth; } void LinesSmoothTension(const double tension) { m_lines_tension=tension; } void LinesSmoothStep(const double step) { m_lines_step=step; } //--- gets or sets the points properties int PointsSize(void) const { return(m_points_size); } ENUM_POINT_TYPE PointsType(void) const { return(m_points_type); } bool PointsFill(void) const { return(m_points_fill); } uint PointsColor(void) const { return(m_points_clr); } void PointsSize(const int size) { m_points_size=size; } void PointsType(ENUM_POINT_TYPE type) { m_points_type=type; } void PointsFill(const bool fill) { m_points_fill=fill; } void PointsColor(const uint clr) { m_points_clr=clr; } //--- gets or sets the steps properties int StepsDimension(void) const { return(m_steps_dimension); } void StepsDimension(const int dimension) { m_steps_dimension=dimension; } //--- gets or sets the histogram properties int HistogramWidth(void) const { return(m_hisogram_width); } void HistogramWidth(const int width) { m_hisogram_width=width; } //--- gets or sets the custom properties PlotFucntion CustomPlotFunction(void) const { return(m_custom_plot_func); } void *CustomPlotCBData(void) const { return(m_custom_plot_cbdata); } void CustomPlotFunction(PlotFucntion func) { m_custom_plot_func=func; } void CustomPlotCBData(void *cbdata) { m_custom_plot_cbdata=cbdata; } //--- gets or sets the trend line properties bool TrendLineVisible(void) const { return(m_trend_visible); } uint TrendLineColor(void) const { return(m_trend_clr); } void TrendLineVisible(const bool visible) { m_trend_visible=visible; } void TrendLineColor(const uint clr) { m_trend_clr=clr; } void TrendLineCoefficients(double &coefficients[]); protected: virtual void CalculateCoefficients(void); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CCurve::CCurve(const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name) : m_name(name), m_clr(clr), m_type(type), m_visible(false), m_lines_style(STYLE_SOLID), m_lines_end_style(LINE_END_ROUND), m_lines_width(1), m_lines_smooth(false), m_lines_tension(0.5), m_lines_step(1.0), m_points_size(6), m_points_type(POINT_CIRCLE), m_points_fill(false), m_points_clr(clr), m_steps_dimension(0), m_hisogram_width(1), m_custom_plot_func(NULL), m_custom_plot_cbdata(NULL), m_trend_visible(false), m_trend_clr(clr), m_trend_calc(false) { //--- keep y array m_size=ArraySize(y); ArrayResize(m_x,m_size); ArrayCopy(m_y,y); m_xmax = m_size-1; m_xmin = 0.0; m_ymax = 0.0; m_ymin = 0.0; bool yvalid=false; //--- find min and max values for(int i=0; iy[i]) m_ymin=y[i]; } } } //--- } //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CCurve::CCurve(const double &x[],const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name) : m_name(name), m_clr(clr), m_type(type), m_visible(false), m_lines_style(STYLE_SOLID), m_lines_end_style(LINE_END_ROUND), m_lines_width(1), m_lines_smooth(false), m_lines_tension(0.5), m_lines_step(1.0), m_points_size(6), m_points_type(POINT_CIRCLE), m_points_fill(false), m_points_clr(clr), m_steps_dimension(0), m_hisogram_width(1), m_custom_plot_func(NULL), m_custom_plot_cbdata(NULL), m_trend_visible(false), m_trend_clr(clr), m_trend_calc(false) { //--- keep x and y array ArrayCopy(m_x,x); ArrayCopy(m_y,y); m_size = ArraySize(x); m_xmax = 0.0; m_xmin = 0.0; m_ymax = 0.0; m_ymin = 0.0; bool yvalid=false; bool xvalid=false; //--- find min and max values for(int i=0; ix[i]) m_xmin=x[i]; } } if(MathIsValidNumber(m_y[i])) { if(!yvalid) { m_ymax = y[i]; m_ymin = y[i]; yvalid=true; } else { //--- find max and min of y if(m_ymaxy[i]) m_ymin=y[i]; } } } //--- } //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CCurve::CCurve(const CPoint2D &points[],const uint clr,ENUM_CURVE_TYPE type,const string name) : m_name(name), m_clr(clr), m_type(type), m_visible(false), m_lines_style(STYLE_SOLID), m_lines_end_style(LINE_END_ROUND), m_lines_width(1), m_lines_smooth(false), m_lines_tension(0.5), m_lines_step(1.0), m_points_size(6), m_points_type(POINT_CIRCLE), m_points_fill(false), m_points_clr(clr), m_steps_dimension(0), m_hisogram_width(1), m_custom_plot_func(NULL), m_custom_plot_cbdata(NULL), m_trend_visible(false), m_trend_clr(clr), m_trend_calc(false) { //--- preliminary calculation m_size=ArraySize(points); ArrayResize(m_x,m_size); ArrayResize(m_y,m_size); m_xmax = 0.0; m_xmin = 0.0; m_ymax = 0.0; m_ymin = 0.0; bool xvalid=false; bool yvalid=false; //--- keep x and y array for(int i=0; im_x[i]) m_xmin=m_x[i]; } } if(MathIsValidNumber(m_y[i])) { if(!yvalid) { m_ymax = m_y[i]; m_ymin = m_y[i]; yvalid=true; } else { //--- find max and min of y if(m_ymaxm_y[i]) m_ymin=m_y[i]; } } } //--- } //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CCurve::CCurve(CurveFunction function,const double from,const double to,const double step,const uint clr,ENUM_CURVE_TYPE type,const string name) : m_name(name), m_clr(clr), m_type(type), m_visible(false), m_lines_style(STYLE_SOLID), m_lines_end_style(LINE_END_ROUND), m_lines_width(1), m_lines_smooth(false), m_lines_tension(0.5), m_lines_step(1.0), m_points_size(6), m_points_type(POINT_CIRCLE), m_points_fill(false), m_points_clr(clr), m_steps_dimension(0), m_hisogram_width(1), m_custom_plot_func(NULL), m_custom_plot_cbdata(NULL), m_trend_visible(false), m_trend_clr(clr), m_trend_calc(false) { //--- preliminary calculation m_size=(int)((to-from)/step)+1; ArrayResize(m_x,m_size); ArrayResize(m_y,m_size); m_xmax = to; m_xmin = from; m_ymax = 0.0; m_ymin = 0.0; bool yvalid=false; //--- keep x and y array for(int i=0; im_y[i]) m_ymin=m_y[i]; } } } //--- } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CCurve::~CCurve(void) { } //+------------------------------------------------------------------+ //| Update x and y coordinates of curve | //+------------------------------------------------------------------+ void CCurve::Update(const double &y[]) { m_trend_calc=false; ArrayFree(m_y); int size=ArraySize(y); //--- keep y array if(m_size!=size) { m_size=size; ArrayResize(m_x,m_size); } ArrayCopy(m_y,y); m_xmax = m_size-1; m_xmin = 0.0; m_ymax = 0.0; m_ymin = 0.0; bool yvalid=false; //--- find min and max values for(int i=0; iy[i]) m_ymin=y[i]; } } } //--- } //+------------------------------------------------------------------+ //| Update x and y coordinates of curve | //+------------------------------------------------------------------+ void CCurve::Update(const double &x[],const double &y[]) { m_trend_calc=false; ArrayFree(m_x); ArrayFree(m_y); //--- keep x and y array ArrayCopy(m_x,x); ArrayCopy(m_y,y); m_size = ArraySize(x); m_xmax = 0.0; m_xmin = 0.0; m_ymax = 0.0; m_ymin = 0.0; bool yvalid=false; bool xvalid=false; //--- find min and max values for(int i=0; ix[i]) m_xmin=x[i]; } } if(MathIsValidNumber(m_y[i])) { if(!yvalid) { m_ymax = y[i]; m_ymin = y[i]; yvalid=true; } else { //--- find max and min of y if(m_ymaxy[i]) m_ymin=y[i]; } } } //--- } //+------------------------------------------------------------------+ //| Update x and y coordinates of curve | //+------------------------------------------------------------------+ void CCurve::Update(const CPoint2D &points[]) { m_trend_calc=false; int size=ArraySize(points); //--- preliminary calculation if(size!=m_size) { m_size=size; ArrayResize(m_x,m_size); ArrayResize(m_y,m_size); } m_xmax = 0.0; m_xmin = 0.0; m_ymax = 0.0; m_ymin = 0.0; bool xvalid=false; bool yvalid=false; //--- keep x and y array for(int i=0; im_x[i]) m_xmin=m_x[i]; } } if(MathIsValidNumber(m_y[i])) { if(!yvalid) { m_ymax = m_y[i]; m_ymin = m_y[i]; yvalid=true; } else { //--- find max and min of y if(m_ymaxm_y[i]) m_ymin=m_y[i]; } } } //--- } //+------------------------------------------------------------------+ //| Update x and y coordinates of curve | //+------------------------------------------------------------------+ void CCurve::Update(CurveFunction function,const double from,const double to,const double step) { m_trend_calc=false; int size=(int)((to-from)/step)+1; //--- preliminary calculation if(size!=m_size) { m_size=size; ArrayResize(m_x,m_size); ArrayResize(m_y,m_size); } m_xmax = to; m_xmin = from; m_ymax = 0.0; m_ymin = 0.0; bool yvalid=false; //--- keep x and y array for(int i=0; im_y[i]) m_ymin=m_y[i]; } } } //--- } //+------------------------------------------------------------------+ //| Gets the coefficients for trend line | //+------------------------------------------------------------------+ void CCurve::TrendLineCoefficients(double &coefficients[]) { if(!m_trend_calc) { CalculateCoefficients(); m_trend_calc=true; } ArrayCopy(coefficients,m_trend_coeff); } //+------------------------------------------------------------------+ //| Calculate coefficients | //+------------------------------------------------------------------+ void CCurve::CalculateCoefficients(void) { //--- simple linear resgression ArrayResize(m_trend_coeff,2); double xmean=0.0; double ymean=0.0; double sum_xy=0.0; double sum_xx=0.0; //--- primary calculate for(int i=0; i