mql-for-begginers/Include/Graphics/Graphic.mqh
2025-07-22 18:30:17 +03:00

2384 lines
No EOL
169 KiB
MQL5

//+------------------------------------------------------------------+
//| CGraphic.mqh |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://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;
};
//+------------------------------------------------------------------+
//| 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); }
//--- 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; }
//--- 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,ColorToARGB(clrBlack),TA_LEFT);
if(m_mark_size>0.0)
m_canvas.LineHorizontal(x1,x2,m_yc[i],ColorToARGB(clrBlack));
}
//--- 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,ColorToARGB(clrBlack));
if(m_mark_size>0.0)
m_canvas.LineVertical(m_xc[i],y1,y2,ColorToARGB(clrBlack));
}
//---
}
//+------------------------------------------------------------------+
//| 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,ColorToARGB(clrBlack));
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();
}
//+------------------------------------------------------------------+