Canvas is cool!

 

I set myself a task: to demonstrate the capabilities of custom graphics via CCanvas class in a short code.

Here's what came out of it.

This script works in both MQL5 and MQL4. But it is much faster on MT5.

Each frame is unique and does not repeat, i.e. the script is not cyclic.

#include <Canvas\Canvas.mqh>

void OnStart()
  {
   ChartSetInteger(0,CHART_FOREGROUND,true);
   CCanvas C;
   int Width=(ushort)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);  // получаем Ширину окна
   int Height=(ushort)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); // получаем Высоту окна
   if(!C.CreateBitmapLabel(0,0,"CanvasExamlple",0,0,Width,Height,COLOR_FORMAT_XRGB_NOALPHA)) // создаем канвас размером текущего окна
   Print("Error creating canvas: ",GetLastError()); 
   uint i=0,j=100000;
   int size=Width*Height;
   uchar h[25600];
   for (int w=0;w<25600;w++) 
   h[w]= uchar(128+128*sin(double(w)/256));//создаем массив для ускорения работы
   double X1=0,Y1=0,X2=0,Y2=0;
   while(!IsStopped())
     {
      int pos=int(i%size);
      if(pos==0)
        {
         C.Update();
         //Sleep(30);
         X1= Width-(sin((double)j/100)*(double)Width);
         Y1= Height-(cos((double)j/140)*(double)Height);
         X2= Width+(cos((double)j/80)*(double)Width);
         Y2= Height+(sin((double)j/20)*(double)Height);
         j++;
        }
      int X=pos%Width;
      int Y=int(pos/Width);
      double d= ((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y))/(((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y))+((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y)));
      C.m_pixels[pos]=XRGB(h[int(d*11520)],h[int(d*17920)],h[int(d*6400)]);
      i++;
     }
   C.Destroy();
  }


Before compiling, move array m_pixels[] from protected: to public in Canvas.mqh:

public:
   uint              m_pixels[];               // array of pixels

                     CCanvas(void);
                    ~CCanvas(void);
Files:
Swirl.mq5  3 kb
Swirl.ex5  16 kb
 

Cool, for sure!

And can even be used for useful things ;)

 
Andrey Khatimlianskii:

Cool, for sure!

And can even be used for useful things ;)

For people to start using Kanvas for useful things, you need to start by showing useless things. :))

 
Nikolai Semko:

You need to move array m_pixels[] from protected: to public in Canvas.mqh file before compilation:

You don't need to change anything in the SB.

class CCanvas2 : public CCanvas
{
private:
  int Pos;

public:
  CCanvas2* operator []( const int iPos )
  {
    this.Pos = iPos;
    
    return(&this);
  }
  
  void operator =( const uint Color )
  {
    this.m_pixels[this.Pos] = Color;
  }
};


CCanvas2 C;
//..
// C.m_pixels[pos]=XRGB(h[int(d*11520)],h[int(d*17920)],h[int(d*6400)]);
C[pos]=XRGB(h[int(d*11520)],h[int(d*17920)],h[int(d*6400)]);
 
fxsaber:

You don't have to change anything in the SB.


Cool! :))

But unfortunately, it's not free.

Checked it out. Overall slowdown on MT5 was ~11%

 
Nikolai Semko:

Cool! :))

But unfortunately, it's not free.

Checked it out. Total slowdown on MT5 was ~11%.

Your case uses 1% from CCanvas. Try it without CCanvas. The code won't be the least bit more complicated and the speed will improve even more.

 
fxsaber:

In your case, 1% is used from CCanvas. Try it without CCanvas. The code will not be the least bit more complicated and the speed will increase even more.

Of course, you can do without CCanvas class as well. But the code will increase, while the processing speed will not get any better, since all I actually use from CCanvas class is m_pixels[] array of graphic resource pixels (and Update() and Destroy() functions, but they will not be of any use, and we'll barely save money on them).

But an array is still an array. How can you make it faster? You can't. Just CCanvas class takes care of some routine, when you create a resource, update it (or rather recreate it) and delete it.

Or are you saying that C.m_pixels[] doesn't compile as direct array access? I think it's direct. Without any intermediate gestures. Or am I wrong?

It would be even more logical for the developers of this class to shove the CreateBitmapLabel into the class constructor itself to avoid looming. If you create a new instance of the class without parameters, then you create a canvas with the size in the window (as in my case), and if you want, you can specify parameters when creating an instance of the class. I did it that way myself.

 
Nikolai Semko:

Of course, I could do without CCanvas class. But the code will increase, but there will be no gain in speed, because all I use from CCanvas class is graphical resource array m_pixels[] (and Update() and Destroy() functions, but you can neglect them, because they will not save money).

But an array is still an array. How can you make it faster? You can't. Just CCanvas class takes care of some routine, when you create a resource, update it (or rather recreate it) and delete it.

Or are you saying that C.m_pixels[] doesn't compile as direct array access? I think it's direct. Without any intermediate gestures. Or am I mistaken?

CCanvas is a wrapper for ResourceCreate. So, for example, you have 20 ready-made images in the form of arrays. If you want to change them via canvas, you will have to do expensive ArrayCopy+Update.

And if you do it without CCanvas, you will need ResourceCreate+ChartRerdraw only. I've posted several dynamic drawing jobs in kodobase. It was obvious there that CCanvas is no good.

 
Nikolai Semko:

You need to move array m_pixels[] from protected: to public in Canvas.mqh file before compiling:

Are you sure PixelSet won't help?

 
Rashid Umarov:

Are you sure PixelSet won't help?

Of course, it will help, but it will be terribly slow. First, a function call is not free, because parameters are passed and stored (in PixelSet, this isn't even done by reference), all registers must be shoved onto the stack and then pulled out again. Secondly, the function itself checks whether X and Y fall into the specified range, and thirdly, it calculates the array index. And I don't need all this because I already have an index and in my algorithm I can't get out of range.

 
Cool rainbow chart! I'd also like to make the candles dance to the music and twist with each other!