Get all points in circle

BlitzMax Forums/BlitzMax Programming/Get all points in circle

Regular K(Posted 2007) [#1]
I need to know the coordinates of each pixel in a circle (radius) of a point, preferably through a loop (so I can create objects at those points)

I'm managing to do it now like so:
For d=-(PenSize/2) To PenSize/2
	For b=0 To 360 Step 2
		rX=MouseX()+(GetCos(b)*d)
		rY=MouseY()+(GetSin(b)*d)
		' create my object now at rX, rY
	Next
Next


As you can see, that is not very optimized (despite me precalculating Sin and Cos (helps a lot but not enough))

If anyone can help me I'd greatly appreciate it.


ImaginaryHuman(Posted 2007) [#2]
Put MouseX() and MouseY() outside of the inner For loop otherwise you are polling for mouse values via a function call for every pixel.

Local rXm:Float=MouseX()
Local rYm:Float=MouseY()
For b=0 .....

Also your first loop, mentioning the pensize, does not specify the `step` in which that loop will proceed. Perhaps the default of 1.0 is used provided the pensize is big enough to be at least 1 pixel or more? I just wondered if you were causing floating point steps which could be way small causing many more loops than you need.

I think the way I'd do it is use an entirely integer-based bresenham-style circle routine with a diameter of pensize/2, where you have control over being able to iterate through every pixel by yourself without repeating pixels. At the same time I would have a second circle being calculated, simultaneously, at the smaller diameter -(pensize/2) and then only accept pixels that are IN the bigger circle and NOT IN the smaller circle. You can easily find that because you will render the circle one row at a time and only have to figure out the outside radius position of each circle, once - you then only need to pay attention to the pixels on the same row between the outer circle perimeter and the inner one, which are all nicely next to each other in little sequences. You end up `drawing` a hollow circle with a varying pen thickness.

See my fast integer totally non-trigonometry non-floating-point bresenham circle program(s) in the code archives as a basis to work from. I think that will be faster than using any lookup table of sin/cos and you will be sure to cover all pixels, not leaving any gaps and not visiting the same pixel more than once, which is important if you want to use it to draw stuff in lightblend and not have overlap.


Derron(Posted 2007) [#3]
Think that must do it...
Function PointsInCircle:byte(X:Int, Y:Int, circlex:Int, circley:Int, radius:Int)
    Local posX:Int, posY:Int  
    local pointIsInside:byte=0
	For posX = X - radius To x + radius
  	   For posY = Y - radius To Y + radius
  	     ' within the circle?
	     If Sqr((posX - X)^2 + (posY - Y)^2) <= radius Then
	       'i'm within the circle... do something	
		   'my position is: posX-x,posY-y
                  pointIsInside=true
		 EndIf
	   Next
	Next
  return pointIsInside 
End Function



bye
MB


Regular K(Posted 2007) [#4]
Thanks MichaelB, and AngelDaniel.

I've settled with MichaelBs way, not as efficient as Daniels but a lot simpler :D


FlameDuck(Posted 2007) [#5]
Bresenham Circle Algorithm?


ImaginaryHuman(Posted 2007) [#6]
http://www.blitzbasic.com/codearcs/codearcs.php?code=1478

http://www.blitzbasic.com/codearcs/codearcs.php?code=1479

I only know it as the midpoint circle algorithm but it is very similar to the bresenham line routine in that it uses only integers, uses a wrap-around overflow, and lets you draw one pixel at a time.


Curtastic(Posted 2007) [#7]
I've been using this one, it's pretty simple. Just replace the dawrect, with: create object at dotx,doty.

'Goes through each pixel in a circle, so you can access them.
Function CirclePixels(x:Int, y:Int, r:Int)
	Local rx:Float
	Local dotx:Int, doty:Int
	Local rr:Int
	
	rr = r * r
	
	For doty = y - r To y + r
		rx = Sqr(rr - (doty - y) * (doty - y))
		For dotx = x - rx To x + rx
			DrawRect dotx, doty, 1, 1
		Next
	Next
EndFunction