Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Another small filled circe sub (not as fast as fcirc)
#41
Re: Petr
No, it doesn't work for anyone because two lines are being drawn over the same spot. That's fine for non transparent colors but not for transparent colors.


I have noticed something with these timed tests, the first one is so horrendous in time that it messes up the over all total so we are putting fcirc at disadvantage calling it first in these tests.

To test this idea, I swicthed the right FC3 sub with fcirc in order so it is called first and now fcirc comes out the consistent winner:
Code: (Select All)
_Title "FC3 versus fcirc reverse order" ' b+ 2024-08-30
'Dav, AUG/2024 bplus mod 2024-08-28  try faster FC2 mod of fc

' 2024-08-29 try larger circles all on screen with FC3

' 2024-08-30 test idea who goes first loses!

' next line uncommented will speed up test time but wont be able to exit until done.
$Checking:Off
Screen _NewImage(1000, 700, 32)
_ScreenMove 150, 0
Randomize Timer
Print "Overlapping lines check of FC3"
FC3 500, 350, 300, &H200000FF ' check for overlapping lines
Print "Looking good! no lighter lines." ' FC passes too BTW
Print: Print " zzz... press any for timed test"
Sleep
Cls
For i = 1 To 10 ' in case going first has disadvantage
    'time the fc sub
    t# = Timer(.001)
    For c = 1 To 2000
        FC3 Rnd * (_Width - 700) + 350, 350, 350, _RGB32(Rnd * 255, Rnd * 255, Rnd * 255)
        _Display
    Next
    t1# = t1# + Timer(.001) - t#

    'time the fc2 sub
    t# = Timer(.001)
    For c = 1 To 2000
        fcirc Rnd * (_Width - 700) + 350, 350, 350, _RGB32(Rnd * 255, Rnd * 255, Rnd * 255)
        _Display
    Next
    t2# = t2# + Timer(.001) - t#
Next
Print
Print "  FC3 ="; t1#
Print "fcirc ="; t2#
Print

If t2# < t1# Then
    Print "fcirc wins!"
ElseIf t1# < t2# Then ' EDIT fixed!
    Print "FC3 wins!"
Else
    Print "Tie fcirc = FC3 time"
End If
_Display
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 FC3 (cx, cy, r, clr&)
    Line (cx - r, cy)-(cx + r, cy), clr&, BF
    y = 1
    r2 = r * r ' Dav mod
    While y <= r
        x = Int(Sqr(r2 - y * y)) ' r2 Dav
        Line (cx - x, cy + y)-(cx + x, cy + y), clr&, BF
        Line (cx - x, cy - y)-(cx + x, cy - y), clr&, BF
        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
b = b + ...
Reply
#42
(08-30-2024, 02:35 PM)Petr Wrote: 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.

Oh crap! everyone is using & not ~& for the color in the subs!

Sorry @Petr, I missed that from the start of Dav's experiments!

+1 to Petr

BTW @Dav If you don't care about transparency then YES! there are faster ways to fill a circle, an extra line is nothing compared to an extra decision in a loop!
b = b + ...
Reply
#43
I messed around with it and the transparency now works in both cases. For CircleFill I had to remove the BF parameter on the first LINE command.

Code: (Select All)

_Title "FC3 versus fcirc reverse order" ' b+ 2024-08-30
'Dav, AUG/2024 bplus mod 2024-08-28  try faster FC2 mod of fc

' 2024-08-29 try larger circles all on screen with FC3

' 2024-08-30 test idea who goes first loses!

' next line uncommented will speed up test time but wont be able to exit until done.
$Checking:Off
Screen _NewImage(1000, 700, 32)
_ScreenMove 150, 0
Randomize Timer
Print "Overlapping lines check of FC3"
FC3 500, 350, 300, &H200000FF ' check for overlapping lines
Print "Looking good! no lighter lines." ' FC passes too BTW
Print: Print " zzz... press any for timed test"
Sleep
Cls

$Checking:On
'better for program quit...

Dim A As _Unsigned _Byte

For i = 1 To 10 ' in case going first has disadvantage
    'time the fc sub
    t# = Timer(.001)
    For c = 1 To 5
        Randomize Timer
        A = Rnd * 255
        FC3 Rnd * (_Width - 700) + 350, 350, 350, _RGBA32(Rnd * 255, Rnd * 255, Rnd * 255, A)
        Locate 1: Print "Alpha: "; A
        _Display
    Next
    t1# = t1# + Timer(.001) - t#

    'time the fc2 sub
    t# = Timer(.001)
    For c = 1 To 5
        A = Rnd * 255
        fcirc Rnd * (_Width - 700) + 350, 350, 350, _RGBA32(Rnd * 255, Rnd * 255, Rnd * 255, A)
        Locate 1: Print "Alpha: "; A
        _Display
    Next
    t2# = t2# + Timer(.001) - t#
Next
Print
Print "  FC3 ="; t1#
Print "fcirc ="; t2#
Print

If t2# < t1# Then
    Print "fcirc wins!"
ElseIf t1# < t2# Then ' EDIT fixed!
    Print "FC3 wins!"
Else
    Print "Tie fcirc = FC3 time"
End If
_Display
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
    Sound 250, .2
    Sleep
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
        x = Int(Sqr(r2 - y * y)) ' r2 Dav
        Line (cx - x, cy + y)-(cx + x, cy + y), clr~&, BF
        Line (cx - x, cy - y)-(cx + x, cy - y), clr~&, BF
        y = y + 1
    Wend
    Beep
    Sleep
End Sub


Sub fcirc (CX As Integer, CY As Integer, R As Integer, C As _Unsigned Long)
    Dim Radius As Integer, RadiusError As _Integer64
    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
    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

    Sound 320, .2
    Sleep
End Sub

A BEEP is to announce that FC3 has completed a circle, a SOUND is to announce that Fcirc has completed a circle. Testing doesn't work here, it was about transparency.


Reply
#44
OK here is the FC3 sub that you guys are not getting right: (update: Petr got it right but then put in Beep and Sleep?)
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
        x = Int(Sqr(r2 - y * y)) ' r2 Dav
        Line (cx - x, cy + y)-(cx + x, cy + y), clr~&, BF
        Line (cx - x, cy - y)-(cx + x, cy - y), clr~&, BF
        y = y + 1
    Wend
End Sub

Don't use y2 and the extra decision in the loop. I just updated the sub for _Unsigned long color!

Now to run these tests all over again!
b = b + ...
Reply
#45
Sorry I messed up the SUB's, guys.  Sad 

When I make a mess, it's usually big.  No, I'm not a politician.

- Dav

Find my programs here in Dav's QB64 Corner
Reply
#46
BPlus wrote:  Petr got it right but then put in Beep and Sleep?

Yes, I put beep and sleep in there to see for myself that the result is transparent. Now in both cases.


Reply
#47
Just a couple of things to point out, that I believe to be correct.

1) There should be no need to use INT() if we simply DIM x As Integer. Making the x variable an integer instead of a default single is faster. The system will convert the value automatically to an integer this way.

2) I assigned the variables to use in the SQR() calculation in the flat ellipse project as  _Integer64. I discovered working with SQR() that this was required to avoid incorrect renderings with certain ellipse size numbers. 201 comes to mind.

3) Cobalt had mentioned that: " _SHL\_SHR are even faster if dealing with powers of 2." Well, I took a look at _SHL(y, 1) but unless I'm not familiar enough with bit flipping, this simply does not equal y ^2 or y * y. Also beyond 256 we have an issue, so I don't see making use of it. Am I wrong?

Also thanks to Steve for trying out what I previously referred to as using a hash table lookup method. I know array processing is a bit sluggish in QB64, for whatever reason, so it was interesting to see that precalculated input using arrays is about a push, perhaps a hair faster. Couple this with the baggage and it is just not practical unless you are interested in filling a billion circles and don't have a second to waste.

Pete
Shoot first and shoot people who ask questions, later.
Reply
#48
+1 @Pete no need Int() is good point! why am missing all this? because I was modding off Dav.

That's my excuse and I am sticking to it! -1 for me for that crap!

@Dav it's good we are testing filled circle and not resting on past laurels.
b = b + ...
Reply
#49
I see that in CircleFill I can leave the BF parameter at the first LINE statement. That's right. Steve always posts perfectly tuned treasures. 
And thanks to all of you for forcing me to let go of the IDE again. Guys, I have so much work, this is a holiday for me.


Reply
#50
This is a perfect example why it's good to have more eyes on your code to catch errors you overlook.

- Dav

Find my programs here in Dav's QB64 Corner
Reply




Users browsing this thread: 2 Guest(s)