GFX_MATH.bi (Const's, Macro's & Func's)

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

GFX_MATH.bi (Const's, Macro's & Func's)

Post by MrSwiss »

Hi all,

over time I've collected, what I consider *essentials* to work with FB's GFX-lib.
I've made it all, into an easy to include .bi file, which I want to share here.
Sources, other than my own stuff, are noted, however, limited to my memory.
(if I've made any mistakes, in quoting sources, please let me know ...)

Contains:
  • constants: PI (Π), PI2 (double Π), GolderRatio -- others are used by macro's
  • all Macro's are *single line*, aka: #Define (not listed, quite a few)
  • two Function's: Contrast(), CContrast()
  • updated: 2018-04-12 (added single alpha-/color-channel getters/setters)
Here goes GFX_MATH.bi:

Code: Select all

' GFX_MATH.bi -- mathematics for fbGFX (Singles only) -- 2016/18, MrSwiss
'
' update     : 2017-05-06   changed: added Smap (renamed map to Imap)
' last update: 2018-04-11/12changed: added color-channel getters/setters
'
' some math const(s) + macro(s) + conrast Func's -- #Define = single line macro
'
' forum: https://www.freebasic.net/forum/viewtopic.php?f=7&t=25635&p=231423

#Ifndef __GFX_MATH_BI__
#Define __GFX_MATH_BI__

' from: FB-manual (maybe: Forum??)
Const As Single PI      = Atn( 1f ) * 4f	' semi-circle, in RADians
Const As Single PI2     = Atn( 1f ) * 8f	' full-circle, RAD
' original, by bluatigro (I assume)
Const As Single GoldenRatio = ( Sqr(5f) - 1f ) / 2f
' original, by FB-manual
Const As Single D2R     = pi / 180f		    ' conversion factor, DEG --> RAD
Const As Single R2D     = 180f / pi		    ' conversion factor, RAD --> DEG
' original, by MrSwiss (I don't want to have to remember the Const's names!)
#Define RAD(d)          ( CSng(d * D2R) )	' conversion macro, DEG --> RAD
#Define DEG(r)          ( CSng(r * R2D) )	' conversion macro, RAD --> DEG

Randomize(Timer, 3) ' seed for Rnd(), Mersenne Twister (FB-default)
' original, by dodicat, modified for returning defined variable type, by MrSwiss
#Define LRange(l, h)    ( CLng(Rnd() * (h - l) + l) )   ' general use, Long    (32bit)
#Define LIRange(l, h)   ( CLngInt(Rnd() * (h - l) + l) )' general use, LongInt (64bit)
#Define IRange(l, h)    ( CInt(Rnd() * (h - l) + l) )   ' general use, Integer (FBC-bitness)
#Define SRange(l, h)    ( CSng(Rnd() * (h - l) + l) )   ' general use, Single  (GFX-Float, 32bit)
' original, by dodicat modified: MrSwiss (removed brackets around var's), added brackets _
#define Imap(a,b,x,c,d) ( (d - c) * (x - a) \ (b - a) + c ) ' around 'whole body' (readability)
#define Smap(a,b,x,c,d) ( (d - c) * (x - a) / (b - a) + c )

' -- all Color stuff, original, by MrSwiss --
#Define ClrRng(l, h)    ( CULng(Rnd() * (h - l) + l) )  ' Color, aka: ULong
' random Color RGB range, ULong (full alpha, always)
#Define RndRGB          ( CULng(Rnd() * &hFFFFFF + &hFF000000ul) )
' random Color ARGB range, ULong (random Alpha & Color)
#Define RndARGB         ( CULng(Rnd() * &hFFFFFFFFul) )
' color inverter, not touching/changing of Alpha-Chan.
#Define InvClr(c)       ( CULng(c Xor &h00FFFFFF) )
' color inverter, incl. Alpha
#Define InvAClr(c)      ( CULng(c Xor &hFFFFFFFFul) )

' 2018-04-12, function like MACRO's (getters) for alpha-/color-channel's values (UByte, from 32-bit color)
#Define ga_ch(c)        ( CULng(c) Shr 24 And 255 )         ' get alpha-channel
#Define gr_ch(c)        ( CULng(c) Shr 16 And 255 )         ' get red-channel
#Define gg_ch(c)        ( CULng(c) Shr  8 And 255 )         ' get green-channel
#Define gb_ch(c)        ( CULng(c)        And 255 )         ' get blue-channel
' 2018-04-11, function like MACRO's (setters) for alpha-/color-channel's (32-bit color, ULong)
#Define sa_ch(c,a)      ( CULng(c) + ((a And 255) Shl 24) ) ' set alpha-channel
#Define sr_ch(c,r)      ( CULng(c) + ((r And 255) Shl 16) ) ' set red-channel
#Define sg_ch(c,g)      ( CULng(c) + ((g And 255) Shl  8) ) ' set green-channel
#Define sb_ch(c,b)      ( CULng(c) +  (b And 255) )         ' set blue-channel

' 2017-04-28, by MrSwiss (simplified version, of below Function: CContrast())
' reason: with CContrast() and, many diff. colors, it's too quickly Carnival-like!
Function Contrast ( ByVal cin As ULong _    ' param:  'in' ARGB-Color
                    ) As ULong              ' result: ARGB-Color (black or white)
    ' if NOT full alpha --> set it to full alpha (for easy evaluation)
    If CPtr(UByte Ptr, @cin)[3] < 255 Then CPtr(UByte Ptr, @cin)[3] = 255
    ' bright half of RGB range --> return black
    If cin > &hFF7F7F7F Then Return &hFF000000ul
    ' dark half of RGB range   --> return white
    Return &hFFFFFFFFul
End Function

' make one random colour over another different: original by dodicat, recoded: _
' 2017-04-28, by MrSwiss -- reason: more efficient code & independent of macro's
Function CContrast( ByVal cin As ULong _    ' param:  'in' ARGB-Color
                    ) As ULong              ' result: ARGB-Color 
    Dim As UByte    a = CPtr(Ubyte Ptr, @cin)[3], _ ' save curr. alpha-chan
                    r = CPtr(Ubyte Ptr, @cin)[2], _ ' save curr. red-chan
                    g = CPtr(Ubyte Ptr, @cin)[1], _ ' save curr. green-chan
                    b = CPtr(Ubyte Ptr, @cin)[0], _ ' save curr. blue-chan
                    r2, g2, b2                      ' temp. var's (uninit)
    Dim As Boolean  rf, gf, bf                      ' color channels flags
    ' minimal required difference from original: 127 / &h7F (aka: 50% of range)
    While Not rf    ' run's only: until new red val found
        r2 = CUByte(Rnd() * 255) : If Abs(r - r2) > 126 Then rf = TRUE
    Wend
    While Not gf    ' run's only: until new green val found
        g2 = CUByte(Rnd() * 255) : If Abs(g - g2) > 126 Then gf = TRUE
    Wend
    While Not bf    ' run's only: until new blue val found
        b2 = CUByte(Rnd() * 255) : If Abs(b - b2) > 126 Then bf = TRUE
    Wend
    ' got them all: return result
    Return RGBA(r2, g2, b2, a)  ' leave alpha unchanged (use saved original)
End Function


#EndIf  ' __GFX_MATH_BI__
and a short Demo (uses Grid.bas), which can be found at the given location, here in the Forum:

Code: Select all

' Demo1_GFX_MATH_bi.bas -- 2017-05-02, by MrSwiss
' last update: 2017-05-02   changed: nothing yet

' compile with: -s GUI

#Include "GFX_MATH.bi"          ' see: https://freebasic.net/forum/viewtopic.php?f=7&t=25635
#Include Once "Grid.bas"        ' see: https://freebasic.net/forum/viewtopic.php?f=7&t=24997

' NOTE: if only RGB() is used with GFX_ALPHA_PRIMITIVES, nothing is shown (alpha = 0)
Dim As ULong    c1 = RGBA(255,   0,   0, 191), _    ' red 3/4 alpha = 1/4 transparent
                c2 = RGBA(127, 127, 127, 255), _    ' grey 100% alpha = opaque (0% trans)
                c3 = RGBA(  0,   0, 255, 191)       ' blue (as red)
' for program execution control
Dim As Boolean  quit = FALSE, sw = TRUE                 ' flags

' ===== MAIN =====
ScreenRes(641, 641, 32, 2, 64)      ' GFX_ALPHA_PRIMITIVES = &h40 / 64 dec; double buffer
'Randomize(Timer, 3)                 ' seed for RND(), set in GFX_MATH.bi
c2 = RGBA(255, 255, 255, 255)       ' redefine c2 to: white / opaque

Do
    ' cell size 68 (square), border 48 = cells: h/v = 8/8 (aka: chessboard)
    Grid(640, 640, 68, 48,, c2)     ' grid color = c2 (default = medium-gray)
    For j As UInteger = 1 To 8      ' rows (cells vertical)
        Var y = j * 68 + 24         ' calc. injection point y (paint, aka: flood-fill)
        For i As UInteger = 1 To 8  ' columns (cells horizontal)
            Var x = i * 68 + 24     ' calc. injection point x (paint)
            If sw Then
                Paint (x, y), ClrRng(&h7F7F7F7F, &hFFFFFFFF), c2    ' in GFX_MATH.bi
            Else
                ' random color RGB range only (100% alpha always)
                Paint (x, y), RndRGB, c2    ' in GFX_MATH.bi
            EndIf
        Next
        If Len(InKey()) Then quit = TRUE : Exit For ' exit outer For loop (only)
        sw = Not sw                 ' change macro used, every new row
    Next
    Flip
    If quit Then Exit Do
    Sleep 1500, 1 : Cls
Loop
' ===== END-MAIN =====  ' ----- EOF -----
[edit: 2017-05-06] Another test code, without additional #Includes:

Code: Select all

' GFX_MATH_Test2.bas -- 2017-05-06, by MrSwiss
' last update: 2017-05-06   changed: ---

' compile with: -s GUI

#Include Once "GFX_MATH.bi"     ' see: https://freebasic.net/forum/viewtopic.php?f=7&p=231423#p231423

' for program execution control
Dim As Boolean  quit = FALSE    ' flag(s)

' ===== MAIN =====
ScreenRes(641, 641, 32, 2, 64)  ' GFX_ALPHA_PRIMITIVES = &h40 / 64 dec; double buffer

Do
    For j As UInteger = 0 To 10         ' rows (steps vertical)
        Var y = j * 55                  ' calc. y-axis pos.
        For i As UInteger = 0 To 10     ' columns (steps horizontal)
            Var x = i * 55              ' calc. x-axis pos.
            Var h = IRange(25, 85)      ' get a random height between 25 and 85
            Var w = IRange(35, 150)     ' get a random width between 35 and 150
            Line (x, y)-Step(w, h), RndARGB, BF ' random color full ARGB range
        Next
        If Len(InKey()) Then quit = TRUE : Exit For ' exit outer For loop (only)
    Next
    Flip
    If quit Then Exit Do                ' end prog. (if quit = TRUE)
    Sleep 1000, 1 : Cls                 ' give user some time, to 'look at it'
Loop
' ===== END-MAIN =====  ' ----- EOF -----
Post Reply