Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Another small filled circe sub (not as fast as fcirc)
#31
nagging... that reminds me I got to go Tongue
b = b + ...
Reply
#32
(08-29-2024, 11:35 PM)Pete Wrote: Very cool you found something on par with it. Now all you have to do is lobby for it as an alternative! Didn't we work together with Bill and Steve on some ellipse fill gold standard years ago?

Pete

- The Three Musketeers and the Theoretical Musketeer

yes we did, that's when we drove Bill nutz and he posted his slanted ellipse version without consulting, fortunately it was good!

BTW FC3 is working well in QB64 v2.1 once I tested without the browser on both with Checking On and OFF
b = b + ...
Reply
#33
Code: (Select All)
Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
    Dim Radius As Integer, RadiusError As Integer
    Dim X As Integer, Y As Integer
    Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
    If Radius = 0 Then PSet (CX, CY), C: Exit Sub
    Line (CX - X, CY)-(CX + X, CY), C, BF
    While X > Y
        RadiusError = RadiusError + Y * 2 + 1
        If RadiusError >= 0 Then
            If X <> Y + 1 Then
                Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
                Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
            End If
            X = X - 1
            RadiusError = RadiusError - X * 2
        End If
        Y = Y + 1
        Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
        Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
    Wend
End Sub

Probably just for style points, or do you think changing the conditional statement slows it down or speeds it up?

Code: (Select All)

Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
    Dim Radius As Integer, RadiusError As Integer
    Dim X As Integer, Y As Integer
    Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
    If Radius Then
        Line (CX - X, CY)-(CX + X, CY), C, BF
        While X > Y
            RadiusError = RadiusError + Y * 2 + 1
            If RadiusError >= 0 Then
                If X <> Y + 1 Then
                    Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
                    Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
                End If
                X = X - 1
                RadiusError = RadiusError - X * 2
            End If
            Y = Y + 1
            Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
            Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
        Wend
    Else
        PSet (CX, CY), C
    End If
End Sub


or...

Code: (Select All)
Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
    Dim RadiusError, X, Y As Integer
    If Abs(R) Then
        X = Abs(R): Y = 0: RadiusError = -X
        Line (CX - X, CY)-(CX + X, CY), C, BF
        While X > Y
            RadiusError = RadiusError + Y * 2 + 1
            If RadiusError >= 0 Then
                If X <> Y + 1 Then
                    Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
                    Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
                End If
                X = X - 1
                RadiusError = RadiusError - X * 2
            End If
            Y = Y + 1
            Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
            Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
        Wend
    Else
        PSet (CX, CY), C
    End If
End Sub

Pete
Shoot first and shoot people who ask questions, later.
Reply
#34
Play around with a pre-calculated set of coordinates:

Code: (Select All)
Screen _NewImage(1200, 700, 32)
_Define A-Z As LONG
Dim Shared CircleXPos(500, 500)
PreCalcX



Print
Print " fcirc fc fc3 fc4 precalc"
Print
For i = 1 To 10

'time the fcirc sub
t## = Timer(0.001)
For c = 1 To 15000
fcirc 400, 400, 100, _RGB(128, 128, 128)
Next
t1## = Timer(0.001) - t##

'time the fc sub
t## = Timer(0.001)
For c = 1 To 15000
fc 400, 400, 100, _RGB(255, 128, 128)
Next
t2## = Timer(0.001) - t##

'time the fc3 sub
t## = Timer(0.001)
For c = 1 To 15000
FC3 400, 400, 100, _RGB(128, 255, 128)
Next
t3## = Timer(0.001) - t##

'time the fc4 sub
t## = Timer(0.001)
For c = 1 To 15000
fc4 400, 400, 100, _RGB(128, 128, 255)
Next
t4## = Timer(0.001) - t##

'time the Steve sub
t## = Timer(0.001)
For c = 1 To 15000
StevePreCalcCircle 400, 400, 100, _RGB(255, 0, 0)
Next
t5## = Timer(0.001) - t##

Print t1##, t2##, t3##, t4##, t5##
Next

Sub fc (cx, cy, r, clr&)
For y = -r To r
x = Int(Sqr(r * r - y * y))
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Next
End Sub

Sub fc4 (cx, cy, r, clr&)
r2 = r * r
For y = 0 To r
y2 = y * y
'If y2 <= r2 Then
x = Int(Sqr(r2 - y2))
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
'End If
Next
End Sub

Sub FC3 (cx, cy, r, clr&)
Line (cx - r, cy)-(cx + r, cy), clr&, BF
y = 1
r2 = r * r ' Dav mod
While y <= r
y2 = y * y
If y2 < r2 Then
x = Int(Sqr(r2 - y2))
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
End If
y = y + 1
Wend
End Sub


Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
Dim Radius As Integer, RadiusError As Integer
Dim X As Integer, Y As Integer
Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
If Radius = 0 Then PSet (CX, CY), C: Exit Sub
Line (CX - X, CY)-(CX + X, CY), C, BF
While X > Y
RadiusError = RadiusError + Y * 2 + 1
If RadiusError >= 0 Then
If X <> Y + 1 Then
Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
Wend
End Sub


Sub StevePreCalcCircle (cx, cy, r, clr&)
$Checking:Off
For y = 0 To r
x = CircleXPos(r, y)
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Next
$Checking:On
End Sub

Sub PreCalcX
For r = 0 To 500 'circles with a radius from 0 to 500
r2 = r * r
For y = 0 To r
y2 = y * y
x = Int(Sqr(r2 - y2))
CircleXPos(r, y) = x
Next
Next
End Sub

Note that I just translated the easiest to modify routine (f4) to make use of just doing a lookup, rather than the math on the spot.

Performance here varies widely for me here, based on optimization flags, variable types (change that _DEFINE type a few times), and other such things...

Which leads me to the conclusion that you can only optimize down so much, and then you're defeating the purpose and over analyzing it. Speeds are going to always vary based on OS/memory/system/background processes/blah/blah/blah...

Just because one method works fastest on my machine, doesn't mean it's going to be the fastest on yours. If you TRULY have time-critical tasks, the best you can do is head to the PC/Laptop/Machine that needs to run that task, and then test and benchmark all those thousands of different variables and configurations that can come into play, and then you micro-optimize for that *one particular machine*.

It's like professional, Olympic level shooting and the care they take to perfectly bore and set up each rifle and sight, and then how they weigh out each grain of gunpowder that they manually load their ammo with, after the choose the perfect... blah blah and blah.... Compared to Joe Smoe who has a 20-year old rifle that was cleaned and oiled sometime in the last ten years, with ammo that's been on a shelf for the last five to forty years, and a scope that was kinda... maybe... sighted in probably about six years ago.

Sometimes you just have to say, "Meh, close enough," and then let it go as long as it'll still drop that deer at 100 yards and put food on your table. Wink
Reply
#35
Yes, I recall how Bill didn't think using SQR could possibly work, until I did exactly that. Mostly thanks to _INTEGER64, it worked.

That reminds me....
Code: (Select All)
Sub FC3 (cx, cy, r, clr&)
    Line (cx - r, cy)-(cx + r, cy), clr&, BF
    y = 1
    r2 = r * r ' Dav mod
    While y <= r
        y2 = y * y
        If y2 < r2 Then
            x = Int(Sqr(r2 - y2))
            Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
            Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
        End If
        y = y + 1
    Wend
End Sub

Could be modified to...
Code: (Select All)
Sub FC3 (cx, cy, r, clr&)
    Dim x as Integer
    Line (cx - r, cy)-(cx + r, cy), clr&, BF
    r2 = r * r ' Dav mod
    Do Until y > r
        y = y + 1
        y2 = y * y
        If y2 < r2 Then
            x = Sqr(r2 - y2)
            Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
            Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
        End If
    Loop
End Sub

Pete
Shoot first and shoot people who ask questions, later.
Reply
#36
(08-30-2024, 04:21 AM)Pete Wrote: Yes, I recall how Bill didn't think using SQR could possibly work, until I did exactly that. Mostly thanks to _INTEGER64, it worked.

That reminds me....
Code: (Select All)
Sub FC3 (cx, cy, r, clr&)
    Line (cx - r, cy)-(cx + r, cy), clr&, BF
    y = 1
    r2 = r * r ' Dav mod
    While y <= r
        y2 = y * y
        If y2 < r2 Then
            x = Int(Sqr(r2 - y2))
            Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
            Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
        End If
        y = y + 1
    Wend
End Sub

Could be modified to...
Code: (Select All)
Sub FC3 (cx, cy, r, clr&)
    Dim x as Integer
    Line (cx - r, cy)-(cx + r, cy), clr&, BF
    r2 = r * r ' Dav mod
    Do Until y > r
        y = y + 1
        y2 = y * y
        If y2 < r2 Then
            x = Sqr(r2 - y2)
            Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
            Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
        End If
    Loop
End Sub

Pete

My thinking was to make use of something like this:
Code: (Select All)
Sub PreCalcX
    For r = 0 To 500 'circles with a radius from 0 to 500
        r2 = r * r
        For y = 0 To r
            y2 = y * y
            x = Int(Sqr(r2 - y2))
            CircleXPos(r, y) = x
        Next
    Next
End Sub

Precalculate all that math, and get rid of it completely.  Just one quick lookup for that value rather than multiplying and all that.

It would seem to me that *this* should be much faster than everything else is:
Code: (Select All)
Sub StevePreCalcCircle (cx, cy, r, clr&)
    $Checking:Off
    For y = 0 To r
        x = CircleXPos(r, y)
        Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
        Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
    Next
    $Checking:On
End Sub

Just look up that one value from a precalculated list.   And yet... almost impossibly... it's often not the fastest method we have available, when resting those speeds all side by side!

Are our arrays that slow?
Is the timer routine screwing up somewhere?
WTF is going on to give us the figures that we're getting??

I have no clue.  I just found the results upper astonishing.
Reply
#37
A few changes to make comparing the speeds and overall results a little easier to understand the overall differences:

Code: (Select All)
Screen _NewImage(1200, 700, 32)
_Define A-Z As LONG
Dim Shared CircleXPos(500, 500)
PreCalcX



Print
Print " fcirc fc fc3 fc4 precalc"
Print
For i = 1 To 10

'time the fcirc sub
t## = Timer(0.001)
For c = 1 To 15000
fcirc 400, 400, 200, _RGB(128, 128, 128)
Next
t1## = Timer(0.001)

'time the fc sub
For c = 1 To 15000
fc 400, 400, 200, _RGB(255, 128, 128)
Next
t2## = Timer(0.001)

'time the fc3 sub
For c = 1 To 15000
FC3 400, 400, 200, _RGB(128, 255, 128)
Next
t3## = Timer(0.001)

'time the fc4 sub
For c = 1 To 15000
fc4 400, 400, 200, _RGB(128, 128, 255)
Next
t4## = Timer(0.001)

'time the Steve sub
For c = 1 To 15000
StevePreCalcCircle 400, 400, 200, _RGB(255, 0, 0)
Next
t5## = Timer(0.001)

Print t1## - t##, t2## - t1##, t3## - t2##, t4## - t3##, t5## - t4##
f1## = f1## + t1## - t##
f2## = f2## + t2## - t1##
f3## = f3## + t3## - t2##
f4## = f4## + t4## - t3##
f5## = f5## + t5## - t4##
Next
Print
Print f1##, f2##, f3##, f4##, f5##


Sub fc (cx, cy, r, clr&)
For y = -r To r
x = Int(Sqr(r * r - y * y))
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Next
End Sub

Sub fc4 (cx, cy, r, clr&)
r2 = r * r
For y = 0 To r
y2 = y * y
'If y2 <= r2 Then
x = Int(Sqr(r2 - y2))
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
'End If
Next
End Sub

Sub FC3 (cx, cy, r, clr&)
Line (cx - r, cy)-(cx + r, cy), clr&, BF
y = 1
r2 = r * r ' Dav mod
While y <= r
y2 = y * y
If y2 < r2 Then
x = Int(Sqr(r2 - y2))
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
End If
y = y + 1
Wend
End Sub


Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
Dim Radius As Integer, RadiusError As Integer
Dim X As Integer, Y As Integer
Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
If Radius = 0 Then PSet (CX, CY), C: Exit Sub
Line (CX - X, CY)-(CX + X, CY), C, BF
While X > Y
RadiusError = RadiusError + Y * 2 + 1
If RadiusError >= 0 Then
If X <> Y + 1 Then
Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
End If
X = X - 1
RadiusError = RadiusError - X * 2
End If
Y = Y + 1
Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
Wend
End Sub


Sub StevePreCalcCircle (cx, cy, r, clr&)
$Checking:Off
For y = 0 To r
x = CircleXPos(r, y)
Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
Next
$Checking:On
End Sub

Sub PreCalcX
For r = 0 To 500 'circles with a radius from 0 to 500
r2 = r * r
For y = 0 To r
y2 = y * y
x = Int(Sqr(r2 - y2))
CircleXPos(r, y) = x
Next
Next
End Sub


   

From this, on my machine, the precalculated coordinate look-up is the quickest, with fcirc right behind and everything else being a little slower. This is with the latest QB64PE version and with the optimization flag set in compiler options. I don't know if others will see the same style results or not, depending on however it compiles and optimizes on their systems.
Reply
#38
Steve yours has same flaw as Dav's FC4 from which you made youirs

Code: (Select All)
Screen _NewImage(1200, 700, 32)
_Define A-Z As LONG
Dim Shared CircleXPos(500, 500)
PreCalcX

StevePreCalcCircle 600, 350, 300, _RGB32(0, 0, 255, 100)

Sub StevePreCalcCircle (cx, cy, r, clr&)
    $Checking:Off
    For y = 0 To r
        x = CircleXPos(r, y)
        Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
        Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
    Next
    $Checking:On
End Sub

Sub PreCalcX
    For r = 0 To 500 'circles with a radius from 0 to 500
        r2 = r * r
        For y = 0 To r
            y2 = y * y
            x = Int(Sqr(r2 - y2))
            CircleXPos(r, y) = x
        Next
    Next
End Sub

Does not work for transparent colors.

Both Steve and Pete are also using Dav's messed up FC3 code.

I've already pointed out these 2 things with Dav's code.
b = b + ...
Reply
#39
(08-30-2024, 02:17 PM)bplus Wrote: Steve yours has same flaw as Dav's FC4 from which you made youirs

Code: (Select All)
Screen _NewImage(1200, 700, 32)
_Define A-Z As LONG
Dim Shared CircleXPos(500, 500)
PreCalcX

StevePreCalcCircle 600, 350, 300, _RGB32(0, 0, 255, 100)

Sub StevePreCalcCircle (cx, cy, r, clr&)
    $Checking:Off
    For y = 0 To r
        x = CircleXPos(r, y)
        Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
        Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
    Next
    $Checking:On
End Sub

Sub PreCalcX
    For r = 0 To 500 'circles with a radius from 0 to 500
        r2 = r * r
        For y = 0 To r
            y2 = y * y
            x = Int(Sqr(r2 - y2))
            CircleXPos(r, y) = x
        Next
    Next
End Sub

Does not work for transparent colors.

Both Steve and Pete are also using Dav's messed up FC3 code.

I've already pointed out these 2 things with Dav's code.

Aye.  I wasn't trying to make an image perfect circle.  I was simply testing the concept of how much a precalculated-point system would speed up a circle.

What we have is already quick enough and optimized enough for my needs.   The time difference in these routines is really fairly negligible under most use cases.  It shouldn't be too difficult to adjust that to accommodate for the overlap.

Code: (Select All)
Sub StevePreCalcCircle (cx, cy, r, clr&)
    $Checking:Off
    For y = 0 To r
        x = CircleXPos(r, y)
        Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
        IF y > 0 THEN Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
    Next
    $Checking:On
End Sub

Something as simple as the above should fix it, I'd think -- though it's untested.  The concept, at least, seems sound to me:  If your +y and -y are 0, then you only need to draw the line once, not twice.
Reply
#40
Bplus, color has data type unsigned long. You use the long data type in FC (variable clr&). Maybe that's why it doesn't work for you with transparent colors.


Reply




Users browsing this thread: 30 Guest(s)