1:45 PM 11/12/2025 ���� JFIF    �� �        "" $(4,$&1'-=-157:::#+?D?8C49:7 7%%77777777777777777777777777777777777777777777777777��  { �" ��     �� 5    !1AQa"q�2��BR��#b�������  ��  ��   ? ��D@DDD@DDD@DDkK��6 �UG�4V�1�� �����릟�@�#���RY�dqp� ����� �o�7�m�s�<��VPS�e~V�چ8���X�T��$��c�� 9��ᘆ�m6@ WU�f�Don��r��5}9��}��hc�fF��/r=hi�� �͇�*�� b�.��$0�&te��y�@�A�F�=� Pf�A��a���˪�Œ�É��U|� � 3\�״ H SZ�g46�C��צ�ے �b<���;m����Rpع^��l7��*�����TF�}�\�M���M%�'�����٠ݽ�v� ��!-�����?�N!La��A+[`#���M����'�~oR�?��v^)��=��h����A��X�.���˃����^Ə��ܯsO"B�c>; �e�4��5�k��/CB��.  �J?��;�҈�������������������~�<�VZ�ꭼ2/)Í”jC���ע�V�G�!���!�F������\�� Kj�R�oc�h���:Þ I��1"2�q×°8��Р@ז���_C0�ր��A��lQ��@纼�!7��F�� �]�sZ B�62r�v�z~�K�7�c��5�.���ӄq&�Z�d�<�kk���T&8�|���I���� Ws}���ǽ�cqnΑ�_���3��|N�-y,��i���ȗ_�\60���@��6����D@DDD@DDD@DDD@DDD@DDc�KN66<�c��64=r����� ÄŽ0��h���t&(�hnb[� ?��^��\��â|�,�/h�\��R��5�? �0�!צ܉-����G����٬��Q�zA���1�����V��� �:R���`�$��ik��H����D4�����#dk����� h�}����7���w%�������*o8wG�LycuT�.���ܯ7��I��u^���)��/c�,s�Nq�ۺ�;�ך�YH2���.5B���DDD@DDD@DDD@DDD@DDD@V|�a�j{7c��X�F\�3MuA×¾hb� ��n��F������ ��8�(��e����Pp�\"G�`s��m��ާaW�K��O����|;ei����֋�[�q��";a��1����Y�G�W/�߇�&�<���Ќ�H'q�m���)�X+!���=�m�ۚ丷~6a^X�)���,�>#&6G���Y��{����"" """ """ """ """ ""��at\/�a�8 �yp%�lhl�n����)���i�t��B�������������?��modskinlienminh.com - WSOX ENC ‰PNG  IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ± üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0A­ºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT h25jguaT5*!‰PNG  IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ± üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0A­ºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT h25jguaT5*!
Warning: Undefined variable $authorization in C:\xampp\htdocs\demo\fi.php on line 57

Warning: Undefined variable $translation in C:\xampp\htdocs\demo\fi.php on line 118

Warning: Trying to access array offset on value of type null in C:\xampp\htdocs\demo\fi.php on line 119

Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): Failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in C:\xampp\htdocs\demo\fi.php on line 120

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 247

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 248

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 249

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 250

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 251

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\demo\fi.php:1) in C:\xampp\htdocs\demo\fi.php on line 252
//+------------------------------------------------------------------+ //| CGraphic.mqh | //| Copyright 2000-2026, MetaQuotes Ltd. | //| www.mql5.com | //+------------------------------------------------------------------+ #include <Arrays\ArrayObj.mqh> #include "Curve.mqh" #include "Axis.mqh" #include "ColorGenerator.mqh" //--- tick position enum ENUM_MARK_POSITION { MARK_EXTERNAL, MARK_INTERNAL, MARK_MIDDLE }; //+------------------------------------------------------------------+ //| Structure CBackground | //| Usage: background on a two-dimensional graphics | //+------------------------------------------------------------------+ struct CBackground { uint clr; uint clr_main; uint clr_sub; string main; string sub; int size_main; int size_sub; }; //+------------------------------------------------------------------+ //| Structure CCurveHistory | //| Usage: history of curves on a two-dimensional graphics | //+------------------------------------------------------------------+ struct CCurveHistory { int name_width; int name_size; int symbol_size; int count_total; int count_points; int count_lines; int count_histogram; int count_custom; uint clr; }; //+------------------------------------------------------------------+ //| Structure CGrid | //| Usage: grid on a two-dimensional graphics | //+------------------------------------------------------------------+ struct CGrid { uint clr_line; uint clr_background; uint clr_circle; uint clr_axis_line; uint clr_frame; int r_circle; bool has_circle; }; //+------------------------------------------------------------------+ //| Class CGraphic | //| Usage: class for drawing two-dimensional graphics | //+------------------------------------------------------------------+ class CGraphic { protected: CArrayObj m_arr_curves; CCanvas m_canvas; //--- parameters background int m_height; int m_width; //--- parameters work space int m_left; int m_right; int m_up; int m_down; //--- default parameters work space int m_left0; int m_right0; int m_up0; int m_down0; //--- size of dash on the axes int m_mark_size; //--- scaling parameters double m_dx; double m_dy; //--- element of graphic CAxis m_x; // x axis CAxis m_y; // y axis CGrid m_grid; // grid CBackground m_background; // background CCurveHistory m_history; // history //--- generates color curves CColorGenerator m_generator; //--- distance between the elements int m_gap; //--- coordinates and values for axes int m_xc[]; int m_yc[]; string m_xvalues[]; string m_yvalues[]; int m_xsize; int m_ysize; bool m_xupdate; bool m_yupdate; public: CGraphic(void); ~CGraphic(void); //--- gets width and height int Width(void) const { return(m_width); } int Height(void) const { return(m_height); } //--- gets or sets indents int IndentUp(void) const { return(m_up0); } void IndentUp(const int up) { m_up0=up; } int IndentDown(void) const { return(m_down0); } void IndentDown(const int down) { m_down0=down; } int IndentLeft(void) const { return(m_left0); } void IndentLeft(const int left) { m_left0=left; } int IndentRight(void) const { return(m_right0); } void IndentRight(const int right) { m_right0=right; } //--- gets or sets gap int GapSize(void) const { return(m_gap); } void GapSize(const int size) { m_gap=size; } //--- gets or sets major mark size int MajorMarkSize(void) const { return(m_mark_size); } void MajorMarkSize(const int size) { m_mark_size=size; } //--- axis properties CAxis *XAxis(void) { return GetPointer(m_x); } CAxis *YAxis(void) { return GetPointer(m_y); } //--- gets the curve history properties int HistoryNameWidth(void) const { return(m_history.name_width); } int HistoryNameSize(void) const { return(m_history.name_size); } int HistorySymbolSize(void) const { return(m_history.symbol_size); } uint HistoryColor(void) const { return(m_history.clr); } //--- sets the curve history properties void HistoryNameWidth(const int width) { m_history.name_width=width; } void HistoryNameSize(const int size) { m_history.name_size=size; } void HistorySymbolSize(const int size) { m_history.symbol_size=size; } void HistoryColor(const uint clr) { m_history.clr=clr; } //--- gets the grid properties uint GridLineColor(void) const { return(m_grid.clr_line); } uint GridAxisLineColor(void) const { return(m_grid.clr_axis_line); } uint GridBackgroundColor(void) const { return(m_grid.clr_background); } int GridCircleRadius(void) const { return(m_grid.r_circle); } uint GridCircleColor(void) const { return(m_grid.clr_circle); } bool GridHasCircle(void) const { return(m_grid.has_circle); } //--- sets the grid properties void GridLineColor(const uint clr) { m_grid.clr_line=clr; } void GridAxisLineColor(const uint clr) { m_grid.clr_axis_line=clr; } void GridBackgroundColor(const uint clr) { m_grid.clr_background=clr; } void GridCircleRadius(const int r) { m_grid.r_circle=r; } void GridCircleColor(const uint clr) { m_grid.clr_circle=clr; } void GridHasCircle(const bool has) { m_grid.has_circle=has; } //--- gets the background properties uint BackgroundColor(void) const { return(m_background.clr); } uint BackgroundMainColor(void) const { return(m_background.clr_main); } uint BackgroundSubColor(void) const { return(m_background.clr_sub); } string BackgroundMain(void) const { return(m_background.main); } string BackgroundSub(void) const { return(m_background.sub); } int BackgroundMainSize(void) const { return(m_background.size_main); } int BackgroundSubSize(void) const { return(m_background.size_sub); } //--- sets the background properties void BackgroundColor(const uint clr) { m_background.clr=clr; } void BackgroundMainColor(const uint clr) { m_background.clr_main=clr; } void BackgroundSubColor(const uint clr) { m_background.clr_sub=clr; } void BackgroundMain(const string main) { m_background.main=main; } void BackgroundSub(const string sub) { m_background.sub=sub; } void BackgroundMainSize(const int size) { m_background.size_main=size; } void BackgroundSubSize(const int size) { m_background.size_sub=size; } //--- create/attach/destroy bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); bool Attach(const long chart_id,const string objname); bool Attach(const long chart_id,const string objname,const int width,const int height); void Destroy(void); //--- main properties string ChartObjectName(void) const { return(m_canvas.ChartObjectName()); } string ResourceName(void) const { return(m_canvas.ResourceName()); } //--- redraw all object on screen bool Redraw(const bool rescale=false); //--- update object on screen void Update(const bool redraw=true); //--- methods for add new curve CCurve *CurveAdd(const double &y[],ENUM_CURVE_TYPE type,const string name=NULL); CCurve *CurveAdd(const double &x[],const double &y[],ENUM_CURVE_TYPE type,const string name=NULL); CCurve *CurveAdd(const CPoint2D &points[],ENUM_CURVE_TYPE type,const string name=NULL); CCurve *CurveAdd(CurveFunction function,const double from,const double to,const double step,ENUM_CURVE_TYPE type,const string name=NULL); CCurve *CurveAdd(const double &x[],const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name=NULL); CCurve *CurveAdd(const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name=NULL); CCurve *CurveAdd(const CPoint2D &points[],const uint clr,ENUM_CURVE_TYPE type,const string name=NULL); CCurve *CurveAdd(CurveFunction function,const double from,const double to,const double step,const uint clr,ENUM_CURVE_TYPE type,const string name=NULL); //--- methods for draw curve bool CurvePlotAll(void); bool CurvePlot(const int index); //--- methods for work with curves int CurvesTotal(void); CCurve *CurveGetByIndex(const int index); CCurve *CurveGetByName(const string name); bool CurveRemoveByIndex(const int index); bool CurveRemoveByName(const string name); //--- methods for add new elements bool MarksToAxisAdd(const double &marks[],const int mark_size,ENUM_MARK_POSITION position,const int dimension=0); void TextAdd(const int x,const int y,const string text,const uint clr,const uint alignment=0); void TextAdd(const CPoint &point,const string text,const uint clr,const uint alignment=0); void LineAdd(const int x1,const int y1,const int x2,const int y2,const uint clr,const uint style); void LineAdd(const CPoint &point1,const CPoint &point2,const uint clr,const uint style); //--- methods for settings text parameters bool FontSet(const string name,const int size,const uint flags=0,const uint angle=0) { return(m_canvas.FontSet(name,size,flags,angle)); } void FontGet(string &name,int &size,uint &flags,uint &angle) { m_canvas.FontGet(name,size,flags,angle); } //--- methods for convert real coordinates to pixel coordinates virtual int ScaleX(double x); virtual int ScaleY(double y); //--- methods for settings internal parameters void SetDefaultParameters(void); void ResetParameters(void); //--- method for calculate max and min values void CalculateMaxMinValues(void); protected: //--- methods for plot curve virtual void CustomPlot(CCurve *curve); virtual void PointsPlot(CCurve *curve); virtual void LinesPlot(CCurve *curve); virtual void PointsAndLinesPlot(CCurve *curve); virtual void StepsPlot(CCurve *curve); virtual void HistogramPlot(CCurve *curve); virtual void TrendLinePlot(CCurve *curve); //--- methods for create graphic elements virtual void CreateWorkspace(void); virtual void CreateGrid(void); virtual void CreateBackground(void); virtual void CreateXName(void); virtual void CreateYName(void); virtual void CreateAxes(void); virtual void CreateHistory(void); //--- methods for calculation internal parameters virtual void CalculateBoundaries(void); virtual void CalculateXAxis(void); virtual void CalculateYAxis(void); //--- services functions static double AxisFactorPrecision(const double min,const double max,const double step); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CGraphic::CGraphic(void) : m_height(0.0),m_width(0.0) { SetDefaultParameters(); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CGraphic::~CGraphic(void) { } //+------------------------------------------------------------------+ //| Crete workspace on graphic | //+------------------------------------------------------------------+ void CGraphic::CreateWorkspace(void) { //--- coordinates int x1 = m_left; int y1 = m_up; int x2 = m_width-m_right; int y2 = m_height-m_down; //--- draw background of workspace m_canvas.FillRectangle(x1+1,y1+1,x2-1,y2-1,m_grid.clr_background); } //+------------------------------------------------------------------+ //| Create grid on graphic | //+------------------------------------------------------------------+ void CGraphic::CreateGrid(void) { int xc0=-1.0; int yc0=-1.0; for(int i=1; i<m_ysize-1; i++) { if(StringToDouble(m_yvalues[i])==0.0) yc0=m_yc[i]; else m_canvas.LineHorizontal(m_left+1,m_width-m_right,m_yc[i],m_grid.clr_line); for(int j=1; j<m_xsize-1; j++) { if(i==1) { if(StringToDouble(m_xvalues[j])==0.0) xc0=m_xc[j]; else m_canvas.LineVertical(m_xc[j],m_height-m_down-1,m_up+1,m_grid.clr_line); } //-- draw circle if(m_grid.has_circle) { m_canvas.FillCircle(m_xc[j],m_yc[i],m_grid.r_circle,m_grid.clr_circle); m_canvas.CircleWu(m_xc[j],m_yc[i],m_grid.r_circle,m_grid.clr_circle); } } } //--- if(yc0>0) m_canvas.LineHorizontal(m_left+1,m_width-m_right,yc0,m_grid.clr_axis_line); if(xc0>0) m_canvas.LineVertical(xc0,m_height-m_down-1,m_up+1,m_grid.clr_axis_line); //--- } //+------------------------------------------------------------------+ //| Create background, main and sub title | //+------------------------------------------------------------------+ void CGraphic::CreateBackground(void) { //--- coordinates int x1 = 0; int y1 = 0; int x2 = m_width; int y2 = m_height; //--- create background m_canvas.FillRectangle(0,0,m_width,m_up-1,m_background.clr); m_canvas.FillRectangle(0,m_height-m_down+1,m_width,m_height,m_background.clr); m_canvas.FillRectangle(0,m_up,m_left-1,m_height-m_down,m_background.clr); m_canvas.FillRectangle(m_width-m_right+1,m_up,m_width,m_height-m_down,m_background.clr); //--- set main title if(m_background.main!=NULL && m_background.size_main!=0) { m_canvas.FontSet("Arial",m_background.size_main,FW_HEAVY); int xc=int((x2+x1-m_canvas.TextWidth(m_background.main))/2.0); int yc=m_up-m_background.size_main-m_gap; m_canvas.TextOut(xc,yc,m_background.main,m_background.clr_main); m_canvas.FontFlagsSet(0); } //--- set sub title if(m_background.sub!=NULL && m_background.size_sub!=0) { m_canvas.FontSet("Arial",m_background.size_sub,FW_MEDIUM); int xc=int((x2+x1-m_canvas.TextWidth(m_background.sub))/2.0); int yc=m_height-m_down+m_mark_size+m_y.ValuesSize()+m_y.NameSize()+m_gap*3; m_canvas.TextOut(xc,yc,m_background.sub,m_background.clr_sub); m_canvas.FontFlagsSet(0); } } //+------------------------------------------------------------------+ //| Create x axis name on graphic | //+------------------------------------------------------------------+ void CGraphic::CreateXName(void) { if(m_x.NameSize()!=0 && m_x.Name()!=NULL) { m_canvas.FontSizeSet(m_x.NameSize()); int yc=m_height-m_down+m_mark_size+m_x.ValuesSize()+m_gap*2; m_canvas.TextOut((int)((m_width-m_canvas.TextWidth(m_x.Name()))/2.0),yc,m_x.Name(),m_x.Color()); } } //+------------------------------------------------------------------+ //| Create y axis name on graphic | //+------------------------------------------------------------------+ void CGraphic::CreateYName(void) { if(m_y.NameSize()!=0 && m_y.Name()!=NULL) { m_canvas.FontSizeSet(m_y.NameSize()); m_canvas.FontAngleSet(900); int xc=m_left-m_y.NameSize()-m_mark_size-m_y.ValuesWidth()-m_gap*2; m_canvas.TextOut(xc,(int)((m_height+m_canvas.TextWidth(m_y.Name()))/2.0),m_y.Name(),m_y.Color()); m_canvas.FontAngleSet(0); } } //+------------------------------------------------------------------+ //| Create axes on graphic | //+------------------------------------------------------------------+ void CGraphic::CreateAxes(void) { //--- int x1=m_left; int x2=m_left-m_mark_size; int y1=m_height-m_down; int y2=m_height-m_down+m_mark_size; //--- create frame m_canvas.Rectangle(m_left,m_up,m_width-m_right,m_height-m_down,m_grid.clr_frame); //--- set font y m_canvas.FontSet(m_y.ValuesFontName(),m_y.ValuesSize(),m_y.ValuesFontFlags(),m_y.ValuesFontAngle()); //--- create y axis for(int i=0; i<m_ysize; i++) { string yvalue=m_yvalues[i]; int yh=m_canvas.TextHeight(yvalue); if(m_canvas.TextWidth(yvalue)>m_y.ValuesWidth()) { if(m_canvas.TextWidth("...")>m_y.ValuesWidth()) { yvalue=NULL; } else { while(m_canvas.TextWidth(yvalue+"...")>m_y.ValuesWidth()) { yvalue=StringSubstr(yvalue,0,StringLen(yvalue)-1); } yvalue+="..."; } } //--- draw mark and set y value int yi_width=m_canvas.TextWidth(yvalue); m_canvas.TextOut(m_left-yi_width-m_mark_size-m_gap,m_yc[i]-yh/2,yvalue,m_y.Color(),TA_LEFT); if(m_mark_size>0.0) m_canvas.LineHorizontal(x1,x2,m_yc[i],m_y.Color()); } //--- set font x m_canvas.FontSet(m_x.ValuesFontName(),m_x.ValuesSize(),m_x.ValuesFontFlags(),m_x.ValuesFontAngle()); //--- create x axis for(int i=0; i<m_xsize; i++) { string xvalue=m_xvalues[i]; int xw=m_canvas.TextWidth(xvalue); //--- draw mark and set y value m_canvas.TextOut(m_xc[i]-xw/2,y2+m_gap,xvalue,m_x.Color()); if(m_mark_size>0.0) m_canvas.LineVertical(m_xc[i],y1,y2,m_x.Color()); } //--- } //+------------------------------------------------------------------+ //| Create graphic | //+------------------------------------------------------------------+ bool CGraphic::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) { //--- check object name if(ObjectFind(chart,name)>=0) return(false); //--- preliminary calculation int width=x2-x1; int height=y2-y1; if(width>0 && height>0) { m_width=width; m_height=height; //--- create object if(!ObjectCreate(chart,name,OBJ_BITMAP_LABEL,subwin,0,0)) return(false); //--- customize object if(!ObjectSetInteger(chart,name,OBJPROP_XDISTANCE,x1) || !ObjectSetInteger(chart,name,OBJPROP_YDISTANCE,y1)) { ObjectDelete(chart,name); return(false); } //--- attach object if(!m_canvas.Attach(chart,name,width,height)) { ObjectDelete(chart,name); return(false); } } //--- success return(true); } //+------------------------------------------------------------------+ //| Attach new object with bitmap resource | //+------------------------------------------------------------------+ bool CGraphic::Attach(const long chart_id,const string objname) { if(m_canvas.Attach(chart_id,objname)) { m_width=m_canvas.Width(); m_height=m_canvas.Height(); //--- success return(true); } //--- failed return(false); } //+------------------------------------------------------------------+ //| Attach new object without bitmap resource | //+------------------------------------------------------------------+ bool CGraphic::Attach(const long chart_id,const string objname,const int width,const int height) { if(m_canvas.Attach(chart_id,objname,width,height)) { m_width=m_canvas.Width(); m_height=m_canvas.Height(); //--- success return(true); } //--- failed return(false); } //+------------------------------------------------------------------+ //| Remove graphic from chart | //+------------------------------------------------------------------+ void CGraphic::Destroy(void) { SetDefaultParameters(); m_generator.Reset(); m_canvas.Destroy(); } //+------------------------------------------------------------------+ //| Add new curve on graphic | //+------------------------------------------------------------------+ CCurve *CGraphic::CurveAdd(const double &y[],ENUM_CURVE_TYPE type,const string name=NULL) { return CurveAdd(y,m_generator.Next(),type,name); } //+------------------------------------------------------------------+ //| Add new curve on graphic | //+------------------------------------------------------------------+ CCurve *CGraphic::CurveAdd(const double &x[],const double &y[],ENUM_CURVE_TYPE type,const string name=NULL) { return CurveAdd(x,y,m_generator.Next(),type,name); } //+------------------------------------------------------------------+ //| Add new curve on graphic | //+------------------------------------------------------------------+ CCurve *CGraphic::CurveAdd(const CPoint2D &points[],ENUM_CURVE_TYPE type,const string name=NULL) { return CurveAdd(points,m_generator.Next(),type,name); } //+------------------------------------------------------------------+ //| Add new curve on graphic | //+------------------------------------------------------------------+ CCurve *CGraphic::CurveAdd(CurveFunction function,const double from,const double to,const double step,ENUM_CURVE_TYPE type,const string name=NULL) { return CurveAdd(function,from,to,step,m_generator.Next(),type,name); } //+------------------------------------------------------------------+ //| Add new curve on graphic | //+------------------------------------------------------------------+ CCurve *CGraphic::CurveAdd(const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name=NULL) { //--- create new curve CCurve *curve=new CCurve(y,clr,type,name); //--- set max and min values if(m_arr_curves.Total()==0) { if(m_x.AutoScale()) { m_x.Max(curve.XMax()); m_x.Min(curve.XMin()); } if(m_y.AutoScale()) { m_y.Max(curve.YMax()); m_y.Min(curve.YMin()); } m_xupdate = true; m_yupdate = true; } else { //--- find max of x if(m_x.Max()<curve.XMax() && m_x.AutoScale()) { m_x.Max(curve.XMax()); m_xupdate=true; } //--- find min of x if(m_x.Min()>curve.XMin() && m_x.AutoScale()) { m_x.Min(curve.XMin()); m_xupdate=true; } //--- find max of y if(m_y.Max()<curve.YMax() && m_y.AutoScale()) { m_y.Max(curve.YMax()); m_yupdate=true; } //--- find min of y if(m_y.Min()>curve.YMin() && m_y.AutoScale()) { m_y.Min(curve.YMin()); m_yupdate=true; } } //--- add curve m_arr_curves.Add(curve); return(curve); } //+------------------------------------------------------------------+ //| Add new curve on graphic | //+------------------------------------------------------------------+ CCurve *CGraphic::CurveAdd(const double &x[],const double &y[],const uint clr,ENUM_CURVE_TYPE type,const string name=NULL) { int xSize = ArraySize(x); int ySize = ArraySize(y); //--- check if(xSize!=ySize) return(NULL); //--- create new curve CCurve *curve=new CCurve(x,y,clr,type,name); //--- set max and min values if(m_arr_curves.Total()==0) { if(m_x.AutoScale()) { m_x.Max(curve.XMax()); m_x.Min(curve.XMin()); } if(m_y.AutoScale()) { m_y.Max(curve.YMax()); m_y.Min(curve.YMin()); } m_xupdate = true; m_yupdate = true; } else { //--- find max of x if(m_x.Max()<curve.XMax() && m_x.AutoScale()) { m_x.Max(curve.XMax()); m_xupdate=true; } //--- find min of x if(m_x.Min()>curve.XMin() && m_x.AutoScale()) { m_x.Min(curve.XMin()); m_xupdate=true; } //--- find max of y if(m_y.Max()<curve.YMax() && m_y.AutoScale()) { m_y.Max(curve.YMax()); m_yupdate=true; } //--- find min of y if(m_y.Min()>curve.YMin() && m_y.AutoScale()) { m_y.Min(curve.YMin()); m_yupdate=true; } } //--- add curve m_arr_curves.Add(curve); return(curve); } //+------------------------------------------------------------------+ //| Add new curve on graphic | //+------------------------------------------------------------------+ CCurve *CGraphic::CurveAdd(const CPoint2D &points[],const uint clr,ENUM_CURVE_TYPE type,const string name=NULL) { //--- create new curve CCurve *curve=new CCurve(points,clr,type,name); //--- set max and min values if(m_arr_curves.Total()==0) { if(m_x.AutoScale()) { m_x.Max(curve.XMax()); m_x.Min(curve.XMin()); } if(m_y.AutoScale()) { m_y.Max(curve.YMax()); m_y.Min(curve.YMin()); } m_xupdate = true; m_yupdate = true; } else { //--- find max of x if(m_x.Max()<curve.XMax() && m_x.AutoScale()) { m_x.Max(curve.XMax()); m_xupdate=true; } //--- find min of x if(m_x.Min()>curve.XMin() && m_x.AutoScale()) { m_x.Min(curve.XMin()); m_xupdate=true; } //--- find max of y if(m_y.Max()<curve.YMax() && m_y.AutoScale()) { m_y.Max(curve.YMax()); m_yupdate=true; } //--- find min of y if(m_y.Min()>curve.YMin() && m_y.AutoScale()) { m_y.Min(curve.YMin()); m_yupdate=true; } } //--- add curve m_arr_curves.Add(curve); return(curve); } //+------------------------------------------------------------------+ //| Add new curve on graphic | //+------------------------------------------------------------------+ CCurve *CGraphic::CurveAdd(CurveFunction function,const double from,const double to,const double step,const uint clr,ENUM_CURVE_TYPE type,const string name=NULL) { //--- check if(from>=to || step<=0 || step>=MathAbs(to-from)) return(NULL); //--- create new curve CCurve *curve=new CCurve(function,from,to,step,clr,type,name); //--- set max and min values if(m_arr_curves.Total()==0) { if(m_x.AutoScale()) { m_x.Max(curve.XMax()); m_x.Min(curve.XMin()); } if(m_y.AutoScale()) { m_y.Max(curve.YMax()); m_y.Min(curve.YMin()); } m_xupdate = true; m_yupdate = true; } else { //--- find max of x if(m_x.Max()<curve.XMax() && m_x.AutoScale()) { m_x.Max(curve.XMax()); m_xupdate=true; } //--- find min of x if(m_x.Min()>curve.XMin() && m_x.AutoScale()) { m_x.Min(curve.XMin()); m_xupdate=true; } //--- find max of y if(m_y.Max()<curve.YMax() && m_y.AutoScale()) { m_y.Max(curve.YMax()); m_yupdate=true; } //--- find min of y if(m_y.Min()>curve.YMin() && m_y.AutoScale()) { m_y.Min(curve.YMin()); m_yupdate=true; } } //--- add curve m_arr_curves.Add(curve); return(curve); } //+------------------------------------------------------------------+ //| Add ticks to current graphic | //+------------------------------------------------------------------+ bool CGraphic::MarksToAxisAdd(const double &marks[],const int mark_size,ENUM_MARK_POSITION position,const int dimension=0) { int originalX=m_left; int originalY=m_height-m_down; //--- check dimension if(dimension==0) { int y1=m_height-m_down; int y2=m_height-m_down; //--- calculate y coordinates for marks switch(position) { case MARK_INTERNAL: y1-=mark_size; break; case MARK_EXTERNAL: y2+=mark_size; break; case MARK_MIDDLE: y1-=mark_size/2; y2+=mark_size/2; break; } //--- draw marks to x axis for(int i=0; i<ArraySize(marks); i++) { int x=originalX+(int)((marks[i]-m_x.Min())*m_dx); m_canvas.LineVertical(x,y1,y2,ColorToARGB(clrBlack)); } } else if(dimension==1) { int x1=m_left; int x2=m_left; //--- calculate x coordinates for marks switch(position) { case MARK_INTERNAL: x2+=mark_size; break; case MARK_EXTERNAL: x1-=mark_size; break; case MARK_MIDDLE: x2+=mark_size/2; x1-=mark_size/2; break; } //--- draw marks to y axis for(int i=0; i<ArraySize(marks); i++) { int y=originalY -(int)((marks[i]-m_y.Min())*m_dy); m_canvas.LineHorizontal(x1,x2,y,ColorToARGB(clrBlack)); } } else return(false); //--- success return(true); } //+------------------------------------------------------------------+ //| Add text to graphic | //+------------------------------------------------------------------+ void CGraphic::TextAdd(const int x,const int y,const string text,const uint clr,const uint alignment=0) { //--- check if(StringLen(text)<1) return; //--- set text m_canvas.TextOut(x,y,text,clr,alignment); } //+------------------------------------------------------------------+ //| Add text to graphic | //+------------------------------------------------------------------+ void CGraphic::TextAdd(const CPoint &point,const string text,const uint clr,const uint alignment=0) { //--- check if(StringLen(text)<1) return; //--- set text m_canvas.TextOut(point.x,point.y,text,clr,alignment); } //+------------------------------------------------------------------+ //| Add line to graphic | //+------------------------------------------------------------------+ void CGraphic::LineAdd(const int x1,const int y1,const int x2,const int y2,const uint clr,const uint style) { m_canvas.LineWu(x1,y1,x2,y2,clr,style); } //+------------------------------------------------------------------+ //| Add line to graphic | //+------------------------------------------------------------------+ void CGraphic::LineAdd(const CPoint &point1,const CPoint &point2,const uint clr,const uint style) { m_canvas.LineWu(point1.x,point1.y,point2.x,point2.y,clr,style); } //+------------------------------------------------------------------+ //| Draws all curves | //+------------------------------------------------------------------+ bool CGraphic::CurvePlotAll(void) { ResetParameters(); CalculateBoundaries(); //--- updare axes if(m_xupdate) CalculateXAxis(); if(m_yupdate) CalculateYAxis(); //--- create workspace and grid CreateWorkspace(); CreateGrid(); //--- draw all curves for(int i=0; i<m_arr_curves.Total(); i++) { //--- gets the curve CCurve *curve=m_arr_curves.At(i); if(!CheckPointer(curve)) return(false); curve.Visible(true); //--- draws depending on the type of curve switch(curve.Type()) { case CURVE_CUSTOM: CustomPlot(curve); break; case CURVE_POINTS: PointsPlot(curve); break; case CURVE_LINES: LinesPlot(curve); break; case CURVE_POINTS_AND_LINES: PointsAndLinesPlot(curve); break; case CURVE_STEPS: StepsPlot(curve); break; case CURVE_HISTOGRAM: HistogramPlot(curve); break; case CURVE_NONE: break; } //--- draw trend line if(curve.TrendLineVisible()) TrendLinePlot(curve); } //--- create background CreateBackground(); //--- create names for axes CreateXName(); CreateYName(); //--- create axes CreateAxes(); //--- create history CreateHistory(); //--- success return(true); } //+------------------------------------------------------------------+ //| Draws a curve by index | //+------------------------------------------------------------------+ bool CGraphic::CurvePlot(const int index) { CCurve *curve=dynamic_cast<CCurve*>(m_arr_curves.At(index)); if(CheckPointer(curve)==POINTER_DYNAMIC) curve.Visible(true); else return(false); //--- ResetParameters(); CalculateBoundaries(); //--- update axes if(m_xupdate) CalculateXAxis(); if(m_yupdate) CalculateYAxis(); //--- create workspace and grid CreateWorkspace(); CreateGrid(); //--- draw all curves for(int i=0; i<m_arr_curves.Total(); i++) { //--- gets the curve curve=dynamic_cast<CCurve*>(m_arr_curves.At(i)); if(CheckPointer(curve)!=POINTER_DYNAMIC) return(false); if(!curve.Visible()) continue; //--- draws depending on the type of curve switch(curve.Type()) { case CURVE_CUSTOM: CustomPlot(curve); break; case CURVE_POINTS: PointsPlot(curve); break; case CURVE_LINES: LinesPlot(curve); break; case CURVE_POINTS_AND_LINES: PointsAndLinesPlot(curve); break; case CURVE_STEPS: StepsPlot(curve); break; case CURVE_HISTOGRAM: HistogramPlot(curve); break; case CURVE_NONE: break; } //--- draw trend line if(curve.TrendLineVisible()) TrendLinePlot(curve); } //--- create background CreateBackground(); //--- create names for axes CreateXName(); CreateYName(); //--- create axes CreateAxes(); //--- create history CreateHistory(); //--- success return(true); } //+------------------------------------------------------------------+ //| Redraw grahic | //+------------------------------------------------------------------+ bool CGraphic::Redraw(const bool rescale=false) { ResetParameters(); CalculateBoundaries(); if(rescale) { CalculateMaxMinValues(); } //--- update axes if(m_xupdate) CalculateXAxis(); if(m_yupdate) CalculateYAxis(); //--- create workspace and grid CreateWorkspace(); CreateGrid(); //--- draw all curves for(int i=0; i<m_arr_curves.Total(); i++) { //--- gets the curve CCurve *curve=dynamic_cast<CCurve*>(m_arr_curves.At(i)); if(CheckPointer(curve)!=POINTER_DYNAMIC) return(false); if(!curve.Visible()) continue; //--- draws depending on the type of curve switch(curve.Type()) { case CURVE_CUSTOM: CustomPlot(curve); break; case CURVE_POINTS: PointsPlot(curve); break; case CURVE_LINES: LinesPlot(curve); break; case CURVE_POINTS_AND_LINES: PointsAndLinesPlot(curve); break; case CURVE_STEPS: StepsPlot(curve); break; case CURVE_HISTOGRAM: HistogramPlot(curve); break; case CURVE_NONE: break; } //--- draw trend line if(curve.TrendLineVisible()) TrendLinePlot(curve); } //--- create background CreateBackground(); //--- create names for axes CreateXName(); CreateYName(); //--- create axes CreateAxes(); //--- create hictory CreateHistory(); //--- success return(true); } //+------------------------------------------------------------------+ //| Update graphic on screen (redraw) | //+------------------------------------------------------------------+ void CGraphic::Update(const bool redraw=true) { m_canvas.Update(redraw); } //+------------------------------------------------------------------+ //| Gets the number of curves on the graphic | //+------------------------------------------------------------------+ int CGraphic::CurvesTotal(void) { return(m_arr_curves.Total()); } //+------------------------------------------------------------------+ //| Gets the curve in the specified index | //+------------------------------------------------------------------+ CCurve *CGraphic::CurveGetByIndex(const int index) { return(m_arr_curves.At(index)); } //+------------------------------------------------------------------+ //| Gets the curve by name | //+------------------------------------------------------------------+ CCurve *CGraphic::CurveGetByName(const string name) { //--- try to find curve by name for(int i=0; i<m_arr_curves.Total(); i++) { CCurve *curve=dynamic_cast<CCurve*>(m_arr_curves.At(i)); if(curve.Name()==name) return(curve); } //--- failed return(NULL); } //+------------------------------------------------------------------+ //| Remove the curve in the specified index | //+------------------------------------------------------------------+ bool CGraphic::CurveRemoveByIndex(const int index) { CCurve *curve=dynamic_cast<CCurve*>(m_arr_curves.Detach(index)); if(CheckPointer(curve)==POINTER_DYNAMIC) { delete curve; return(true); } else { return(false); } } //+------------------------------------------------------------------+ //| Remove the curve by name | //+------------------------------------------------------------------+ bool CGraphic::CurveRemoveByName(const string name) { for(int i=0; i<m_arr_curves.Total(); i++) { CCurve *curve=m_arr_curves.At(i); if(curve.Name()==name) { if(CheckPointer(curve)==POINTER_DYNAMIC) { delete m_arr_curves.Detach(i); return(true); } else { return(false); } } } return(false); } //+------------------------------------------------------------------+ //| Calculate x coordinate in pixels | //+------------------------------------------------------------------+ int CGraphic::ScaleX(const double x) { int xc=m_left+(int)((x-m_x.Min())*m_dx); //--- return x coordinate return(xc); } //+------------------------------------------------------------------+ //| Calculate y coordinate in pixels | //+------------------------------------------------------------------+ int CGraphic::ScaleY(const double y) { int yc=m_height-m_down-(int)((y-m_y.Min())*m_dy); //--- return y coordinate return(yc); } //+------------------------------------------------------------------+ //| Draws a curve custom | //+------------------------------------------------------------------+ void CGraphic::CustomPlot(CCurve *curve) { int size=curve.Size(); double x[],y[]; //--- gets the coordinates of the curve curve.GetX(x); curve.GetY(y); //--- check if(ArraySize(x)==0 || ArraySize(y)==0) return; //--- get and check custom fucntion PlotFucntion plot=curve.CustomPlotFunction(); if(plot==NULL) return; CGraphic *graphic=GetPointer(this); CCanvas *canvas=GetPointer(m_canvas); void *cbdata=curve.CustomPlotCBData(); //--- draw plot(x,y,size,graphic,canvas,cbdata); } //+------------------------------------------------------------------+ //| Draws a curve points | //+------------------------------------------------------------------+ void CGraphic::PointsPlot(CCurve *curve) { int size=curve.Size(); double x[],y[]; //--- gets the coordinates of the curve curve.GetX(x); curve.GetY(y); //--- check if(ArraySize(x)==0 || ArraySize(y)==0) return; //--- check points size if(curve.PointsSize()==0) return; //--- gets the colors uint clr0 = curve.Color(); uint clr1 = curve.PointsColor(); //--- draw for(int i=0; i<size; i++) { //--- check coordinates if(!MathIsValidNumber(x[i]) || !MathIsValidNumber(y[i])) continue; int xc=ScaleX(x[i]); int yc=ScaleY(y[i]); int r=curve.PointsSize()/2; if(r>0) { switch(curve.PointsType()) { case POINT_CIRCLE: { //--- draw fill circle if(curve.PointsFill()) m_canvas.FillCircle(xc,yc,r,clr1); //--- draw circle m_canvas.CircleWu(xc,yc,r,clr0); break; } case POINT_SQUARE: { //--- draw square m_canvas.Rectangle(xc-r,yc-r,xc+r,yc+r,clr0); //--- draw fill square if(curve.PointsFill()) m_canvas.FillRectangle(xc-r+1,yc-r+1,xc+r-1,yc+r-1,clr1); break; } case POINT_DIAMOND: { int xc1=xc+1-r; int yc1=yc; int xc2=xc; int yc2=yc+1-r; //--- draw diamond m_canvas.Line(xc-r,yc,xc,yc-r,clr0); m_canvas.Line(xc,yc-r,xc+r,yc,clr0); m_canvas.Line(xc+r,yc,xc,yc+r,clr0); m_canvas.Line(xc,yc+r,xc-r,yc,clr0); //--- draw fill diamond if(curve.PointsFill()) { int count=(curve.PointsSize()%2==0) ? curve.PointsSize()-1 : curve.PointsSize()-2; for(int j=0; j<count; j++) { m_canvas.Line(xc1,yc1,xc2,yc2,clr1); if(j%2==0) { yc2++; xc1++; } else { xc2++; yc1++; } } } break; } case POINT_TRIANGLE: { //--- draw triangle m_canvas.TriangleWu(xc,yc-r,xc-r,yc+r,xc+r,yc+r,clr0); //--- draw fill triangle if(curve.PointsFill()) { int dy=-r; int dx=0; int count=(curve.PointsSize()%2==0) ? curve.PointsSize()-1 : curve.PointsSize()-2; for(int j=0; j<count; j++, dy++) { m_canvas.LineHorizontal(xc-dx+1,xc+dx,yc+1+dy,clr1); if(j%2==0) dx++; } } break; } case POINT_TRIANGLE_DOWN: { //--- draw down triangle m_canvas.TriangleWu(xc,yc+r,xc-r,yc-r,xc+r,yc-r,clr0); //--- draw fill triangle if(curve.PointsFill()) { int dy=r; int dx=0; int count=(curve.PointsSize()%2==0) ? curve.PointsSize()-1 : curve.PointsSize()-2; for(int j=0; j<count; j++, dy--) { m_canvas.LineHorizontal(xc-dx+1,xc+dx,yc-1+dy,clr1); if(j%2==0) dx++; } } break; } case POINT_X_CROSS: { //--- draw x cross m_canvas.Line(xc+r,yc+r,xc-r,yc-r,clr0); m_canvas.Line(xc-r,yc+r,xc+r,yc-r,clr0); break; } case POINT_PLUS: { //--- draw plus m_canvas.LineHorizontal(xc+r+1,xc-r,yc,clr0); m_canvas.LineVertical(xc,yc+r,yc-r,clr0); break; } case POINT_STAR: { //--- draw plus m_canvas.LineHorizontal(xc+r+1,xc-r,yc,clr0); m_canvas.LineVertical(xc,yc+r,yc-r,clr0); //--- draw x cross m_canvas.Line(xc+r,yc+r,xc-r,yc-r,clr0); m_canvas.Line(xc-r,yc+r,xc+r,yc-r,clr0); break; } case POINT_HORIZONTAL_DASH: { //--- draw horizontal line m_canvas.LineHorizontal(xc+r+1,xc-r,yc,clr0); break; } case POINT_VERTICAL_DASH: { //--- draw vertical line m_canvas.LineVertical(xc,yc+r,yc-r,clr0); break; } } } else { m_canvas.PixelSet(xc,yc,clr0); } } //--- } //+------------------------------------------------------------------+ //| Draws a curve lines | //+------------------------------------------------------------------+ void CGraphic::LinesPlot(CCurve *curve) { int size; double x[],y[]; //--- gets the coordinates of the curve size=curve.Size(); curve.GetX(x); curve.GetY(y); //--- check if(ArraySize(x)==0 || ArraySize(y)==0) return; //--- coordinates int xc[]; int yc[]; int discontinuity[]; //--- find gaps of curve for(int i=0; i<size; i++) { if(!MathIsValidNumber(x[i]) || !MathIsValidNumber(y[i])) { ArrayResize(discontinuity,ArraySize(discontinuity)+1,size); discontinuity[ArraySize(discontinuity)-1]=i; } } //--- get the tension for spline double tension=curve.LinesSmoothTension(); //--- check whether the curve breaks if(ArraySize(discontinuity)==0) { //--- calculate coordinates of curve ArrayResize(xc,size); ArrayResize(yc,size); for(int i=0; i<size; i++) { xc[i]=ScaleX(x[i]); yc[i]=ScaleY(y[i]); } //--- draw curve if(curve.LinesSmooth() && size>2 && tension>0.0 && tension<=1.0) m_canvas.PolylineSmooth(xc,yc,curve.Color(),curve.LinesWidth(),curve.LinesStyle(),curve.LinesEndStyle(),tension,curve.LinesSmoothStep()); else if(size>1) m_canvas.PolylineThick(xc,yc,curve.Color(),curve.LinesWidth(),curve.LinesStyle(),curve.LinesEndStyle()); else if(size==1) m_canvas.PixelSet(xc[0],yc[0],curve.Color()); } else { int index=0; for(int j=0; j<=ArraySize(discontinuity); j++) { double xj[]; double yj[]; int sizej=0; if(j==0) { sizej=discontinuity[0]; ArrayCopy(xj,x,0,0,sizej); ArrayCopy(yj,y,0,0,sizej); } else if(j==ArraySize(discontinuity)) { sizej=size-discontinuity[j-1]-1; ArrayCopy(xj,x,0,discontinuity[j-1]+1,sizej); ArrayCopy(yj,y,0,discontinuity[j-1]+1,sizej); } else { sizej=discontinuity[j]-discontinuity[j-1]-1; ArrayCopy(xj,x,0,discontinuity[j-1]+1,sizej); ArrayCopy(yj,y,0,discontinuity[j-1]+1,sizej); } //--- calculate coordinates path of curve ArrayResize(xc,sizej,size); ArrayResize(yc,sizej,size); for(int i=0; i<sizej; i++) { xc[i]=ScaleX(xj[i]); yc[i]=ScaleY(yj[i]); index++; } //--- draw path of curve if(curve.LinesSmooth() && size>2 && tension>0.0 && tension<=1.0) m_canvas.PolylineSmooth(xc,yc,curve.Color(),curve.LinesWidth(),curve.LinesStyle(),curve.LinesEndStyle(),tension,curve.LinesSmoothStep()); else if(sizej>1) m_canvas.PolylineThick(xc,yc,curve.Color(),curve.LinesWidth(),curve.LinesStyle(),curve.LinesEndStyle()); else if(sizej==1) m_canvas.PixelSet(xc[0],yc[0],curve.Color()); } } } //+------------------------------------------------------------------+ //| Draws a curve points over lines | //+------------------------------------------------------------------+ void CGraphic::PointsAndLinesPlot(CCurve *curve) { LinesPlot(curve); PointsPlot(curve); } //+------------------------------------------------------------------+ //| Draws a curve steps | //+------------------------------------------------------------------+ void CGraphic::StepsPlot(CCurve *curve) { int size=curve.Size(); double x[],y[]; //--- gets the coordinates of the curve curve.GetX(x); curve.GetY(y); //--- coordinates int xc[],yc[]; size=(size*2)-1; ArrayResize(xc,size); ArrayResize(yc,size); int index=0; if(curve.StepsDimension()==0) { //--- x dimension for(int i=0; i<size-1; i+=2,index++) { xc[i]=ScaleX(x[index]); xc[i+1]=ScaleX(x[index+1]); yc[i]=ScaleY(y[index]); yc[i+1]=yc[i]; } } else if(curve.StepsDimension()==1) { //--- y dimension for(int i=0; i<size-1; i+=2,index++) { xc[i]=ScaleX(x[index]); xc[i+1]=xc[i]; yc[i]=ScaleY(y[index]); yc[i+1]=ScaleY(y[index+1]); } } else { //--- unknown dimension return; } //--- general path for x and y dimension xc[size-1]=ScaleX(x[index]); yc[size-1]=ScaleY(y[index]); m_canvas.PolylineWu(xc,yc,curve.Color(),curve.LinesStyle()); } //+------------------------------------------------------------------+ //| Draws a curve histogram | //+------------------------------------------------------------------+ void CGraphic::HistogramPlot(CCurve *curve) { int size=curve.Size(); double x[],y[]; //--- historgram parametrs int histogram_width=curve.HistogramWidth(); //--- check historgram if(histogram_width<=0) return; //--- gets the coordinates of the curve curve.GetX(x); curve.GetY(y); //--- check if(ArraySize(x)==0 || ArraySize(y)==0) return; //--- calculate original of y int originalY=m_height-m_down; int yc0=ScaleY(0.0); //--- gets curve color uint clr=curve.Color(); //--- draw for(int i=0; i<size; i++) { //--- check coordinates if(!MathIsValidNumber(x[i]) || !MathIsValidNumber(y[i])) continue; int xc=ScaleX(x[i]); int yc=ScaleY(y[i]); int xc1 = xc - histogram_width/2; int xc2 = xc + histogram_width/2; int yc1 = yc; int yc2 = (originalY>yc0 && yc0>0) ? yc0 : originalY; //--- if(yc1>yc2) yc2++; else yc2--; //--- m_canvas.FillRectangle(xc1,yc1,xc2,yc2,clr); } //--- } //+------------------------------------------------------------------+ //| Draws a trend line for curve | //+------------------------------------------------------------------+ void CGraphic::TrendLinePlot(CCurve *curve) { //--- simple linear regression double coeff[]; curve.TrendLineCoefficients(coeff); //--- calculate coordinates double x0=curve.XMin(); double x1=curve.XMax(); double y0=coeff[0]*x0+coeff[1]; double y1=coeff[0]*x1+coeff[1]; //--- coordinates in pixels int xc0=ScaleX(x0); int xc1=ScaleX(x1); int yc0=ScaleY(y0); int yc1=ScaleY(y1); uint clr=curve.Color(); //--- draw line m_canvas.LineWu(xc0,yc0,xc1,yc1,curve.TrendLineColor()); } //+------------------------------------------------------------------+ //| Create history of curves in the right side of the graphic | //+------------------------------------------------------------------+ void CGraphic::CreateHistory(void) { for(int i=0; i<m_arr_curves.Total(); i++) { CCurve *curve=dynamic_cast<CCurve*>(m_arr_curves.At(i)); //--- check if(CheckPointer(curve)!=POINTER_DYNAMIC) return; if(!curve.Visible()) continue; //--- calculate y coordinate int yc=m_up+m_history.name_size/2+m_history.name_size*m_history.count_total; //--- gets the curve name string name=curve.Name(); //--- draw symbol switch(curve.Type()) { case CURVE_STEPS: case CURVE_POINTS_AND_LINES: case CURVE_LINES: { //--- coordinates int xc1=m_width-m_right+m_gap; int xc2=m_width-m_right+m_gap+m_history.symbol_size; if(m_history.symbol_size>0) m_canvas.LineWu(xc1,yc,xc2,yc,curve.Color(),curve.LinesStyle()); if(curve.Type()==CURVE_LINES) { if(name==NULL) { name="Lines "+IntegerToString(m_history.count_lines++); curve.Name(name); } break; } else if(curve.Type()==CURVE_STEPS) { if(name==NULL) { name="Steps "+IntegerToString(m_history.count_lines++); curve.Name(name); } break; } } case CURVE_POINTS : { //--- coordinates int xc=m_width-m_right+m_gap+m_history.symbol_size/2; int r=(m_history.symbol_size)/3; if(r>0) { switch(curve.PointsType()) { case POINT_CIRCLE: { //--- draw fill circle if(curve.PointsFill()) m_canvas.FillCircle(xc,yc,r,curve.PointsColor()); //--- draw circle m_canvas.CircleWu(xc,yc,r,curve.Color()); break; } case POINT_SQUARE: { //--- draw square m_canvas.Rectangle(xc-r,yc-r,xc+r,yc+r,curve.Color()); //--- draw fill square if(curve.PointsFill()) m_canvas.FillRectangle(xc-r+1,yc-r+1,xc+r-1,yc+r-1,curve.PointsColor()); break; } case POINT_DIAMOND: { int xc1=xc+1-r; int yc1=yc; int xc2=xc; int yc2=yc+1-r; //--- draw diamond m_canvas.Line(xc-r,yc,xc,yc-r,curve.Color()); m_canvas.Line(xc,yc-r,xc+r,yc,curve.Color()); m_canvas.Line(xc+r,yc,xc,yc+r,curve.Color()); m_canvas.Line(xc,yc+r,xc-r,yc,curve.Color()); //--- draw fill diamond if(curve.PointsFill()) { int count=((r*2)%2==0) ? (r*2)-1 : (r*2)-2; for(int j=0; j<count; j++) { m_canvas.Line(xc1,yc1,xc2,yc2,curve.PointsColor()); if(j%2==0) { yc2++; xc1++; } else { xc2++; yc1++; } } } break; } case POINT_TRIANGLE: { //--- draw triangle m_canvas.TriangleWu(xc,yc-r,xc-r,yc+r,xc+r,yc+r,curve.Color()); //--- draw fill triangle if(curve.PointsFill()) { int dy=-r; int dx=0; int count=((r*2)%2==0) ? (r*2)-1 : (r*2)-2; for(int j=0; j<count; j++, dy++) { m_canvas.LineHorizontal(xc-dx+1,xc+dx,yc+1+dy,curve.PointsColor()); if(j%2==0) dx++; } } break; } case POINT_TRIANGLE_DOWN: { //--- draw down triangle m_canvas.TriangleWu(xc,yc+r,xc-r,yc-r,xc+r,yc-r,curve.Color()); //--- draw fill triangle if(curve.PointsFill()) { int dy=r; int dx=0; int count=((r*2)%2==0) ? (r*2)-1 : (r*2)-2; for(int j=0; j<count; j++, dy--) { m_canvas.LineHorizontal(xc-dx+1,xc+dx,yc-1+dy,curve.PointsColor()); if(j%2==0) dx++; } } break; } case POINT_X_CROSS: { //--- draw x cross m_canvas.Line(xc+r,yc+r,xc-r,yc-r,curve.Color()); m_canvas.Line(xc-r,yc+r,xc+r,yc-r,curve.Color()); break; } case POINT_PLUS: { //--- draw plus m_canvas.LineHorizontal(xc+r+1,xc-r,yc,curve.Color()); m_canvas.LineVertical(xc,yc+r,yc-r,curve.Color()); break; } case POINT_STAR: { //--- draw plus m_canvas.LineHorizontal(xc+r+1,xc-r,yc,curve.Color()); m_canvas.LineVertical(xc,yc+r,yc-r,curve.Color()); //--- draw x cross m_canvas.Line(xc+r,yc+r,xc-r,yc-r,curve.Color()); m_canvas.Line(xc-r,yc+r,xc+r,yc-r,curve.Color()); break; } case POINT_HORIZONTAL_DASH: { //--- draw horizontal line m_canvas.LineHorizontal(xc+r+1,xc-r,yc,curve.Color()); break; } case POINT_VERTICAL_DASH: { //--- draw vertical line m_canvas.LineVertical(xc,yc+r,yc-r,curve.Color()); break; } } } else { if(curve.PointsSize()>0) m_canvas.PixelSet(xc,yc,curve.Color()); } if(curve.Type()==CURVE_POINTS) { if(name==NULL) { name="Points "+IntegerToString(m_history.count_points++); curve.Name(name); } } else if(curve.Type()==CURVE_POINTS_AND_LINES) { if(name==NULL) { name="Points and Lines "+IntegerToString(m_history.count_points++); curve.Name(name); } } break; } case CURVE_HISTOGRAM: { //--- coordinates int xc1=m_width-m_right+m_gap+m_history.symbol_size/6; int yc1=yc-m_history.symbol_size*1/3; int xc2=m_width-m_right+m_gap+(m_history.symbol_size*5)/6; int yc2=yc+m_history.symbol_size*1/3; if(m_history.symbol_size>0) m_canvas.FillRectangle(xc1,yc1,xc2,yc2,curve.Color()); if(name==NULL) { name="Histogram "+IntegerToString(m_history.count_histogram++); curve.Name(name); } break; } case CURVE_CUSTOM: { if(name==NULL) { name="Custom "+IntegerToString(m_history.count_custom++); curve.Name(name); } break; } }; //--- trim the name m_canvas.FontSet("arial",m_history.name_size); if(m_canvas.TextWidth(name)>m_history.name_width) { if(m_canvas.TextWidth("...")>m_history.name_width) { name=NULL; } else { while(m_canvas.TextWidth(name+"...")>m_history.name_width) name=StringSubstr(name,0,StringLen(name)-1); name+="..."; } } //--- coordinates int xct=m_width-m_right+2*m_gap+m_history.symbol_size; int yct=yc-m_history.name_size/2; //--- draw text m_canvas.TextOut(xct,yct,name,m_history.clr); m_history.count_total++; } } //+------------------------------------------------------------------+ //| Reset current parameters on graphic | //+------------------------------------------------------------------+ void CGraphic::SetDefaultParameters(void) { //--- sets the general default values m_xupdate=false; m_yupdate=false; m_xsize=0; m_ysize=0; //--- sets the default values for boundaries m_left0=0; m_right0=5; m_up0=5; m_down0=0; //--- sets the default values for graphic m_mark_size=3; m_gap=4; //--- sets the default values for history m_history.name_width=60; m_history.symbol_size=12; m_history.name_size=12; m_history.count_points=0; m_history.count_lines=0; m_history.count_histogram=0; m_history.count_custom=0; //--- sets the default values for x and y axis m_x.Name(NULL); m_y.Name(NULL); //--- sets the default values for grid m_grid.clr_line=clrWhiteSmoke; m_grid.clr_axis_line=clrSilver; m_grid.clr_frame=clrBlack; m_grid.clr_background=clrWhite; m_grid.r_circle=0; m_grid.clr_circle=clrWhite; m_grid.has_circle=false; //--- sets the default values for background m_background.clr=clrWhite; m_background.clr_main= clrBlack; m_background.clr_sub = clrBlack; m_background.main= NULL; m_background.sub = NULL; m_background.size_main= 0; m_background.size_sub = 0; } //+------------------------------------------------------------------+ //| Reset parametres | //+------------------------------------------------------------------+ void CGraphic::ResetParameters(void) { //--- reset boundaries m_left=m_left0; m_right=m_right0; m_up=m_up0; m_down=m_down0; //--- reset curve of history m_history.count_total=0; } //+------------------------------------------------------------------+ //| Calculate boundaries for workspace | //+------------------------------------------------------------------+ void CGraphic::CalculateBoundaries(void) { if(m_width>0 && m_height>0) { m_right+=m_history.symbol_size+m_history.name_width+3*m_gap; m_up+=m_background.size_main+2*m_gap; m_down+=m_background.size_sub+m_x.ValuesSize()+m_x.NameSize()+4*m_gap; m_left+=m_y.NameSize()+m_mark_size+m_y.ValuesWidth()+4*m_gap; } else { ZeroMemory(m_right); ZeroMemory(m_up); ZeroMemory(m_down); ZeroMemory(m_left); } } //+------------------------------------------------------------------+ //| Calculate the min and max values for both axes on all curves | //+------------------------------------------------------------------+ void CGraphic::CalculateMaxMinValues(void) { int size=m_arr_curves.Total(); double xmax=0.0; double xmin=0.0; double ymax=0.0; double ymin=0.0; if(size>0) { bool valid=false; for(int i=0; i<size; i++) { CCurve *curve=dynamic_cast<CCurve*>(m_arr_curves.At(i)); if(CheckPointer(curve)==POINTER_DYNAMIC) { if(!valid) { xmax = curve.XMax(); xmin = curve.XMin(); ymax = curve.YMax(); ymin = curve.YMin(); valid=true; } else { //--- find max of x if(xmax<curve.XMax()) xmax=curve.XMax(); //--- find min of x if(xmin>curve.XMin()) xmin=curve.XMin(); //--- find max of y if(ymax<curve.YMax()) ymax=curve.YMax(); //--- find min of y if(ymin>curve.YMin()) ymin=curve.YMin(); } } } } if(m_x.AutoScale()) { m_x.Max(xmax); m_x.Min(xmin); } if(m_y.AutoScale()) { m_y.Max(ymax); m_y.Min(ymin); } m_xupdate=true; m_yupdate=true; } //+------------------------------------------------------------------+ //| Calculate coordinates and values for x axis | //+------------------------------------------------------------------+ void CGraphic::CalculateXAxis(void) { //--- m_x.SelectAxisScale(); //--- gets the axis proprties double max = m_x.Max(); double min = m_x.Min(); double step= m_x.Step(); ENUM_AXIS_TYPE xtype=m_x.Type(); string xformat=m_x.ValuesFormat()==NULL ? "%.7g" : m_x.ValuesFormat(); int xmode=m_x.ValuesDateTimeMode(); DoubleToStringFunction xfunc=m_x.ValuesFunctionFormat(); void *xcbdata=m_x.ValuesFunctionFormatCBData(); //--- calculate scaling parameters double xf1=m_left; double xf2=m_width-m_right; //--- double x_size=max-min; double xf_size=xf2-xf1; //--- keep scaling parameters m_dx=xf_size/x_size; //--- calclulate size m_xsize=(int)MathRound((max-min)/step)+1; ArrayResize(m_xc,m_xsize); ArrayResize(m_xvalues,m_xsize); //--- gets the factor precision double factor=AxisFactorPrecision(min,max,step); for(int i=0; i<m_xsize; i++) { double x=min+(i*step); //--- rounding off the calculation error if(factor!=1.0) x=MathRound(x/factor)*factor; if(x>max) x=max; //--- calculate real coordinate if(i==0) m_xc[i]=m_left; else if(i==m_xsize-1) m_xc[i]=m_width-m_right; else m_xc[i]=m_left+(int)((x-min)*m_dx); //--- create values names switch(xtype) { case AXIS_TYPE_DOUBLE: { m_xvalues[i]=StringFormat(xformat,x); break; } case AXIS_TYPE_DATETIME: { m_xvalues[i]=TimeToString((datetime)x,xmode); break; } case AXIS_TYPE_CUSTOM: { m_xvalues[i]=(xfunc==NULL) ? NULL : xfunc(x,xcbdata); break; } }; } //--- m_xupdate=false; } //+------------------------------------------------------------------+ //| Calculate coordinates and values for y axis | //+------------------------------------------------------------------+ void CGraphic::CalculateYAxis(void) { //--- m_y.SelectAxisScale(); //--- gets the axis proprties double max = m_y.Max(); double min = m_y.Min(); double step= m_y.Step(); ENUM_AXIS_TYPE ytype=m_y.Type(); string yformat=m_y.ValuesFormat()==NULL ? "%.7g" : m_y.ValuesFormat(); int ymode=m_y.ValuesDateTimeMode(); DoubleToStringFunction yfunc=m_y.ValuesFunctionFormat(); void *ycbdata=m_y.ValuesFunctionFormatCBData(); //--- calculate scaling parameters double yf1=m_up; double yf2=m_height-m_down; //--- double y_size=max-min; double yf_size=yf2-yf1; //--- keep scaling parameters m_dy=yf_size/y_size; //--- calclulate size m_ysize=(int)MathRound((max-min)/step)+1; ArrayResize(m_yc,m_ysize); ArrayResize(m_yvalues,m_ysize); //--- gets the factor precision double factor=AxisFactorPrecision(min,max,step); for(int i=0; i<m_ysize; i++) { double y=min+(i*step); //--- rounding off the calculation error if(factor!=1.0) y=MathRound(y/factor)*factor; if(y>max) y=max; //--- calculate real coordinate if(i==0) m_yc[i]=m_height-m_down; else if(i==m_ysize-1) m_yc[i]=m_up; else m_yc[i]=m_height-m_down-(int)((y-min)*m_dy); //--- create values names switch(ytype) { case AXIS_TYPE_DOUBLE: { m_yvalues[i]=StringFormat(yformat,y); StringTrimLeft(m_yvalues[i]); StringTrimRight(m_yvalues[i]); break; } case AXIS_TYPE_DATETIME: { m_yvalues[i]=TimeToString((datetime)y,ymode); break; } case AXIS_TYPE_CUSTOM: { m_yvalues[i]=(yfunc==NULL) ? NULL : yfunc(y,ycbdata); break; } }; } //--- m_yupdate=false; } //+------------------------------------------------------------------+ //| Gets the factor precision for calculation error of control values| //| on axis | //+------------------------------------------------------------------+ double CGraphic::AxisFactorPrecision(const double min,const double max,const double step) { static const double big_value=4097.0; //--- create some big values based on control values double big_min=big_value*min; double big_max=big_value*max; double big_step=big_value*step; //--- gets the difference between big values and their control values double delta_min=big_min-min; double delta_max=big_max-max; double delta_step=big_step-step; //--- gets the calculating error of control values double error_min=MathAbs(min-(big_min-delta_min)); double error_max=MathAbs(max-(big_max-delta_max)); double error_step=MathAbs(step-(big_step-delta_step)); //--- get max error double error=MathMax(MathMax(error_min,error_max),error_step); //--- calculate factor double factor=1.0; if(error!=0) { double log10_val=MathLog10(MathAbs(error)); log10_val=(log10_val>0) ? MathCeil(log10_val) : MathFloor(log10_val); if(log10_val<=-308) factor=1e-308; else if(log10_val>=308) factor=1e308; else factor=MathPow(10,log10_val); } return(factor); } //+------------------------------------------------------------------+ //| Create graphic of one curve and return resource name | //+------------------------------------------------------------------+ string GraphPlot(const double &y[],ENUM_CURVE_TYPE type=CURVE_POINTS,string objname=NULL) { CGraphic graphic; ulong width = ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); ulong height= ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); //--- create graphic bool res=false; objname = (objname==NULL) ? "Graphic" : objname; if(ObjectFind(0,objname)>=0) res=graphic.Attach(0,objname); else res=graphic.Create(0,objname,0,65,45,(int)(0.6*width),(int)(0.65*height)); if(!res) return(NULL); //--- add curves graphic.CurveAdd(y,type); //--- plot curves graphic.CurvePlotAll(); graphic.Update(); //--- return resource name return graphic.ChartObjectName(); } //+------------------------------------------------------------------+ //| Create graphic of one curve and return resource name | //+------------------------------------------------------------------+ string GraphPlot(const double &x[],const double &y[],ENUM_CURVE_TYPE type=CURVE_POINTS,string objname=NULL) { CGraphic graphic; ulong width = ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); ulong height= ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); //--- create graphic bool res=false; objname = (objname==NULL) ? "Graphic" : objname; if(ObjectFind(0,objname)>=0) res=graphic.Attach(0,objname); else res=graphic.Create(0,objname,0,65,45,(int)(0.6*width),(int)(0.65*height)); if(!res) return(NULL); //--- add curves graphic.CurveAdd(x,y,type); //--- plot curves graphic.CurvePlotAll(); graphic.Update(); //--- return resource name return graphic.ChartObjectName(); } //+------------------------------------------------------------------+ //| Create graphic of two curve and return resource name | //+------------------------------------------------------------------+ string GraphPlot(const double &x1[],const double &y1[],const double &x2[],const double &y2[],ENUM_CURVE_TYPE type=CURVE_POINTS,string objname=NULL) { CGraphic graphic; ulong width = ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); ulong height= ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); //--- create graphic bool res=false; objname = (objname==NULL) ? "Graphic" : objname; if(ObjectFind(0,objname)>=0) res=graphic.Attach(0,objname); else res=graphic.Create(0,objname,0,65,45,(int)(0.6*width),(int)(0.65*height)); if(!res) return(NULL); //--- add curves graphic.CurveAdd(x1,y1,type); graphic.CurveAdd(x2,y2,type); //--- plot curves graphic.CurvePlotAll(); graphic.Update(); //--- return resource name return graphic.ChartObjectName(); } //+------------------------------------------------------------------+ //| Create graphic of three curve and return resource name | //+------------------------------------------------------------------+ string GraphPlot(const double &x1[],const double &y1[],const double &x2[],const double &y2[],const double &x3[],const double &y3[],ENUM_CURVE_TYPE type=CURVE_POINTS,string objname=NULL) { CGraphic graphic; ulong width = ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); ulong height= ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); //--- create graphic bool res=false; objname = (objname==NULL) ? "Graphic" : objname; if(ObjectFind(0,objname)>=0) res=graphic.Attach(0,objname); else res=graphic.Create(0,objname,0,65,45,(int)(0.6*width),(int)(0.65*height)); if(!res) return(NULL); //--- add curves graphic.CurveAdd(x1,y1,type); graphic.CurveAdd(x2,y2,type); graphic.CurveAdd(x3,y3,type); //--- plot curves graphic.CurvePlotAll(); graphic.Update(); //--- return resource name return graphic.ChartObjectName(); } //+------------------------------------------------------------------+ //| Create graphic of one curve and return resource name | //+------------------------------------------------------------------+ string GraphPlot(const CPoint2D &points[],ENUM_CURVE_TYPE type=CURVE_POINTS,string objname=NULL) { CGraphic graphic; ulong width = ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); ulong height= ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); //--- create graphic bool res=false; objname = (objname==NULL) ? "Graphic" : objname; if(ObjectFind(0,objname)>=0) res=graphic.Attach(0,objname); else res=graphic.Create(0,objname,0,65,45,(int)(0.6*width),(int)(0.65*height)); if(!res) return(NULL); //--- add curves graphic.CurveAdd(points,type); //--- plot curves graphic.CurvePlotAll(); graphic.Update(); //--- return resource name return graphic.ChartObjectName(); } //+------------------------------------------------------------------+ //| Create graphic of two curve and return resource name | //+------------------------------------------------------------------+ string GraphPlot(const CPoint2D &points1[],const CPoint2D &points2[],ENUM_CURVE_TYPE type=CURVE_POINTS,string objname=NULL) { CGraphic graphic; ulong width = ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); ulong height= ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); //--- create graphic bool res=false; objname = (objname==NULL) ? "Graphic" : objname; if(ObjectFind(0,objname)>=0) res=graphic.Attach(0,objname); else res=graphic.Create(0,objname,0,65,45,(int)(0.6*width),(int)(0.65*height)); if(!res) return(NULL); //--- add curves graphic.CurveAdd(points1,type); graphic.CurveAdd(points2,type); //--- plot curves graphic.CurvePlotAll(); graphic.Update(); //--- return resource name return graphic.ChartObjectName(); } //+------------------------------------------------------------------+ //| Create graphic of three curve and return resource name | //+------------------------------------------------------------------+ string GraphPlot(const CPoint2D &points1[],const CPoint2D &points2[],const CPoint2D &points3[],ENUM_CURVE_TYPE type=CURVE_POINTS,string objname=NULL) { CGraphic graphic; ulong width = ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); ulong height= ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); //--- create graphic bool res=false; objname = (objname==NULL) ? "Graphic" : objname; if(ObjectFind(0,objname)>=0) res=graphic.Attach(0,objname); else res=graphic.Create(0,objname,0,65,45,(int)(0.6*width),(int)(0.65*height)); if(!res) return(NULL); //--- add curves graphic.CurveAdd(points1,type); graphic.CurveAdd(points2,type); graphic.CurveAdd(points3,type); //--- plot curves graphic.CurvePlotAll(); graphic.Update(); //--- return resource name return graphic.ChartObjectName(); } //+------------------------------------------------------------------+ //| Create graphic of one curve and return resource name | //+------------------------------------------------------------------+ string GraphPlot(CurveFunction function,const double from,const double to,const double step,ENUM_CURVE_TYPE type=CURVE_POINTS,string objname=NULL) { CGraphic graphic; ulong width = ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); ulong height= ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); //--- create graphic bool res=false; objname = (objname==NULL) ? "Graphic" : objname; if(ObjectFind(0,objname)>=0) res=graphic.Attach(0,objname); else res=graphic.Create(0,objname,0,65,45,(int)(0.6*width),(int)(0.65*height)); if(!res) return(NULL); //--- add curves graphic.CurveAdd(function,from,to,step,type); //--- plot curves graphic.CurvePlotAll(); graphic.Update(); //--- return resource name return graphic.ChartObjectName(); } //+------------------------------------------------------------------+ //| Create graphic of two curve and return resource name | //+------------------------------------------------------------------+ string GraphPlot(CurveFunction function1,CurveFunction function2,const double from,const double to,const double step,ENUM_CURVE_TYPE type=CURVE_POINTS,string objname=NULL) { CGraphic graphic; ulong width = ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); ulong height= ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); //--- create graphic bool res=false; objname = (objname==NULL) ? "Graphic" : objname; if(ObjectFind(0,objname)>=0) res=graphic.Attach(0,objname); else res=graphic.Create(0,objname,0,65,45,(int)(0.6*width),(int)(0.65*height)); if(!res) return(NULL); //--- add curves graphic.CurveAdd(function1,from,to,step,type); graphic.CurveAdd(function2,from,to,step,type); //--- plot curves graphic.CurvePlotAll(); graphic.Update(); //--- return resource name return graphic.ChartObjectName(); } //+------------------------------------------------------------------+ //| Create graphic of three curve and return resource name | //+------------------------------------------------------------------+ string GraphPlot(CurveFunction function1,CurveFunction function2,CurveFunction function3,const double from,const double to,const double step,ENUM_CURVE_TYPE type=CURVE_POINTS,string objname=NULL) { CGraphic graphic; ulong width = ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); ulong height= ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); //--- create graphic bool res=false; objname = (objname==NULL) ? "Graphic" : objname; if(ObjectFind(0,objname)>=0) res=graphic.Attach(0,objname); else res=graphic.Create(0,objname,0,65,45,(int)(0.6*width),(int)(0.65*height)); if(!res) return(NULL); //--- add curves graphic.CurveAdd(function1,from,to,step,type); graphic.CurveAdd(function2,from,to,step,type); graphic.CurveAdd(function3,from,to,step,type); //--- plot curves graphic.CurvePlotAll(); graphic.Update(); //--- return resource name return graphic.ChartObjectName(); } //+------------------------------------------------------------------+