PDA

Click to See Complete Forum and Search --> : BitBlting a Circle


jramirez
Apr 2nd, 2001, 10:59 AM
Can anyone show me an example of how you might draw a circle, using something like the Circle Method, but while using BitBlt? Mind you, I'm not talking about Blitting a bitmap of a circle; I need to draw the circle from scratch, changing its radius, height, width, and center based on other criteria, which changes from moment to moment.

Suggestions? better yet, examples!!!

Apr 2nd, 2001, 11:37 AM
You can't. BitBlt moves IMAGE bits from one DC to another. If you dont have a picture, you can Blit it.

Z.

jramirez
Apr 2nd, 2001, 11:41 AM
"If I don't have a picture, I can blt it"...do you mean I CAN'T Blt it?

Apr 2nd, 2001, 11:46 AM
BitBlt requires image data in the source that it can move to a destination. You can't Blit arbitrary radius, location data. For example:
I have a picture of a frog, and i want to put that frog picture on top of a pond picture. Sure, I can Blit that. But, if i dont have a frog picture, but you want to draw a circle onto the pond, you require an image of that circle before you can Blit it. Otherwise, BitBlt has nothing to put on top of the pond.

BitBlt moves images, in various ways, depending on how you tell it to draw. Nothing more.

Z.

jramirez
Apr 2nd, 2001, 11:51 AM
Thanks for the clarification!

Hehe, now, how would you handle this if you had to do it? Different circles to be drawn on a form, can't use a "set" bitmap...using the Circle method on the form itself causes waaaay too much screen flickering, so I was hoping to use "something" like BitBlt to get around the flickering issue.

HarryW
Apr 2nd, 2001, 12:00 PM
BitBlt is a Windows GDI function. If that's fast enough for you then there is a Windows GDI function for drawing a circle to a DC too. Well actually, not just circles but ellipses in general. Take a look (http://www.allapi.net/api/Ellipse.php).

Bear in mind that it will draw it using the currently selected-in pen and brush for the DC. You can make it do different colours of outline and fill by selecting in different pens and brushes.

jramirez
Apr 2nd, 2001, 12:06 PM
Thanks again...any suggestions for drawing an Arc, rather than a full circle?

kedaman
Apr 2nd, 2001, 01:18 PM
take a look again :p
http://www.allapi.net/api/Arc.php

Jotaf98
Apr 2nd, 2001, 05:52 PM
Here's a function to draw a circle using only a bit of math and the SetPixel API (similar to VB's PSet):

(It wasn't copied from the Net - nice what you can do with your dad's books when you're really desperate for a function, heh? ;) )



Private Sub DrawACircle(OrigX As Long, OrigY As Long, R As Long, hDc As Long, Color As Long)
Dim X As Long 'X Counter
Dim Y As Long 'Y Counter
'OrigX - X coordinates of the center
'OrigY - Y coordinates of the center
'R - The circle's radius

'Loop trough all the pixels of the circle...
For X = OrigX - R To OrigX + R
For Y = OrigY - R To OrigY + R
'Check if it's inside the circle...
If ((X - OrigX) * (X - OrigX)) + ((Y - OrigY) * (Y - OrigY)) <= (R * R) Then
SetPixel hDc, X, Y, Color
End If
Next Y
Next X
End Sub



Hope it helps you! If you need only the border or only the outside, it's possible too - just tell me ;)

Sastraxi
Apr 2nd, 2001, 07:56 PM
For plotting the X, Y coordinates of a circle:



X = Int(CenterX + Cos(Degrees) * Radius)
Y = Int(CenterY + Sin(Degrees) * Radius)



Degrees is a value between 0 and 359. Radius is a pixel radius value. CenterX and CenterY are pixel center points in the X and Y axes for the circle. X and Y are the positions of the circle.

HarryW
Apr 3rd, 2001, 07:40 AM
That's all very well but unless he's getting direct access to the video memory through something like DirectX, it's going to be slower plotting the pixels himself than it would be to use the Ellipse or Arc function. It's already flickering, he needs it as fast as possible.

Windows GDI may be slow (compared to APIs like DirectX and OpenGL) but it's a lot better than doing your own home-grown versions using VB's maths and the trig functions..... eww ;)

kedaman
Apr 3rd, 2001, 08:50 AM
yeah eww ;)

Apr 3rd, 2001, 03:16 PM
Sas, That code you posted wont work. Sin and Cos work in Radians.

Sastraxi
Apr 3rd, 2001, 03:42 PM
Very strange, because it worked for me. And it posted a full circle, with 360 points. Probably another example of VB's whacked math. (to convert to radians, divide the number by 114.64, (I think) that this will work)

kedaman
Apr 4th, 2001, 06:48 AM
nope multiply with 1.74532925E-02 (somehow i got to remember that one)

you must have a weird version of vb then sas, what does this give you

?sin(3.14159265358979)

should be:
3.23108510433268E-15

kedaman
Apr 4th, 2001, 12:07 PM
If you really want to do fast graphics processing algoritms, you should use DMA and preferably in C++, to fill a circle you could trap the edge's 1/8'th of the circle with a staircase algoritm and then loop from middle to edge in the 8 symetric directions and then fill the middle square

Jotaf98
Apr 4th, 2001, 06:11 PM
I feel like I know everything too when I talk like that :p

Could you please explain that... in more detail?

HarryW
Apr 4th, 2001, 07:43 PM
I'm not sure but I think Kedaman is saying that you can conceptually split the circle up into 8 45 degree (or pi/4 radians) sectors, and use the symmetry of the circle to speed up the calculations. Think of it this way - once you've drawn a semicircle, to draw the rest you just copy a mirror image. Well you can extend that to more axes.

I believe there are extensions of the Bresenham algorithm to draw circles, which is what I would use if I wanted to do fancy effects. I'd do it in C++ with DirectX or OpenGL too. SetPixel kind of sucks if you're going to use it a lot. Each call to SetPixel has to lock the video memory, find the correct location in memory depending on the colour depth of the current display mode, get the old colour, set the new colour, unlock the video memory and return a colour value. Not exactly ideal for performance. I guess the compiler could optimise it a lot, but I'm not sure if it would.

Anyway that code does a solid fill, not an outline.

kedaman
Apr 5th, 2001, 05:16 AM
Outline and solid fill. both would be quite optimal (i think)

imagine a square inside the circle, you can calculate the corner offset using one Squareroot, now you have 4 secants, which can be further splitted up into 8, all kaidoscopically symetric (heh just poped up in my head)
now the cords of these are 45'degree of the circle as Harry said :) Not much aritmetics to do now.

|\
| \
|y \ <- this is curved
| |
_x_|

for filled circles, you just need to store the edge distance to the middle, for each pixel in X axis, starting at the square result we've got from earlier to full circle radius. Y is successively increasing in a nested loop inside the X loop, and exits as soon as point enter circle, using pythagoras, the the value is stored, and X incremented (Y preserves) and it goes on until you've got all edge points into an array.

to draw the filled circle:
loop trough X or responding axis for each 8 mirror, in responding direction, and nested: loop Y from the middle to the value stored in the array, and plot each pixel. No aritmetics done in this process, so if you have several circles with same radius you could use the same array too. And lastly, fill the square in the middle with two nested loops.

to draw outline circle:
loop trough X and Y in the same way excep Y value is preserved, just as in the edge finding algoritm.

Well, this is straith from my head, and it might be that someone else invented this earlier or even got a better solution, i guess Harry knows :p

Jotaf98
Apr 5th, 2001, 10:41 AM
Hehe, ok.

Maybe you could do it this way:
You'd draw it using some algorythm (mine or Bresenham's :p ) , but only a quarter of it. It would be stored into an array, instead of drawn. Then, just draw it according to the array! It would be very easy to flip it to the other 4 quarters. Like this:



Dim Arr(0 to Width/2, 0 to Width/2) As Boolean

For x = 0 to Width/2
For y = 0 to Height/2
If [formulae-to-see-if-inside-the-circle] Then
Arr(x,y)=True
SetPixelV x,y,vbWhite
End If

If Arr(Width/2-x,y)=True Then SetPixelV x+Width/2,y,vbWhite

If Arr(x,Height/2-y)=True Then SetPixelV x,y+Height/2,vbWhite

If Arr(Width/2-x,Height/2-y)=True Then SetPixelV x+Width/2,y+Height/2,vbWhite
Next y
Next x

Mad Compie
Apr 6th, 2001, 02:36 PM
Here's a nice link to many gfx algorithms:

http://exaflop.org/docs/cgafaq/ind.html