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

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Draw Circle using Brush Tool

Note: You must be registered in order to post a reply.
To register, click here. Registration is FREE!

View 
UserName:
Password:
Format  Bold Italicized Underline  Align Left Centered Align Right  Horizontal Rule  Insert Hyperlink   Browse for an image to attach to your post Browse for a zip to attach to your post Insert Code  Insert Quote Insert List
   
Message 

 

Emoji
Smile [:)] Big Smile [:D] Cool [8D] Blush [:I]
Tongue [:P] Evil [):] Wink [;)] Black Eye [B)]
Frown [:(] Shocked [:0] Angry [:(!] Sleepy [|)]
Kisses [:X] Approve [^] Disapprove [V] Question [?]

 
Check here to subscribe to this topic.
   

T O P I C    R E V I E W
kturkay Posted - Jul 12 2020 : 10:38:03
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;
4   L A T E S T    R E P L I E S    (Newest First)
xequte Posted - Jul 16 2020 : 01:50:55
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
xequte Posted - Jul 16 2020 : 01:41:35
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
kturkay Posted - Jul 12 2020 : 22:13:04
#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



xequte Posted - Jul 12 2020 : 20:44:26
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