ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Draw Circle using Brush Tool
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

kturkay

44 Posts

Posted - Jul 12 2020 :  10:38:03  Show Profile  Reply
Hello Mr Nigel..

I draw circle onto canvas using Bresenham algorithm.

have 2 question marks spinning on top of my head.
1- drawing to canvas does not adding to undo stack. so undo doesn't work. is there a way to adding in undostack of that direct canvas draw circle operation?
2- It would be awesome draw using brushtool instead of pixel coloring.

how would you do that ?

ImageenVect1.BrushTool.StartPainting
ImageenVect1.BrushTool.AddToPainting
ImageenVect1.BrushTool.EndPainting
seems the only way. but seems too slow and generates filled circle instead of circle.


BresenhamCircle(400, 400, 100, Iv.Layers[0].Bitmap.Canvas, clred);
Iv.Update;


procedure TForm1.BresenhamCircle(CenterX, CenterY, Radius: Integer; Canvas: TCanvas; Color: TColor);
  procedure PlotCircle(X, Y, x1, y1: Integer);
  begin
    Canvas.Pixels[X + x1, Y + y1] := Color;
    Canvas.Pixels[X - x1, Y + y1] := Color;
    Canvas.Pixels[X + x1, Y - y1] := Color;
    Canvas.Pixels[X - x1, Y - y1] := Color;
    Canvas.Pixels[X + y1, Y + x1] := Color;
    Canvas.Pixels[X - y1, Y + x1] := Color;
    Canvas.Pixels[X + y1, Y - x1] := Color;
    Canvas.Pixels[X - y1, Y - x1] := Color;

  end;

var
  X, Y, r: Integer;
  x1, y1, p: Integer;
begin
  X := CenterX;
  Y := CenterY;
  r := Radius;
  x1 := 0;
  y1 := r;
  p := 3 - 2 * r;

  while (x1 < y1) do
  begin
    PlotCircle(X, Y, x1, y1);
    if (p < 0) then
      p := p + 4 * x1 + 6
    else
    begin
      p := p + 4 * (x1 - y1) + 10;
      y1 := y1 - 1;
    end;
    x1 := x1 + 1;
  end;
  if (x1 = y1) then
    PlotCircle(X, Y, x1, y1);

end;

xequte

38610 Posts

Posted - Jul 12 2020 :  20:44:26  Show Profile  Reply
Hi

1. If you want Undo to work when drawing with the canvas, you should manually call Proc.SaveUndo();

2. This is a slow mechanism to draw a circle (over 1000 pts for a 200 rad circle). Why use this method rather than a TIEShapeLayer or IECanvas.Ellipse(), for example?

3. If you were using BrushTool to paint this, you might want to space out the circle points (<360 pts for a circle should generally be plenty).

4. I cannot see why a brush circle would be filled. You would need to show me your code.

Nigel
Xequte Software
www.imageen.com
Go to Top of Page

kturkay

44 Posts

Posted - Jul 12 2020 :  22:13:04  Show Profile  Reply
#2 old swot men loves old school boards :) my app is for this. (I sent a copy of app to your email. I will update soon installation in googledrive)

yesterday before, I did. works good enough. performance is not too bad (on 2K perf. is okay but I don't wanna think 4K monitors^^). also undo operations is okay. (I think to make brushtool faster,GPU usage, directx or gdi+ routines could be used. I am not an expert of it. just dreaming about it)

I thought same as you. and it seems the way of mind is one.

https://tr.im/lines_and_circles is small demo

code works very well in my application. but don't understand why circles and lines offsetting randomly in this demo...
may be something wrong with XScr2Bmp YScr2Bmp or maybe I didn't understand what they are for.
code works good in my app. but offsetting in demo.. weird ...couldn't detect the reason at 1st sight. if you know the reason . I will modify to make a better demoapp and wanna add in "demos" forum section.

(usage.
to draw a circle. 1st click is the center 2nd alt+click is the radius,
to draw a line. 1st click is the start-point 2nd ctrl+click is the endpoint. if you keep holding click it mimics as poly-line)

this is how it works well in my app



mr Nigel



Go to Top of Page

xequte

38610 Posts

Posted - Jul 16 2020 :  01:41:35  Show Profile  Reply
Hi

The main issue is that with XScr2Bmp the screen value is actually relative to the control, i.e. as if the TImageEnView is positioned at 0,0 on the active screen. So you need to use ScreenToClient to convert it to a client screen value.

// At TTimer interval, paint the pixel at the cursor position white
// Note: Example only. MouseMove event would be better for this
procedure TForm5.Timer1Timer(Sender: TObject);
var
  Pos: TPoint;
begin
  // Get pos of cursor on screen
  GetCursorPos(Pos);

  // Convert it to position of the TImageEnView
  Pos := ImageEnView1.ScreenToClient(Pos);

  // Convert it to a bitmap value
  Pos.X := ImageEnView1.XScr2Bmp(Pos.X);
  Pos.Y := ImageEnView1.YScr2Bmp(Pos.Y);

  // Paint the pixel
  if ( Pos.X >= 0 ) and ( Pos.X < ImageEnView1.IEBitmap.Width ) and
     ( Pos.Y >= 0 ) and ( Pos.Y < ImageEnView1.IEBitmap.Height ) then
  begin
    ImageEnView1.IEBitmap.Pixels[ Pos.X, Pos.Y ] := TColor2TRGB( clWhite );
    ImageEnView1.Update();
  end;
end;


Nigel
Xequte Software
www.imageen.com
Go to Top of Page

xequte

38610 Posts

Posted - Jul 16 2020 :  01:50:55  Show Profile  Reply
Other points:
- Use a TImageEnView, not a TImageEnVect
- I don't think you should use a MouseInteraction for this, otherwise your painting code will compete with the built in painting code. Set MouseInteractGeneral to [] and use the MouseMove event to do your painting.

This is just a rough example, as I'm not sure how you want your app to paint:

procedure TForm5.IvMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  mc_: TPoint;
begin
  if fMouseDown and (GetKeyState(VK_CONTROL) < 0) then
  begin
    mc_.X := Iv.XScr2Bmp(X);
    mc_.Y := Iv.YScr2Bmp(Y);
    LinePoint(mc_, false);
  end
  else
  if fMouseDown and (GetKeyState(VK_MENU) < 0) then
  begin
    mc_.X := Iv.XScr2Bmp(X);
    mc_.Y := Iv.YScr2Bmp(Y);
    LinePoint(mc_, true);
  end
  else
  if fMouseDown then
  begin
    mc_.X := Iv.XScr2Bmp(X);
    mc_.Y := Iv.YScr2Bmp(Y);
    ...
  end
  else
  begin
    // Mouse is up
    mc_.X := Iv.XScr2Bmp(X);
    mc_.Y := Iv.YScr2Bmp(Y);
    FLinePoint1 := mc_;
    FLinePoint2 := TPoint.Zero;
  end;
end;





Nigel
Xequte Software
www.imageen.com
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: