Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
trouble filling in a closed vector shape
#1
UPDATE: figured this out, the final program is here! But I'm tired... In the words of c3p0, "no more adventures!" Tongue 


Hi everyone... over the weekend I did some work on the "van halen" screensaver, playing around with vector graphics, and added the band logo moving across the screen and getting bigger for a 3D effect.

It works good drawn as just an outline, even with 10 or 20 of them going at once (for that see attached "VanHalenizer2-05-17.multi vectors.bas"). 
(Hey @BPlus, check out "VanHalenizer2-05-17b.multi vectors.PSYCHEDELIC!.bas"! Big Grin ) 
BUT then I wanted to make them solid (filled in), and that's where I ran into trouble. 

At first I tried filling in the logo itself which is 2 closed shapes, but was having trouble determining a point inside each shape. That version runs pretty fast and looks good... when the flood fill is working (about half the time) - for that see attached "VanHalenizer2-05-17i.multi vectors.PAINT FILL.bas"). Maybe fixing this version is the ticket? 

So I changed tactics to fill around the shape with black and then use _ClearColor to get rid of the black, and voila, solid shape. Which brings us to the last version ("VanHalenizer2-05-23.bas"). It reliably produces the solid shapes, but is SLOOOOW (search "USE FLOOD FILL" to go right to the problem section).

I tried a couple of different flood fill methods which haven't made a difference, which is surprising, because back around May we had a thread about fast ways to do flood fill, and came up with some pretty good ones (this program compares the various methods).

If anyone has any suggestions that don't involve completely rewriting the program & vector logic (which took a long time to get right!), a 2nd set of eyes would be much appreciated...

Thanks...


Attached Files
.bas   VanHalenizer2-05-17.multi vectors.bas (Size: 172.33 KB / Downloads: 17)
.bas   VanHalenizer2-05-23.bas (Size: 190.75 KB / Downloads: 18)
.bas   VanHalenizer2-05-17b.multi vectors.PSYCHEDELIC!.bas (Size: 174.63 KB / Downloads: 15)
.bas   VanHalenizer2-05-17i.multi vectors.PAINT FILL.bas (Size: 185.94 KB / Downloads: 21)
Reply
#2
Quote:(Hey @BPlus, check out "VanHalenizer2-05-17b.multi vectors.PSYCHEDELIC!.bas"! [Image: biggrin.png] ) 

Oh hey that looks like like my Plasma coloring scheme, nice! I like the animation too. Smile

No maybe just a pallete of random colors? still cool!
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#3
Thanks, B! Your various eye candy programs have definitely been an inspiration!

The colors are not random - I actually put some effort into choosing each, then I just populated an array with the values in order of the spectrum. But no fancy math like in your proggies! 

Eventually I'll get this thing working right!  Tongue
Reply
#4
I got it working right - the solution I used was simply to store a "fill point" in the data for each shape. I think a more robust solution would be to come up with logic to find a point inside the shape, such a routine could come in handy for other projects, but I'm feeling too burnt out right now and it's not that important.
Reply
#5
Quote:I think a more robust solution would be to come up with logic to find a point inside the shape,

What kind of shapes are we talking about? Assuming 2D there are shapes created by points connected by lines that enclose a space which can be described by linear equations for lines and there are closed curves which have far more exotic formula descriptions. I suspect you are talking of the first case of which a triangle is simplest case and finding some point inside not difficult. For that take the midpoint of 2 points and then find midpoint of that point and the third point. I would say:

for triangle {(x1, y1), (x2, y2), (x3, y3)}

pt ((x3 + (x1 + x2)/2)/2, (y3 + (y1 + y2)/2)/2) will be inside it.
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#6
I tried doing the "centroid" of the triangle as you suggested, but that requires knowing 3 points whose middle lies enclosed in the shape. If you look at the V and H in the band logo here we see it may not be so easy if the starting point isn't the top left or top right. Once the point is found for the V and the H, it can be adjusted as the shapes change scale. So by robust I mean an algorithm that takes a set of points for one or more non-connected COMPLEX shapes and determines the "inside" point of each, WITHOUT a human having to tell it which points to use, where the start and end points can lie anywhere.
Reply
#7
I don't know if I understood correctly, but is it just about coloring the logo? If so, here is a simpler and faster solution. You do need an image, but it can also be easily converted directly into the source code.

In this example, you don't calculate anything at all. You use the image as a mask, according to which you then change the pixel color value with the _Mem command. It's much faster than calculating something and then coloring it.
If is needed coloring those shapes that are created with the Line command as vectors, so you can't use transparency there (for POINT) but this could be solved with the _MapTriangle command, where you map one pixel with transparency to three points. That then works the same as if you were coloring it, but it's much faster. I haven't studied this part of the program... I've already chosen my vacation, sorry.

Code: (Select All)


logo$ = "VHLogo.png"
Dim logo As Long
logo = _LoadImage(logo$, 32)
Const TotalLogos = 50

Dim As _MEM m, n
Dim NewColor As _Unsigned Long, Black As _Unsigned Long
Black = _RGB32(0)
Type LogoPos
    As Integer X, Y
    Handle As Long
    As Single Zoom, Xstep, Ystep
End Type
Dim ColoredLogo(1 To TotalLogos) As LogoPos
W = _Width(logo)
H = _Height(logo)
For EmptyImages = 1 To TotalLogos
    ColoredLogo(EmptyImages).Handle = _NewImage(W, H, 32)
Next
Virtual = _NewImage(W, H, 32)
m = _MemImage(logo)
n = _MemImage(Virtual)

'fill start values and logo colors
For Logos = 1 To TotalLogos
    NewColor = _RGBA32(255 * Rnd, 255 * Rnd, 255 * Rnd, 255 * Rnd)
    Do Until i& = m.SIZE - 4
        If _MemGet(m, m.OFFSET + i&, _Unsigned Long) = Black Then _MemPut n, n.OFFSET + i&, NewColor
        i& = i& + 4
    Loop
    i& = 0
    ColoredLogo(Logos).Handle = _CopyImage(Virtual, 32)
    _MemFill n, n.OFFSET, n.SIZE, 0 As _UNSIGNED LONG
    ColoredLogo(Logos).X = Rnd * 1024
    ColoredLogo(Logos).Y = Rnd * -H
    ColoredLogo(Logos).Zoom = (1 + Rnd * 10) / 15
    If Rnd * 10 > 3 Then o = -1 Else o = 1
    ColoredLogo(Logos).Xstep = (1 + Rnd * 3) / 2 * o
    ColoredLogo(Logos).Ystep = (1 + Rnd * 10) / 1.5

    If ColoredLogo(Logos).Y > -H * ColoredLogo(Logos).Zoom Then ColoredLogo(Logos).Y = -H * ColoredLogo(Logos).Zoom - 200
Next


Screen _NewImage(1024, 768, 32)

L = 0
Do Until _KeyHit
    L = L + 1
    If L > TotalLogos Then
        L = 1
        _Display
        _Limit 20
        Cls
    End If

    ColoredLogo(L).X = ColoredLogo(L).X + ColoredLogo(L).Xstep
    ColoredLogo(L).Y = ColoredLogo(L).Y + ColoredLogo(L).Ystep

    If ColoredLogo(L).Y > 768 + H Or ColoredLogo(L).X > 1024 + W Or ColoredLogo(L).X < -W Then 'restart logo if is out
        i& = 0
        _FreeImage ColoredLogo(L).Handle
        NewColor = _RGBA32(255 * Rnd, 255 * Rnd, 255 * Rnd, 255 * Rnd)
        Do Until i& = m.SIZE - 4
            If _MemGet(m, m.OFFSET + i&, _Unsigned Long) = Black Then _MemPut n, n.OFFSET + i&, NewColor
            i& = i& + 4
        Loop
        i& = 0
        ColoredLogo(L).Handle = _CopyImage(Virtual, 32)
        _MemFill n, n.OFFSET, n.SIZE, 0 As _UNSIGNED LONG
        ColoredLogo(L).X = Rnd * 1024
        ColoredLogo(L).Y = Rnd * -H
        ColoredLogo(L).Zoom = (1 + Rnd * 10) / 15
        If Rnd * 10 > 3 Then o = -1 Else o = 1        
        ColoredLogo(L).Xstep = (1 + Rnd * 3) / 2 * o
        ColoredLogo(L).Ystep = (1 + Rnd * 10) / 1.5
        If ColoredLogo(L).Y > -H * ColoredLogo(L).Zoom Then ColoredLogo(L).Y = -H * ColoredLogo(L).Zoom - 200
    End If
    r = W * ColoredLogo(L).Zoom
    _PutImage (ColoredLogo(L).X, ColoredLogo(L).Y)-(ColoredLogo(L).X + r, ColoredLogo(L).Y + r), ColoredLogo(L).Handle, 0
Loop


[Image: VHLogo.png]


Reply
#8
Thanks for sharing - very interesting. In this case, the image changes size, starting very small then getting bigger, and can't be pixellated. Also, there can be 50 or more of them moving on the screen at the same time, all different colors and sizes. I'd prefer not to rely on additional files such as PNG. But I'll play with your code when I get a chance, I could learn a thing or two. Thanks again, @petr!
Reply
#9
@Petr you inspired me!

Code: (Select All)
_Title "VHLogo SwapColor test"
Screen _NewImage(800, 700, 32) ' b+ 2025-11-08  
Randomize Timer
Dim Shared cN, pR, pG, pB

t& = _LoadImage("VHLogo2.png")

_PutImage , t& 'check our current image , OK
cc~& = Point(5, 5) ' back color to remove from image

Black~& = &HFF000000 ' black lines the color to change
While _KeyDown(27) = 0
    resetPlasma
    Cls
    scale = .1: rot = 0
    For x = 100 To 460 Step 2
        newT& = swapColor&(t&, Black~&, Plasma~&)
        _ClearColor cc~&, newT&
        RotoZoom23d x * 1.05, x, newT&, scale, scale, rot
        scale = scale + .008
        rot = rot + 2
        _FreeImage newT&
        _Display
        _Limit 30
    Next
    _Delay 1
Wend

' create new Image Handle for an image copy with a color changed from original image, returns new Handle&
'https://www.qb64.org/forum/index.php?topic=2451.0
' from Petr to Craz1000
Function swapColor& (oldHandle&, oldcolor~&, newcolor~&)
    Dim m As _MEM, c As _Unsigned Long, h As Long
    h = _CopyImage(oldHandle&, 32)
    m = _MemImage(h)
    Do Until a& = m.SIZE - 4
        a& = a& + 4
        c~& = _MemGet(m, m.OFFSET + a&, _Unsigned Long)
        If c~& = oldcolor~& Then _MemPut m, m.OFFSET + a&, newcolor~&
    Loop
    _MemFree m
    swapColor& = h
End Function

' tested in same rotozoom23d test code as original 2023-01-20
Sub RotoZoom23d (centerX As Long, centerY As Long, Image As Long, xScale As Single, yScale As Single, DRotation As Single)
    Dim As Single px(3), py(3), sinr, cosr ' thanks to James D Jarvis who fixed this on 2023/01/18
    Dim As Long IW, IH, i, x2, y2
    IW& = _Width(Image&): IH& = _Height(Image&)
    px(0) = -IW& / 2 * xScale: py(0) = -IH& / 2 * yScale: px(1) = -IW& / 2 * xScale: py(1) = IH& / 2 * yScale
    px(2) = IW& / 2 * xScale: py(2) = IH& / 2 * yScale: px(3) = IW& / 2 * xScale: py(3) = -IH& / 2 * yScale
    sinr! = Sin(-0.01745329 * DRotation): cosr! = Cos(-0.01745329 * DRotation)
    For i& = 0 To 3
        ' x2& = (px(i&) * cosr! + sinr! * py(i&)) * xScale + centerX: y2& = (py(i&) * cosr! - px(i&) * sinr!) * yScale + centerY
        x2& = (px(i&) * cosr! + sinr! * py(i&)) + centerX: y2& = (py(i&) * cosr! - px(i&) * sinr!) + centerY
        px(i&) = x2&: py(i&) = y2&
    Next
    ' might not need Seamless?
    _MapTriangle _Seamless(0, 0)-(0, IH& - 1)-(IW& - 1, IH& - 1), Image& To(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
    _MapTriangle _Seamless(0, 0)-(IW& - 1, 0)-(IW& - 1, IH& - 1), Image& To(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
End Sub

Function Plasma~& ()
    cN = cN + 1 ''Dim Shared cN, pR, pG, pB
    Plasma~& = _RGB32(127 + 127 * Sin(pR * cN), 127 + 127 * Sin(pG * cN), 127 + 127 * Sin(pB * cN))
End Function

Sub resetPlasma ()
    ''Dim Shared cN, pR, pG, pB
    pR = Rnd ^ 2: pG = Rnd ^ 2: pB = Rnd ^ 2: cN = 0
End Sub

   

Mod of Petr image with zip:


Attached Files
.zip   VHLogo2 SwapColor test.zip (Size: 6.61 KB / Downloads: 14)
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#10
A little mod of numbers:
Code: (Select All)
_Title "VHLogo SwapColor test"
Screen _NewImage(800, 700, 32) ' b+ 2025-11-08
Randomize Timer
Dim Shared cN, pR, pG, pB

t& = _LoadImage("VHLogo2.png")

_PutImage , t& 'check our current image , OK
cc~& = Point(5, 5) ' back color to remove from image

Black~& = &HFF000000 ' black lines the color to change
While _KeyDown(27) = 0
    resetPlasma
    Cls
    scale = .1: rot = 0
    For x = 100 To 460 Step 10
        newT& = swapColor&(t&, Black~&, Plasma~&)
        _ClearColor cc~&, newT&
        RotoZoom23d x * 1.05, x, newT&, scale, scale, rot
        scale = scale + .02
        rot = rot + 10
        _FreeImage newT&
        _Display
        _Limit 30
    Next
    _Delay 1
Wend

' create new Image Handle for an image copy with a color changed from original image, returns new Handle&
'https://www.qb64.org/forum/index.php?topic=2451.0
' from Petr to Craz1000
Function swapColor& (oldHandle&, oldcolor~&, newcolor~&)
    Dim m As _MEM, c As _Unsigned Long, h As Long
    h = _CopyImage(oldHandle&, 32)
    m = _MemImage(h)
    Do Until a& = m.SIZE - 4
        a& = a& + 4
        c~& = _MemGet(m, m.OFFSET + a&, _Unsigned Long)
        If c~& = oldcolor~& Then _MemPut m, m.OFFSET + a&, newcolor~&
    Loop
    _MemFree m
    swapColor& = h
End Function

' tested in same rotozoom23d test code as original 2023-01-20
Sub RotoZoom23d (centerX As Long, centerY As Long, Image As Long, xScale As Single, yScale As Single, DRotation As Single)
    Dim As Single px(3), py(3), sinr, cosr ' thanks to James D Jarvis who fixed this on 2023/01/18
    Dim As Long IW, IH, i, x2, y2
    IW& = _Width(Image&): IH& = _Height(Image&)
    px(0) = -IW& / 2 * xScale: py(0) = -IH& / 2 * yScale: px(1) = -IW& / 2 * xScale: py(1) = IH& / 2 * yScale
    px(2) = IW& / 2 * xScale: py(2) = IH& / 2 * yScale: px(3) = IW& / 2 * xScale: py(3) = -IH& / 2 * yScale
    sinr! = Sin(-0.01745329 * DRotation): cosr! = Cos(-0.01745329 * DRotation)
    For i& = 0 To 3
        ' x2& = (px(i&) * cosr! + sinr! * py(i&)) * xScale + centerX: y2& = (py(i&) * cosr! - px(i&) * sinr!) * yScale + centerY
        x2& = (px(i&) * cosr! + sinr! * py(i&)) + centerX: y2& = (py(i&) * cosr! - px(i&) * sinr!) + centerY
        px(i&) = x2&: py(i&) = y2&
    Next
    ' might not need Seamless?
    _MapTriangle _Seamless(0, 0)-(0, IH& - 1)-(IW& - 1, IH& - 1), Image& To(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
    _MapTriangle _Seamless(0, 0)-(IW& - 1, 0)-(IW& - 1, IH& - 1), Image& To(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
End Sub

Function Plasma~& ()
    cN = cN + 1 ''Dim Shared cN, pR, pG, pB
    Plasma~& = _RGB32(127 + 127 * Sin(pR * cN), 127 + 127 * Sin(pG * cN), 127 + 127 * Sin(pB * cN))
End Function

Sub resetPlasma ()
    ''Dim Shared cN, pR, pG, pB
    pR = Rnd ^ 2: pG = Rnd ^ 2: pB = Rnd ^ 2: cN = 0
End Sub

   
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  simple 3d starfield & wireframe or vector graphics revisited madscijr 5 263 01-31-2026, 09:41 PM
Last Post: Pete
  trouble building ansiprint by a740g hsiangch_ong 2 578 01-09-2025, 12:57 AM
Last Post: hsiangch_ong
  Having trouble Windows command line SORT via SHELL GTC 19 4,367 08-26-2023, 04:19 AM
Last Post: GTC
  How do I paint a shape? PhilOfPerth 21 3,921 06-28-2023, 10:09 PM
Last Post: TempodiBasic
Photo Ellipse trouble james2464 14 2,998 08-25-2022, 10:52 PM
Last Post: james2464

Forum Jump:


Users browsing this thread: 1 Guest(s)