2384 lines
No EOL
169 KiB
MQL5
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();
|
|
}
|
|
//+------------------------------------------------------------------+ |