Strange Phenomenon Drawing on Canvas

Its probably not a strange phenomenon but rather developer blunder. I am writing an app in which I can draw shapes on a canvas. I have a grid to which I am snapping 10 x 10 pixels. When I draw a line (see below) it is snapped to the grid, rectangle to grid, polygon snaps, oval snaps etc.

You will see though for some strange reason the bottom and right lines of the rect, rounded rect and oval are one pixel to the left and up from the grid.

I won’t post code as its massive but I have checked the values I am passing to canvas.drawrect and they are on the grid and also checked my grid and it is 10 x 10. Is there some simple reason I am missing that the shapes are missing the grid by 1 pixel.

the grid would be set from 0 - 9, 10-19, etc
and then make sure you’re 10 pixel wide item also draws from 0 - 9 and not 1 - 10

Mike, I don’t know what is going on with your pixel shift, but you may want to check https://forum.xojo.com/13995-toolbars-and-toggle-buttons for new postings.

Thanks Michael, i’ll take a look

[quote=112914:@Norman Palardy]the grid would be set from 0 - 9, 10-19, etc
and then make sure you’re 10 pixel wide item also draws from 0 - 9 and not 1 - 10[/quote]
Thanks Norman, I think that is the issue. I have just zoomed in and counted pixels and my grid is 11 pixels wide as I am looping 0 to 10. I’ll have a re-jig

Norman, so my grid drawing is done as follows:

For N As Integer = 0 To g.Width Step 10 For P As Integer = 0 To g.Height Step 10 GridPicture.Graphics.pixel(N,P) = &c00000000 Next P Next N

Which should set me a pixel every 10 pixels. Then, I am snapping my cursor (I am using crosshairs and hiding the system cursor) with the following calc in the mouse move event:

[code] if mGridSnap = true then
xCursor = (Ceil(X/10)) * 10
yCursor = (Ceil(Y/10)) * 10
Else
xCursor = x
yCursor = Y
end if

//Store the cursor positions for drawing positions
MousePosX = xCursor
MousePosY = yCursor [/code]

Cursor snaps fine bang on grid. I then get my shape X1,Y1,X2,Y2 coordinates my storing my MousePosX and MousePosY in the mousedown event so I am confused what I am doing wrong.

if xCursor = 10
(X/10) => 1
Ceil(X/10)=>1
(Ceil(X/10)) * 10 => 10

BUT you should be drawing 0 - 9 and 10 - 19 not 0-10,10-20 etc
That’d be where I suspect the off by one

You just have to draw one pixel wider and taller than you think, in order to encompass the grid lines. You’re drawing exactly right, if you wanted 2 rectangles side by side with no overlap. But you want the overlap.

It’s a classic off-by-one situation. 0 to 10 is 11 pixels, not 10. Same with 10 to 20, etc. You have the same error with your lines, you just can’t see it because the grid point “blends in”.

I could swear I already said something like that :stuck_out_tongue:

Right
In fact I was off by 1 as well
The grids should be counted as 0-9,9-18,18-27, as each it 10 wide IF you include the “0” point

This must be a bug. Try the following code in the paint event of a canvas:

g.DrawRect(0,0,50,50)
  g.DrawRect(50,0,50,50)

Before you run it wouldn’t you expect the second rectangles left face line be on the same line as the first rectangles right hand face? or am I going mad?

No. I wouldn’t. I would expect them to be side-by-side. The shared edge will appear 2 pixels thick.

The third and forth parameters are Width and Height, not X2, Y2. So if you draw a rectangle starting at 0 with a width of 50, the right edge will be at 49. 0 thru 49 makes 50 pixels for the width.

If you have 2 coordinates, X1/Y1 and X2/Y2, then the width of the rectangle that joins them will be Abs(X2-X1)+1. Similarly for the height.

[quote=112954:@Mike Charlesworth]This must be a bug. Try the following code in the paint event of a canvas:

g.DrawRect(0,0,50,50)
  g.DrawRect(50,0,50,50)

Before you run it wouldn’t you expect the second rectangles left face line be on the same line as the first rectangles right hand face? or am I going mad?[/quote]
No
the first draws from 0-49 (50 pixels)
the second draws starting at 50 - 1 pixel over :stuck_out_tongue:

I think that is what is throwing me. Why don’t we have coordinates for drawing on a canvas instead of width and height.

Right back to the drawing board

So therefore my original post is not incorrect a 10 pixel wide rect will not overlap a 10x10 grid because the first pixel will be overlapped and the next grid pixel will be 1 pixel after the rect.

right
0-9,9-18,18-27
I know it sounds weird but ….

No, your 10x10 grid is correct. There are indeed 10 pixels from one gridline to the next. But that doesn’t count both gridlines. If you want to encompass both gridlines, you have to draw an extra pixel to do it. It’s pretty standard stuff for drawing computer graphics. At least in my experience.

Yes I agree. So I would have a gridline at 0 and 9, 10 and 19, 20 and 29 etc etc

I would still go with 0, 10, 20, etc. When you calculate the width/height of an object, remember to add 1 to account for pixels being zero-based.