Ecere SDK/eC Forums
https://ecere.org/community/
Print view

Ecere DLL update - class Circle
https://ecere.org/community/viewtopic.php?f=5&t=238
Page 1 of 1
Author:  D.Bane [ Fri Jul 20, 2012 6:52 am ]
Post subject:  Ecere DLL update - class Circle

Hi,

I wanted to do this on Git, but I can not download anything at the moment (for some time, who knows for how long :/) so it is easier to copy paste it here, I hope you do not mind :)

I personally really like the option of having a Circular button but, not the one that will 'shine' when you are inside of its box, but the one that follows its lines - if you like that same thing then this code should help.

Ecere.dll/src/sys/units.ec

Code: Select all

public enum CircleBorder { outsideBevel, insideBevel };

public struct Circle
{
   CircleBorder borderType;
      borderType = outsideBevel;
   //Point center;
   int cX, cY;
   int radius;
   int borderSize;
      borderSize = 1;

   property int borderSize
   {
      get { return borderSize; }
      set
      {
         if(value < 1)  { borderSize = 1; }
         else           { borderSize = value; }
      }
   }

   property int leftMostPoint
   {
      get { return cX - radius; }
   }

   property int topMostPoint
   {
      get { return cY - radius; }
   }

   property int rightMostPoint
   {
      get { return cX + radius; }
   }

   property int bottomMostPoint
   {
      get { return cY + radius; }
   }

   public bool isPointInside(Point point, bool countOnBorder)
   {
      float gps; //it can be int (will function properly, but will give warning).
      int nrad;
      int rMin, rMax;

      nrad = radius * -1;

      //Some faster calculations to speed things up..
      if( (point.y - cY) < nrad || (point.y - cY) > radius)
         { return false; }
      if((point.x-cX) < nrad || (point.x-cX) > radius)
         { return false; }

      gps = fastSqrt((point.x-cX)*(point.x-cX) + (point.y-cY)*(point.y-cY));

      if(borderType == insideBevel)
      {
         rMin = radius - borderSize;
         rMax = radius;
      }
      else // borderType == outsideBevel
      {
         rMin = radius;
         rMax = radius + borderSize;
      }

      if(gps < radius)
      {
         //The point is inside of a circle
         return true;
      }
      else if(gps == radius || (gps > rMin && gps < rMax) )
      {
         //The point is on the border
         if(countOnBorder) { return true; }
      }
      //Else - The point is not in the circle nor on the border (or the border is not included)
      return false;
   }

   //Other functions found in Box struct
   //-----------------------------------------------------------------
   //Check what these do for box and if applicable...
   void ClipOffset(Circle against, int x, int y)
   {
   }
   void Clip(Circle against)
   {
   }

   bool Overlap(Circle circle)
   {
      if( leftMostPoint < circle.rightMostPoint && rightMostPoint > circle.leftMostPoint && topMostPoint < circle.bottomMostPoint && bottomMostPoint > circle.topMostPoint)
      {
         //It is inside of the circle's `box` so it should be studied more carefully if it is
         // trully overlaping or not...
         float overlap; //it can be int (will function properly, but will give warning).
         int rad;
         float h, w;

         w = cX - circle.cX;
         h = cY - circle.cY;

         overlap = fastSqrt((w*w)+(h*h));

         rad = radius + circle.radius;

         if(overlap < rad) { return true; }
      }

      return false;
   }
};
I did a bit of research and this seems like a very fast algorithm for squareRoot (faster being done in asm) - the link is included to the most valuable source - at least that I think. So all the thanks/reps, etc. go to the person that spent a lot of time finding these algorithms..

Code: Select all

private float fastSqrt(float x)  
{
   //http://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi
   //Method number 1
   union
   {
      int i;
      float x;
   } u;

   u.x = x;
   u.i = (1<<29) + (u.i >> 1) - (1<<22); 

   // Two Babylonian Steps (simplified from:)
   // u.x = 0.5f * (u.x + x/u.x);
   // u.x = 0.5f * (u.x + x/u.x);
   u.x = u.x + x/u.x;
   u.x = 0.25f*u.x + x/u.x;

   return u.x;
}
Now we need to add some other code that will allow us to draw the circle when in OnRedraw or when we have the surface of any object...

Ecere.dll/src/gfx/Surface.ec

Code: Select all

void DrawCircle(Circle circle)
   {
      ColorAlpha color[2];

      color[0] = black;
      color[1] = black;
      DrawCircleF(circle.cX, circle.cY, circle.radius, emptyCircle, color, circle.borderSize, circle.borderType);
   }

   void DrawCircleF(int x0, int y0, int radius, CircleType circleType, ColorAlpha color[2], int borderSize, CircleBorder borderStyle )
   {
      int f, fX, fY, x, y;

      f = 1 - radius;
      fX = 1;
      fY = -2 * radius;
      x = 0;
      y = radius;

      //Put the dot in the center of the circle
      //SetForeground(red);
      //driver.PutPixel(display, this, x0,y0);

      //The border should always be drawn, not only if empty, as that way you can have
      // only line drawn, full color circle and colored circle with borders
      // this might not be wanted for circle if angles only

      //Draw borders
      SetForeground(color[0]);
      driver.PutPixel(display, this, x0, y0 + radius);
      driver.PutPixel(display, this, x0, y0 - radius);

      //circle dots on the X axis on both sides of circle
      driver.PutPixel(display, this, x0 + radius, y0);
      driver.PutPixel(display, this, x0 - radius, y0);

      if(circleType == fullCircle)
      {
         SetForeground(color[1]);
         driver.DrawLine(display, this, x0, y0 + radius, x0, y0 - radius);
         driver.DrawLine(display, this, x0 + radius, y0, x0 - radius+1, y0);
      }

      while(x < y)
      {
         // fX == 2 * x + 1;
         // fY == -2 * y;
         // f == x*x + y*y - radius*radius + 2*x - y + 1;
         if(f >= 0) 
         {
            y--;
            fY += 2;
            f += fY;
         }

         x++;
         fX += 2;
         f += fX;

         //Draw other dots... each line representing one sector...
         if(circleType == emptyCircle) //only border is shown
         {
            driver.PutPixel(display, this, x0 + x, y0 + y);
            driver.PutPixel(display, this, x0 - x, y0 + y);
            driver.PutPixel(display, this, x0 + x, y0 - y);
            driver.PutPixel(display, this, x0 - x, y0 - y);
            driver.PutPixel(display, this, x0 + y, y0 + x);
            driver.PutPixel(display, this, x0 - y, y0 + x);
            driver.PutPixel(display, this, x0 + y, y0 - x);
            driver.PutPixel(display, this, x0 - y, y0 - x);
         }
         else if(circleType == fullCircle) //everything is filled up..
         {
            driver.DrawLine(display, this, x0 + x, y0 + y, x0 - x, y0 + y);
            driver.DrawLine(display, this, x0 + x, y0 - y, x0 - x, y0 - y);
            driver.DrawLine(display, this, x0 + y, y0 + x, x0 - y, y0 + x);
            driver.DrawLine(display, this, x0 + y, y0 - x, x0 - y, y0 - x);
         }
      }

      if(borderSize > 1)
      {
         if(borderStyle == insideBevel)
         {
            DrawCircleF(x0, y0, radius-1, circleType, color, borderSize-1, borderStyle );
         }
         else
         {
            DrawCircleF(x0, y0, radius+1, circleType, color, borderSize-1, borderStyle );
         }
      }
   }
Here are two examples of how it might work...

form1-basic.ec

Code: Select all

import "ecere"

class Form1 : Window
{
   caption = "Form1";
   background = formColor;
   borderStyle = sizable;
   hasMaximize = true;
   hasMinimize = true;
   hasClose = true;
   clientSize = { 632, 438 };

   //Lets add few circles
   Circle c1 {borderSize = 1;borderType = outsideBevel; cX = 270; cY = 65; radius = 38; };
   Circle c2 {borderSize = 1;borderType = outsideBevel; cX = 102; cY = 83; radius = 150; };
   Circle c3 {borderSize = 1;borderType = outsideBevel; cX = 321; cY = 130; radius = 50; };

   // The Clip() functions that work for the box are not done
   // The filled angles will be available at some other time, but the idea was to have the
   //  possibility of pie chart if it was needed, but it should be based on angles and I have
   //  some other idea in mind for that so will see what will happen - it might end up transferred to
   //  some other class instead...

   void OnRedraw(Surface surface)
   {
      ColorAlpha colors[2];
      ColorAlpha colors2[2];

      colors[0] = black; //border color
      colors[1] = red; //background color

      colors2[0] = blue;
      colors2[1] = green;

      //Lets draw these circles
      surface.DrawCircle(c1); //A quick way to draw them, which does not give you a lot of
                              // room to do anything with it
      //surface.DrawCircleF(x0,y0,radius,curcleType,color[2],borderSize,borderStyle);
      surface.DrawCircleF(c2.cX,c2.cY,c2.radius,fullCircle,colors,c2.borderSize,c2.borderType);
      surface.DrawCircleF(c3.cX,c3.cY,c3.radius,fullCircle,colors2,c3.borderSize,c3.borderType);
   }

   //Lets see what we can do with this...

   bool OnLeftButtonDown(int x, int y, Modifiers mods)
   {
      bool tc1, tc2, tc3;
      String msg;

      msg = "The click happened outside of any circle"; //default value

      tc1 = c1.isPointInside({x,y},true); // Sometimes you want the border to be considered as the
                                    // part of the circle, then you say true, but if you do not want
                                    // to have border included in the calculations then just put
                                    // false and it will not be counted
      tc2 = c2.isPointInside({x,y},false);
      tc3 = c3.isPointInside({x,y},true);

      if(tc1)  { msg = "the 'c1' circle was hit"; }
      else if(tc2) { msg = "the 'c2' circle was hit"; }
      else if(tc3) { msg = "the 'c3' circle was hit"; }

      MessageBox {this, text = "results", contents = msg}.Modal();

      return true;
   }

   bool OnRightButtonDown(int x, int y, Modifiers mods)
   {
      //Lets see if the circles are overlapping each other...
      if(c1.Overlap(c2))
      {
         MessageBox {this, text = "results", contents = "c1 and c2 overlap"}.Modal();
      }
      if(c1.Overlap(c3))
      {
         MessageBox {this, text = "results", contents = "c1 and c3 overlap"}.Modal();
      }
      if(c2.Overlap(c3))
      {
         MessageBox {this, text = "results", contents = "c2 and c3 overlap"}.Modal();
      }
      return true;
   }

}

Form1 form1 {};
form1-bitmorecomplex.ec

Code: Select all

import "ecere"

class Form1 : Window
{
   caption = "Form1";
   background = formColor;
   borderStyle = sizable;
   hasMaximize = true;
   hasMinimize = true;
   hasClose = true;
   clientSize = { 632, 438 };

   //Lets add few circles
   Circle c1 {borderSize = 1;borderType = outsideBevel; cX = 270; cY = 65; radius = 38; };
   Circle c2 {borderSize = 1;borderType = outsideBevel; cX = 102; cY = 83; radius = 150; };
   Circle c3 {borderSize = 1;borderType = outsideBevel; cX = 321; cY = 130; radius = 50; };

   //Lets do something more with it..
   bool c1Inside, c2Inside, c3Inside;
   c1Inside = false;
   c2Inside = false;
   c3Inside = false;

   // The Clip() functions that work for the box are not done
   // The filled angles will be available at some other time, but the idea was to have the
   //  possibility of pie chart if it was needed, but it should be based on angles and I have
   //  some other idea in mind for that so will see what will happen - it might end up transferred to
   //  some other class instead...

   void OnRedraw(Surface surface)
   {
      ColorAlpha colors[2];
      ColorAlpha colors2[2];
      ColorAlpha colorsO[2];
      ColorAlpha colors2O[2];

      //Normal colors
      colors[0] = black;
      colors[1] = red;
      colors2[0] = blue;
      colors2[1] = green;

      //Over
      colorsO[0] = white;
      colorsO[1] = yellow;
      colors2O[0] = red;
      colors2O[1] = brown;

      //Lets draw these circles
      if(c1Inside)
      {
         surface.DrawCircleF(c1.cX,c1.cY,c1.radius,fullCircle,colorsO,c1.borderSize,c1.borderType);
      }
      else
      {
         surface.DrawCircle(c1); //A quick way to draw them, which does not give you a lot of
                                 // room to do anything with it
      }
      //surface.DrawCircleF(x0,y0,radius,curcleType,color[2],borderSize,borderStyle);
      if(c2Inside)
      {
         surface.DrawCircleF(c2.cX,c2.cY,c2.radius,fullCircle,colors2O,c2.borderSize,c2.borderType);
      }
      else
      {
         surface.DrawCircleF(c2.cX,c2.cY,c2.radius,fullCircle,colors,c2.borderSize,c2.borderType);
      }
      
      if(c3Inside)
      {
         surface.DrawCircle(c3);
      }
      else
      {
         surface.DrawCircleF(c3.cX,c3.cY,c3.radius,fullCircle,colors2,c3.borderSize,c3.borderType);
      }
   }

   //Lets see what we can do with this...

   bool OnMouseMove(int x, int y, Modifiers mods)
   {
      c1Inside = false;
      c2Inside = false;
      c3Inside = false;

      if(c1.isPointInside({x,y},true)) { c1Inside = true; }
      if(c2.isPointInside({x,y},true)) { c2Inside = true; }
      if(c3.isPointInside({x,y},true)) { c3Inside = true; }

      Update(null);
      return true;
   }


   bool OnLeftButtonDown(int x, int y, Modifiers mods)
   {
      bool tc1, tc2, tc3;
      String msg;

      msg = "The click happened outside of any circle"; //default value

      tc1 = c1.isPointInside({x,y},true); // Sometimes you want the border to be considered as the
                                    // part of the circle, then you say true, but if you do not want
                                    // to have border included in the calculations then just put
                                    // false and it will not be counted
      tc2 = c2.isPointInside({x,y},false);
      tc3 = c3.isPointInside({x,y},true);

      if(tc1)  { msg = "the 'c1' circle was hit"; }
      else if(tc2) { msg = "the 'c2' circle was hit"; }
      else if(tc3) { msg = "the 'c3' circle was hit"; }

      MessageBox {this, text = "results", contents = msg}.Modal();

      return true;
   }

   bool OnRightButtonDown(int x, int y, Modifiers mods)
   {
      //Lets see if the circles are overlapping each other...
      if(c1.Overlap(c2))
      {
         MessageBox {this, text = "results", contents = "c1 and c2 overlap"}.Modal();
      }
      if(c1.Overlap(c3))
      {
         MessageBox {this, text = "results", contents = "c1 and c3 overlap"}.Modal();
      }
      if(c2.Overlap(c3))
      {
         MessageBox {this, text = "results", contents = "c2 and c3 overlap"}.Modal();
      }
      return true;
   }

}

Form1 form1 {};
I hope someone will like the code and that it will be useful.

All the best to you all,
D.Bane.
Author:  jerome [ Fri Jul 20, 2012 1:43 pm ]
Post subject:  Re: Ecere DLL update - class Circle

Hi D.Bane!

Thanks for sharing with us those circles :)

I put all this code together in one simple file outside of libecere for those who would like to try it quickly. It was missing the CircleType enum which I added. Both versions of the forms will show up.

Code: Select all

public import "ecere"
 
public enum CircleBorder { outsideBevel, insideBevel };
public enum CircleType { emptyCircle, fullCircle };
 
public struct Circle
{
   CircleBorder borderType;
      borderType = outsideBevel;
   //Point center;
   int cX, cY;
   int radius;
   int borderSize;
      borderSize = 1;
 
   property int borderSize
   {
      get { return borderSize; }
      set
      {
         if(value < 1)  { borderSize = 1; }
         else           { borderSize = value; }
      }
   }
 
   property int leftMostPoint
   {
      get { return cX - radius; }
   }
 
   property int topMostPoint
   {
      get { return cY - radius; }
   }
 
   property int rightMostPoint
   {
      get { return cX + radius; }
   }
 
   property int bottomMostPoint
   {
      get { return cY + radius; }
   }
 
   public bool isPointInside(Point point, bool countOnBorder)
   {
      float gps; //it can be int (will function properly, but will give warning).
      int nrad;
      int rMin, rMax;
 
      nrad = radius * -1;
 
      //Some faster calculations to speed things up..
      if( (point.y - cY) < nrad || (point.y - cY) > radius)
         { return false; }
      if((point.x-cX) < nrad || (point.x-cX) > radius)
         { return false; }
 
      gps = fastSqrt((point.x-cX)*(point.x-cX) + (point.y-cY)*(point.y-cY));
 
      if(borderType == insideBevel)
      {
         rMin = radius - borderSize;
         rMax = radius;
      }
      else // borderType == outsideBevel
      {
         rMin = radius;
         rMax = radius + borderSize;
      }
 
      if(gps < radius)
      {
         //The point is inside of a circle
         return true;
      }
      else if(gps == radius || (gps > rMin && gps < rMax) )
      {
         //The point is on the border
         if(countOnBorder) { return true; }
      }
      //Else - The point is not in the circle nor on the border (or the border is not included)
      return false;
   }
 
   //Other functions found in Box struct
   //-----------------------------------------------------------------
   //Check what these do for box and if applicable...
   void ClipOffset(Circle against, int x, int y)
   {
   }
   void Clip(Circle against)
   {
   }
 
   bool Overlap(Circle circle)
   {
      if( leftMostPoint < circle.rightMostPoint && rightMostPoint > circle.leftMostPoint && topMostPoint < circle.bottomMostPoint && bottomMostPoint > circle.topMostPoint)
      {
         //It is inside of the circle's `box` so it should be studied more carefully if it is
         // trully overlaping or not...
         float overlap; //it can be int (will function properly, but will give warning).
         int rad;
         float h, w;
 
         w = cX - circle.cX;
         h = cY - circle.cY;
 
         overlap = fastSqrt((w*w)+(h*h));
 
         rad = radius + circle.radius;
 
         if(overlap < rad) { return true; }
      }
 
      return false;
   }
};
 
 
private float fastSqrt(float x)  
{
   //http://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi
   //Method number 1
   union
   {
      int i;
      float x;
   } u;
 
   u.x = x;
   u.i = (1<<29) + (u.i >> 1) - (1<<22); 
 
   // Two Babylonian Steps (simplified from:)
   // u.x = 0.5f * (u.x + x/u.x);
   // u.x = 0.5f * (u.x + x/u.x);
   u.x = u.x + x/u.x;
   u.x = 0.25f*u.x + x/u.x;
 
   return u.x;
}
 
 
void DrawCircle(Surface surface, Circle circle)
{
   ColorAlpha color[2];
 
   color[0] = black;
   color[1] = black;
   DrawCircleF(surface, circle.cX, circle.cY, circle.radius, emptyCircle, color, circle.borderSize, circle.borderType);
}
 
void DrawCircleF(Surface surface, int x0, int y0, int radius, CircleType circleType, ColorAlpha color[2], int borderSize, CircleBorder borderStyle )
{
   int f, fX, fY, x, y;
 
   f = 1 - radius;
   fX = 1;
   fY = -2 * radius;
   x = 0;
   y = radius;
 
   //Put the dot in the center of the circle
   //SetForeground(red);
   //PutPixel(x0,y0);
 
   //The border should always be drawn, not only if empty, as that way you can have
   // only line drawn, full color circle and colored circle with borders
   // this might not be wanted for circle if angles only
 
   //Draw borders
   surface.SetForeground(color[0]);
   surface.PutPixel(x0, y0 + radius);
   surface.PutPixel(x0, y0 - radius);
 
   //circle dots on the X axis on both sides of circle
   surface.PutPixel(x0 + radius, y0);
   surface.PutPixel(x0 - radius, y0);
 
   if(circleType == fullCircle)
   {
      surface.SetForeground(color[1]);
      surface.DrawLine(x0, y0 + radius, x0, y0 - radius);
      surface.DrawLine(x0 + radius, y0, x0 - radius+1, y0);
   }
 
   while(x < y)
   {
      // fX == 2 * x + 1;
      // fY == -2 * y;
      // f == x*x + y*y - radius*radius + 2*x - y + 1;
      if(f >= 0) 
      {
         y--;
         fY += 2;
         f += fY;
      }
 
      x++;
      fX += 2;
      f += fX;
 
      //Draw other dots... each line representing one sector...
      if(circleType == emptyCircle) //only border is shown
      {
         surface.PutPixel(x0 + x, y0 + y);
         surface.PutPixel(x0 - x, y0 + y);
         surface.PutPixel(x0 + x, y0 - y);
         surface.PutPixel(x0 - x, y0 - y);
         surface.PutPixel(x0 + y, y0 + x);
         surface.PutPixel(x0 - y, y0 + x);
         surface.PutPixel(x0 + y, y0 - x);
         surface.PutPixel(x0 - y, y0 - x);
      }
      else if(circleType == fullCircle) //everything is filled up..
      {
         surface.DrawLine(x0 + x, y0 + y, x0 - x, y0 + y);
         surface.DrawLine(x0 + x, y0 - y, x0 - x, y0 - y);
         surface.DrawLine(x0 + y, y0 + x, x0 - y, y0 + x);
         surface.DrawLine(x0 + y, y0 - x, x0 - y, y0 - x);
      }
   }
 
   if(borderSize > 1)
   {
      if(borderStyle == insideBevel)
      {
         DrawCircleF(surface, x0, y0, radius-1, circleType, color, borderSize-1, borderStyle );
      }
      else
      {
         DrawCircleF(surface, x0, y0, radius+1, circleType, color, borderSize-1, borderStyle );
      }
   }
}
 
class Form1 : Window
{
   caption = "Form1";
   background = formColor;
   borderStyle = sizable;
   hasMaximize = true;
   hasMinimize = true;
   hasClose = true;
   clientSize = { 632, 438 };
 
   //Lets add few circles
   Circle c1 {borderSize = 1;borderType = outsideBevel; cX = 270; cY = 65; radius = 38; };
   Circle c2 {borderSize = 1;borderType = outsideBevel; cX = 102; cY = 83; radius = 150; };
   Circle c3 {borderSize = 1;borderType = outsideBevel; cX = 321; cY = 130; radius = 50; };
 
   // The Clip() functions that work for the box are not done
   // The filled angles will be available at some other time, but the idea was to have the
   //  possibility of pie chart if it was needed, but it should be based on angles and I have
   //  some other idea in mind for that so will see what will happen - it might end up transferred to
   //  some other class instead...
 
   void OnRedraw(Surface surface)
   {
      ColorAlpha colors[2];
      ColorAlpha colors2[2];
 
      colors[0] = black; //border color
      colors[1] = red; //background color
 
      colors2[0] = blue;
      colors2[1] = green;
 
      //Lets draw these circles
      DrawCircle(surface, c1); //A quick way to draw them, which does not give you a lot of
                              // room to do anything with it
      //DrawCircleF(surface, x0,y0,radius,curcleType,color[2],borderSize,borderStyle);
      DrawCircleF(surface, c2.cX,c2.cY,c2.radius,fullCircle,colors,c2.borderSize,c2.borderType);
      DrawCircleF(surface, c3.cX,c3.cY,c3.radius,fullCircle,colors2,c3.borderSize,c3.borderType);
   }
 
   //Lets see what we can do with this...
 
   bool OnLeftButtonDown(int x, int y, Modifiers mods)
   {
      bool tc1, tc2, tc3;
      String msg;
 
      msg = "The click happened outside of any circle"; //default value
 
      tc1 = c1.isPointInside({x,y},true); // Sometimes you want the border to be considered as the
                                    // part of the circle, then you say true, but if you do not want
                                    // to have border included in the calculations then just put
                                    // false and it will not be counted
      tc2 = c2.isPointInside({x,y},false);
      tc3 = c3.isPointInside({x,y},true);
 
      if(tc1)  { msg = "the 'c1' circle was hit"; }
      else if(tc2) { msg = "the 'c2' circle was hit"; }
      else if(tc3) { msg = "the 'c3' circle was hit"; }
 
      MessageBox {this, text = "results", contents = msg}.Modal();
 
      return true;
   }
 
   bool OnRightButtonDown(int x, int y, Modifiers mods)
   {
      //Lets see if the circles are overlapping each other...
      if(c1.Overlap(c2))
      {
         MessageBox {this, text = "results", contents = "c1 and c2 overlap"}.Modal();
      }
      if(c1.Overlap(c3))
      {
         MessageBox {this, text = "results", contents = "c1 and c3 overlap"}.Modal();
      }
      if(c2.Overlap(c3))
      {
         MessageBox {this, text = "results", contents = "c2 and c3 overlap"}.Modal();
      }
      return true;
   }
 
}
 
class Form2 : Window
{
   caption = "Form2";
   background = formColor;
   borderStyle = sizable;
   hasMaximize = true;
   hasMinimize = true;
   hasClose = true;
   clientSize = { 632, 438 };
 
   //Lets add few circles
   Circle c1 {borderSize = 1;borderType = outsideBevel; cX = 270; cY = 65; radius = 38; };
   Circle c2 {borderSize = 1;borderType = outsideBevel; cX = 102; cY = 83; radius = 150; };
   Circle c3 {borderSize = 1;borderType = outsideBevel; cX = 321; cY = 130; radius = 50; };
 
   //Lets do something more with it..
   bool c1Inside, c2Inside, c3Inside;
   c1Inside = false;
   c2Inside = false;
   c3Inside = false;
 
   // The Clip() functions that work for the box are not done
   // The filled angles will be available at some other time, but the idea was to have the
   //  posibility of pie chart if it was needed, but it should be based on angles and I have
   //  some other idea in mind for that so will see what will happen - it might end up transfered to
   //  some other class instead...
 
   void OnRedraw(Surface surface)
   {
      ColorAlpha colors[2];
      ColorAlpha colors2[2];
      ColorAlpha colorsO[2];
      ColorAlpha colors2O[2];
 
      //Normal colors
      colors[0] = black;
      colors[1] = red;
      colors2[0] = blue;
      colors2[1] = green;
 
      //Over
      colorsO[0] = white;
      colorsO[1] = yellow;
      colors2O[0] = red;
      colors2O[1] = brown;
 
      //Lets draw these circles
      if(c1Inside)
      {
         DrawCircleF(surface, c1.cX,c1.cY,c1.radius,fullCircle,colorsO,c1.borderSize,c1.borderType);
      }
      else
      {
         DrawCircle(surface, c1); //A quick way to draw them, which does not give you a lot of
                                 // room to do anything with it
      }
      //surface.DrawCircleF(x0,y0,radius,curcleType,color[2],borderSize,borderStyle);
      if(c2Inside)
      {
         DrawCircleF(surface, c2.cX,c2.cY,c2.radius,fullCircle,colors2O,c2.borderSize,c2.borderType);
      }
      else
      {
         DrawCircleF(surface, c2.cX,c2.cY,c2.radius,fullCircle,colors,c2.borderSize,c2.borderType);
      }
 
      if(c3Inside)
      {
         DrawCircle(surface, c3);
      }
      else
      {
         DrawCircleF(surface, c3.cX,c3.cY,c3.radius,fullCircle,colors2,c3.borderSize,c3.borderType);
      }
   }
 
   //Lets see what we can do with this...
 
   bool OnMouseMove(int x, int y, Modifiers mods)
   {
      c1Inside = false;
      c2Inside = false;
      c3Inside = false;
 
      if(c1.isPointInside({x,y},true)) { c1Inside = true; }
      if(c2.isPointInside({x,y},true)) { c2Inside = true; }
      if(c3.isPointInside({x,y},true)) { c3Inside = true; }
 
      Update(null);
      return true;
   }
 
 
   bool OnLeftButtonDown(int x, int y, Modifiers mods)
   {
      bool tc1, tc2, tc3;
      String msg;
 
      msg = "The click happend outside of any circle"; //default value
 
      tc1 = c1.isPointInside({x,y},true); // Sometimes you want the border to be considered as the
                                    // part of the circle, then you say true, but if you do not want
                                    // to have border included in the calculations then just put
                                    // false and it will not be counted
      tc2 = c2.isPointInside({x,y},false);
      tc3 = c3.isPointInside({x,y},true);
 
      if(tc1)  { msg = "the 'c1' circle was hit"; }
      else if(tc2) { msg = "the 'c2' circle was hit"; }
      else if(tc3) { msg = "the 'c3' circle was hit"; }
 
      MessageBox {this, text = "results", contents = msg}.Modal();
 
      return true;
   }
 
   bool OnRightButtonDown(int x, int y, Modifiers mods)
   {
      //Lets see if the circles are overlapping each other...
      if(c1.Overlap(c2))
      {
         MessageBox {this, text = "results", contents = "c1 and c2 overlap"}.Modal();
      }
      if(c1.Overlap(c3))
      {
         MessageBox {this, text = "results", contents = "c1 and c3 overlap"}.Modal();
      }
      if(c2.Overlap(c3))
      {
         MessageBox {this, text = "results", contents = "c2 and c3 overlap"}.Modal();
      }
      return true;
   }
 
}
 
Form1 form1 {};
Form2 form2 {};
I might pick some things from this code when I add more graphics features to the Ecere graphics engine. Ideally though, the circle implementation would be a bit more optimal, implemented at the graphics driver level. If I don't have time to do this before the next release, I might include this circles.ec as part of the sdk/extras if you wish! Also I want to add round rectangle buttons since I read Steve Jobs biography, hehe he was a big fan of round rectangles!

Keep up the great work! =)

All the best,

Jerome
Author:  D.Bane [ Fri Jul 20, 2012 4:57 pm ]
Post subject:  Re: Ecere DLL update - class Circle

Hi Jerome,

Thank you for putting it all in one file. Yes, now that you have mentioned it, I searched for it and for some reason I had it in Surface.ec, not in units.ec, don't know why.. Thanks for noticing it.

If you want you can put it in extras, as far as I know all code we 'give to Ecere' is for everyone to use in Ecere :) (do not remember the exact post, something with 3D engine..) so it is up to you to put it in any place you think it would benefit people the best :)

I also like rounded buttons, and circles as buttons, so when I have time I will surely have a better algorithm for rounded rectangles, the one I currently have is hard coded for a bit roundish effect and I want 'border-radius' property on buttons..

[quote=jerome]Ideally though, the circle implementation would be a bit more optimal, implemented at the graphics driver level.[/quote] - Is it not like that? Should I have not added it in Surface.ec but in all .ec files found at ecere.dll/src/gfx/drivers? If that is true I would do that when I have some time again for ecere (hope soon) as well as for any other thing that I create (similar to this).

Best wishes,
D.Bane.
Author:  jerome [ Fri Jul 20, 2012 5:13 pm ]
Post subject:  Re: Ecere DLL update - class Circle

Hi D.Bane,

Yes, in each driver. For example in OpenGL, a circle would ideally be done with a vertex buffer object (VBO) with precomputed vertices. But all this is really part of doing a big graphics system improvement, so it is best to work together to get that going.

Regards,

Jerome
Author:  D.Bane [ Sat Jul 21, 2012 11:09 am ]
Post subject:  Re: Ecere DLL update - class Circle

Hi Jerome,

OK, then we will talk about it later on to see exactly how that could be accomplished :)

Also, just a note, for now, the Draw Circle function is recursive if you have borderSize bigger then 1, so for borderSize = 3, it would draw 3 circles. When I figure it out for a fast way to fill in the color, that will be replaced as 3 circles, just 1 pixel each smaller then another, will not create a fine border but would instead have few dots missing from it and when filling in the color, you would only need to draw 2 circles and fill in the gaps.

All the best,
D.Bane.
All times are UTC-05:00 Page 1 of 1