Recent

Author Topic: Drawing a rectangle  (Read 667 times)

Zaxxon

  • New Member
  • *
  • Posts: 30
Drawing a rectangle
« on: August 01, 2022, 12:09:21 pm »
Why the difference in drawing?
Using Canvas.Rectangle vs Canvas.MoveTo / Canvas.LineTo.
Same coordinates are used.



Handoko

  • Hero Member
  • *****
  • Posts: 4712
  • My goal: build my own game engine using Lazarus
Re: Drawing a rectangle
« Reply #1 on: August 01, 2022, 03:15:16 pm »
Not only slow but TCanvas drawing often gives you weird result. Is it a bug? I don't know but I already knew this weird issue long ago, no one care to fix it. Maybe it is done by design.

For example below is the code for drawing rectangles, both give different results and both are wrong:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   // Draw first rectangle
  4.   Canvas.Rectangle(10,10,12,12);  // delta X = 2, delta Y = 2
  5.  
  6.   //Draw second rectangle
  7.   Canvas.MoveTo(10,15);
  8.   Canvas.LineTo(12,15);  // delta X = 2
  9.   Canvas.LineTo(12,17);  // delta Y = 2
  10.   Canvas.LineTo(10,17);
  11.   Canvas.LineTo(10,15);
  12. end;

If I remember correctly, some call it last pixel missing issue.
« Last Edit: August 01, 2022, 06:02:49 pm by Handoko »

howardpc

  • Hero Member
  • *****
  • Posts: 3998
Re: Drawing a rectangle
« Reply #2 on: August 01, 2022, 03:33:47 pm »
It is not a bug.
The LCL graphics routines are nearly all based on rectangular frames. In 2-D, how do you count and identify pixels? In a line of pixels numbered 0, 1, 2 etc. from left to right the LineTo/MoveTo routines use the numbered pixels as expected.
However, the rectangle-based routines (Rectangle, FrameRect, FillRect, Frame, Ellipse, etc.) regard the coordinate given as the rightmost pixel to be the "edge" of the graphic, and the graphic is drawn up to that edge.
If you add an OnPaint handler to your example, and fill out the skeleton code Lazarus provides as follows you will perhaps get a feel for the routines. Uncomment the commented lines one at a time to see the effect.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormPaint(Sender: TObject);
  2. begin
  3.   Canvas.Pen.Color := clBlack;
  4.   Canvas.Brush.Color := clWhite;
  5.   //Canvas.Rectangle(56,321,56,321);   // this obviously does nothing
  6.   Canvas.Rectangle(56,321,57,322);   // this also does nothing
  7.   //Canvas.Rectangle(56,321,58,323); // this paints a single pixel  //Canvas.Rectangle(56,321,59,324); // this paints the smallest framed square possible
  8.   //Canvas.Rectangle(56,321,60,325); // this paints a slightly larger square
  9.   //Canvas.Rectangle(56,321,61,326); // etc.
  10. end;      
  11.  
« Last Edit: August 01, 2022, 03:36:35 pm by howardpc »

winni

  • Hero Member
  • *****
  • Posts: 3134
Re: Drawing a rectangle
« Reply #3 on: August 01, 2022, 03:47:39 pm »
Hi !

To make it clear:

This draws a line of 101 Pixels:

Code: Pascal  [Select][+][-]
  1.  Canvas.MoveTo(100,y);
  2.  Canvas.LineTo(200,y);
  3.  

But this draws a rectangle with a horizontal  width of 100:

Code: Pascal  [Select][+][-]
  1. canvas.rectangle (100,y1,200,y2);
  2.  


Winni

Handoko

  • Hero Member
  • *****
  • Posts: 4712
  • My goal: build my own game engine using Lazarus
Re: Drawing a rectangle
« Reply #4 on: August 01, 2022, 03:57:12 pm »
Thanks howardpc for the explanation.

But that does not explain why we can't get a good rectangle even if the delta x > 2 and delta y > 2. You always get a missing pixel. Also how will you explain the missing pixel of:

  Canvas.MoveTo(12,15);
  Canvas.LineTo(12,17); 
  Canvas.LineTo(10,17);


Even if one can explain it, that still against the rule of POLA:
https://en.wikipedia.org/wiki/Principle_of_least_astonishment

The best thing to do is avoid using TCanvas drawing feature, use OpenGL or other graphics engine. At least BASIC, which I learned when I was a kid, does not have this problem.

jamie

  • Hero Member
  • *****
  • Posts: 4763
Re: Drawing a rectangle
« Reply #5 on: August 01, 2022, 10:38:11 pm »
If memory serves those use a TRect for those functions and the right and lower sides need to be one more than the drawing area.

 So the left,top are as they say they are and the right bottom needs to be one more larger.

Maybe you have some other issues...
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018