Lines using Vectors - DEMO

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

Lines using Vectors - DEMO

Postby MrSwiss » Sep 06, 2018 19:46

This DEMO is about my current way to do Lines, with the 'help' of vectors.

To start with, a few thoughts on details covered:
  • Constants used to define stuff for: fbGFX, colors, screen definitions.
  • Keyword Erase (seldom seen in code), erases a array (frees used memory).
  • Separation of initializer-code, from run-code (aka: MAIN-LOOP).
  • Separation of seldom used code-part from MAIN ('extender' Sub askUser()).
  • Separation of Function Calc_V2D(...) As V2D (heavily used, by initializer-code).
  • Consequent release of used resources, as soon as finished, using them.
    Obvious advantage is: nothing to remember 'to free', at code end.
Result of all above points is:
compact, fast running code in main-loop, with: good readability (lots of comments).

EDIT: a few code changes made, see: here! 2018-09-10

For more detail, refer to comments in the code itself:

Code: Select all

' Vectors&Lines.bas -- 2018-09-10, MrSwiss
'
' compile: -s gui
'

Type V2D                                ' a simple 2 dimension vector
    As Single   x, y                    ' x-axis pos. | y-axis pos.
End Type                                ' acessible from everywhere

Type anyLine                            ' a simple line type (24 bytes), both compilers 32/64
  Private:                              ' NO direct type's/variable's access
    As V2D      v1, v2                  ' start/end vector's (define the line)
    As ULong    c1, res                 ' color | res is for 8 byte alignment (FBC x64)
  Public:                               ' minimal interface (no fancy OOP, here)
    Declare Sub init(ByVal As Single, ByVal As Single, ByVal As Single, ByVal As Single, ByVal As ULong)
    Declare Sub show(ByVal As Boolean=TRUE) ' to enable skipping of a instance, e.g. in a loop
End Type

Sub anyLine.init( _                     ' pre-set the line's pos. & color
    ByVal v1x   As Single, _            ' vector 1 - x
    ByVal v1y   As Single, _            ' vector 1 - y
    ByVal v2x   As Single, _            ' vector 2 - x
    ByVal v2y   As Single, _            ' vector 2 - y
    ByVal clr   As ULong _              ' color (32 bit's)
    )
    With This
        .v1.x = v1x : .v1.y = v1y       ' assign values
        .v2.x = v2x : .v2.y = v2y
        .c1 = clr                       ' don't touch res (its reserved!)
    End With
End Sub

Sub anyLine.show( _                     ' line to screen
    ByVal vis   As Boolean = TRUE _     ' OPTIONAL: skip if FALSE (default TRUE)
    )
    If Not vis Then Exit Sub            ' FALSE --> get out
    With This
        Line (.v1.x, .v1.y)-(.v2.x, .v2.y), c1  ' line to screen
    End With
End Sub
' end type

' general constants for fbGFX
Const As Double pi = 4 * Atn(1), d2r = pi / 180.0, r2d = 180.0 / pi
' define some colors (32 bit's)
Const As ULong  red = &hFFFF0000, blue = &hFF0000FF, green = &hFF00FF00, _
                white = &hFFFFFFFF, black = &hFF000000
' define screen (keep 4 : 3 ratio) tested from: 641x481 to: 1281x961 (e.g. 801x601)
Const As UShort scr_w = 1025, scr_h = 769, scr_cx = scr_w \ 2, _ ' only change w/h definitions!
                scr_cy = scr_h \ 2, scr_cd = 32, scr_pg = 2, scr_flg = 0
Const As Single DPI = .75               ' high DPI = 150%, change to 1, otherwise!

' declare external "helper" Function (external to type anyLine), uses only V2D
Declare Function Calc_V2D(ByVal As Single, ByVal As Single, ByVal As Single, ByVal As Single) As V2D

' ===== MAIN =====
ScreenRes(scr_w, scr_h, scr_cd, scr_pg, scr_flg)    ' using (above) constants for screen definition
ScreenSet(1, 0)                         ' use double buffering
Color(black, white) : Cls               ' pre-set default colors | set them

Dim As anyLine  aLine(0 To 360), _      ' 1° step, anyLine (defined below), red, 360°
                bLine(0 To 90), _       ' 3° step, anyLine (defined below), blue, 90°
                cLine(0 To 90)          ' 1° step, anyLine (defined below), green, 90°
ReDim As V2D    vs(0 To 360), _         ' 1° step, start vector (helper), 360°
                ve(0 To 360), _         ' 1° step, end vector (helper), 360°
                ve1(0 To 90)            ' 1° step, end vector (helper), 90°
Dim As ULong    cnt = 0, _              ' counter (used as array index)
                off = (scr_cy \ 16) * DPI, _    ' radius offset (with high DPI correction)
                radius = scr_cy * DPI * .55 ' radius (based on scr_h \ 2, with high DPI correction)
Dim As Boolean  qflg = FALSE            ' quit flag (for main-loop)

' initialize anyLine() array's ... (using "helper" array's)
For ang As UInteger = LBound(aLine) To UBound(aLine)    ' full circle 1° step
    vs(ang) = Calc_V2D(scr_cx, scr_cy, ang * 1.03, ang) ' in-/outside of circle (below)
    ve(ang) = Calc_V2D(scr_cx, scr_cy, radius, ang)     ' strictly "on circle" (below)
    aLine(ang).init(vs(ang).x, vs(ang).y, ve(ang).x, ve(ang).y, red)    ' initialize line's array
Next
For a2 As UInteger = LBound(bLine) To UBound(bLine)     ' cLine() has the same size!
    ve1(a2) = Calc_V2D(scr_cx, scr_cy, radius + off, a2) ' initialize 3rd helper array
    bLine(a2).init(30, scr_h - 30, vs(a2 * 3).x, vs(a2 * 3).y, blue)    ' 3° step (a2 * 3)
    cLine(a2).init(scr_w - 30, scr_h - 30, ve1(a2).x, ve1(a2).y, green) ' 1° step
Next
Erase vs, ve, ve1                       ' the helper's are no longer needed, destroy them
Circle(scr_cx, scr_cy), radius          ' frame the line's (in-/outside), default = black
' a little main-loop extension Sub
Declare Sub askUser(ByRef As ULong, ByRef As Boolean, ByVal As ULong)

' main-loop start
Do
    If cnt < 91 Then                    ' assure: to NOT "blow", the small array's
        bLine(cnt).show                 ' fast and rough 90° * 3 (result: 270°)
        cLine(cnt).show                 ' fast and fine 90° * 1
    End If
    aLine(cnt).show : Flip              ' show 1 line per run (360°) | copy screen page
    Sleep(10, 1) : cnt += 1             ' slow it slightly down | incr. counter (index)
    If cnt = 360 Then                   ' finished with graphics, ask user: repeat/quit
        askUser(cnt, qflg, radius)      ' a simple extension of the loop (could be inlined too)
    End If
Loop Until qflg
' ===== End-MAIN =====

' implement loop-extension
Sub askUser( _                          ' external user Q & A & the required actions!
    ByRef c     As ULong, _             ' counter (may be modified = reset)
    ByRef q     As Boolean, _           ' quit flag (may be modified = set)
    ByVal r     As ULong _              ' radius (for circle, copy only)
    )
    Var m = "Re-run program loop? [y/N]"    ' user message (Var = String)
    While Len(InKey()) > 0 : Wend       ' assure: keyboard buffer = empty
    Draw String (30, 30), m             ' position | message (default: exit, aka "N")
    Flip : Sleep                        ' show it | wait | get user answer
    If LCase(InKey()) = "y" Then        ' only if "y"/"Y" pressed
        Cls : c = 0                     ' prep. for re-run | clear screen | reset c
        Circle(scr_cx, scr_cy), r       ' re-draw circle then, back to: main-loop
    Else                                ' anything NOT "y"/"Y", prep. exit
        q = TRUE                        ' set quit flag (to exit main-loop)
    End If
End Sub

' implement "helper"
Function Calc_V2D(_                     ' angle/distance based calc. of a vector
    ByVal vsx   As Single, _            ' vector (start x pos.)
    ByVal vsy   As Single, _            ' vector (start y pos.)
    ByVal radi  As Single, _            ' radius (= distance)
    ByVal angl  As Single _             ' angle (in degrees, conv. to radian internal)
    ) As V2D                            ' calculated vector (start or end)
    Dim As V2D  ret                     ' define return type
    Var rad = angl * d2r                ' once, instead of twice (speed/readability)
    ret.x = vsx + Cos(rad) * radi       ' init. x pos. (of vector)
    ret.y = vsy + Sin(rad) * radi       ' init. y pos. (of vector)
    Return ret                          ' return the calculated type
End Function
'-----EOF -----
If you don't run the code, you don't know if you miss something, or not. :-))
Last edited by MrSwiss on Sep 10, 2018 14:10, edited 2 times in total.
dodicat
Posts: 5254
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Lines using Vectors - DEMO

Postby dodicat » Sep 06, 2018 22:07

That's rather nice Mr Swiss.
MrSwiss
Posts: 2817
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Lines using Vectors - DEMO

Postby MrSwiss » Sep 08, 2018 15:18

Thank you, dodicat.

@all,
There is one thing I've not mentioned above:
  • use of odd screen dimensions width/height
There is, as almost always, a reason 'behind the madness':
if one divides a even int-value by 2, you'll get: nn.5 (which rounds up to next int-value),
this means: the graphics is always slightly towards right/bottom of the screen.
With odd values by contrast, you'll get a 'true', physical pixel straight away (check with
a circle, inside a sqare, to spot the difference!), aka: truely centered graphics!
paul doe
Posts: 804
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Lines using Vectors - DEMO

Postby paul doe » Sep 09, 2018 6:59

Functional, but you're making a couple of wrong assumptions:
MrSwiss wrote:
  • Keyword Erase (seldom seen in code), erases a array (frees used memory).
  • Consequent release of used resources, as soon as finished, using them.
    Obvious advantage is: nothing to remember 'to free', at code end.

Problem is, you're not actually freeing anything (since the arrays are static), just zeroing them out. The documentation clearly states this. EDIT: It's even more clear now. Thanks, fxm.
BTW, if you use static allocation, there's no need to 'remember' to free anything, since it's done automatically at the end of the program anyways. This would be more like what you intend (or simply make the arrays dynamic):

Code: Select all

/'
  ...
'/
scope
  Dim As V2D      vs(0 To 360), _         ' 1° step, start vector (helper), 360°
                  ve(0 To 360), _         ' 1° step, end vector (helper), 360°
                  ve1(0 To 90)            ' 1° step, end vector (helper), 90°
  ' initialize anyLine() array's ... (using "helper" array's)
  For ang As UInteger = LBound(aLine) To UBound(aLine)    ' full circle 1° step
      vs(ang) = Calc_V2D(scr_cx, scr_cy, ang * 1.03, ang) ' in-/outside of circle (below)
      ve(ang) = Calc_V2D(scr_cx, scr_cy, radius, ang)     ' strictly "on circle" (below)
      aLine(ang).init(vs(ang).x, vs(ang).y, ve(ang).x, ve(ang).y, red)    ' initialize line's array
  Next
  For a2 As UInteger = LBound(bLine) To UBound(bLine)     ' cLine() has the same size!
      ve1(a2) = Calc_V2D(scr_cx, scr_cy, radius + off, a2) ' initialize 3rd helper array
      bLine(a2).init(30, scr_h - 30, vs(a2 * 3).x, vs(a2 * 3).y, blue)    ' 3° step (a2 * 3)
      cLine(a2).init(scr_w - 30, scr_h - 30, ve1(a2).x, ve1(a2).y, green) ' 1° step
  Next
end scope
/'
  ...
'/

MrSwiss wrote:@all,
There is one thing I've not mentioned above:
  • use of odd screen dimensions width/height
There is, as almost always, a reason 'behind the madness':
...

Seems like a neat idea in theory, but what one hand gives, the other takes away. Try this one:

Code: Select all

' Vectors&Lines.bas -- 2018-09-06, MrSwiss
'
' compile: -s gui
'
#include once "fbgfx.bi"

Type V2D                                ' a simple 2 dimension vector
    As Single   x, y                    ' x-axis pos. | y-axis pos.
End Type                                ' acessible from everywhere

Type anyLine                            ' a simple line type (24 bytes), both compilers 32/64
  Private:                              ' NO direct type's/variable's access
    As V2d      v1, v2                  ' start/end vector's (define the line)
    As ULong    c1, res                 ' color | res is for 8 byte allignment (FBC x64)
  Public:                               ' minimal interface (no fancy OOP, here)
    Declare Sub init(ByVal As Single, ByVal As Single, ByVal As Single, ByVal As Single, ByVal As ULong)
    Declare Sub show(ByVal As Boolean=TRUE) ' to enable skipping of a instance, e.g. in a loop
End Type

Sub anyLine.init( _                     ' pre-set the line's pos. & color
    ByVal v1x   As Single, _            ' vector 1 - x
    ByVal v1y   As Single, _            ' vector 1 - y
    ByVal v2x   As Single, _            ' vector 2 - x
    ByVal v2y   As Single, _            ' vector 2 - y
    ByVal clr   As ULong _              ' color (32 bit's)
    )
    With This
        .v1.x = v1x : .v1.y = v1y       ' assign values
        .v2.x = v2x : .v2.y = v2y
        .c1 = clr                       ' don't touch res (its reserved!)
    End With
End Sub

Sub anyLine.show( _                     ' line to screen
    ByVal vis   As Boolean = TRUE _     ' OPTIONAL: skip if FALSE (default TRUE)
    )
    If Not vis Then Exit Sub            ' FALSE --> get out
    With This
        Line (.v1.x, .v1.y)-(.v2.x, .v2.y), c1  ' line to screen
    End With
End Sub
' end type

' general constants for fbGFX
Const As Double pi = 4 * Atn(1), d2r = pi / 180.0, r2d = 180.0 / pi
' define some colors (32 bit's)
Const As ULong  red = &hFFFF0000, blue = &hFF0000FF, green = &hFF00FF00, _
                white = &hFFFFFFFF, black = &hFF000000
' define screen (keep 4 : 3 ratio) tested from: 641x481 to: 1281x961 (e.g. 801x601)
Const As UShort scr_w = 1025, scr_h = 769, scr_cx = scr_w \ 2, _ ' only change w/h definitions!
                scr_cy = scr_h \ 2, scr_cd = 32, scr_pg = 2, scr_flg = fb.GFX_FULLSCREEN
Const As Single DPI = .75               ' high DPI = 150%, change to 1, otherwise!

' declare external "helper" Function (external to type anyLine), uses only V2D
Declare Function Calc_V2D(ByVal As Single, ByVal As Single, ByVal As Single, ByVal As Single) As V2D

' ===== MAIN =====
ScreenRes(scr_w, scr_h, scr_cd, scr_pg, scr_flg)    ' using (above) constants for screen definition
ScreenSet(1, 0)                         ' use double buffering
Color(black, white) : Cls               ' pre-set default colors | set them

Dim As anyLine  aLine(0 To 360), _      ' 1° step, anyLine (defined below), red, 360°
                bLine(0 To 90), _       ' 3° step, anyLine (defined below), blue, 90°
                cLine(0 To 90)          ' 1° step, anyLine (defined below), green, 90°
Dim As V2D      vs(0 To 360), _         ' 1° step, start vector (helper), 360°
                ve(0 To 360), _         ' 1° step, end vector (helper), 360°
                ve1(0 To 90)            ' 1° step, end vector (helper), 90°
Dim As ULong    cnt = 0, off = scr_cy \ 16, _   ' counter (used as array index) | radius offset
                radius = scr_cy * DPI * .55 ' radius (based on scr_h \ 2 with high DPI correction)
Dim As Boolean  qflg = FALSE            ' quit flag (for main-loop)

' initialize anyLine() array's ... (using "helper" array's)
For ang As UInteger = LBound(aLine) To UBound(aLine)    ' full circle 1° step
    vs(ang) = Calc_V2D(scr_cx, scr_cy, ang * 1.03, ang) ' in-/outside of circle (below)
    ve(ang) = Calc_V2D(scr_cx, scr_cy, radius, ang)     ' strictly "on circle" (below)
    aLine(ang).init(vs(ang).x, vs(ang).y, ve(ang).x, ve(ang).y, red)    ' initialize line's array
Next
For a2 As UInteger = LBound(bLine) To UBound(bLine)     ' cLine() has the same size!
    ve1(a2) = Calc_V2D(scr_cx, scr_cy, radius + off, a2) ' initialize 3rd helper array
    bLine(a2).init(30, scr_h - 30, vs(a2 * 3).x, vs(a2 * 3).y, blue)    ' 3° step (a2 * 3)
    cLine(a2).init(scr_w - 30, scr_h - 30, ve1(a2).x, ve1(a2).y, green) ' 1° step
Next
Erase vs, ve, ve1                       ' the helper's are no longer needed, destroy them
Circle(scr_cx, scr_cy), radius          ' frame the line's (in-/outside), default = black
' a little main-loop extension Sub
Declare Sub askUser(ByRef As ULong, ByRef As Boolean, ByVal As ULong)

' main-loop start
Do
    If cnt < 91 Then                    ' assure: to NOT "blow", the small array's
        bLine(cnt).show                 ' fast and rough 90° * 3 (result: 270°)
        cLine(cnt).show                 ' fast and fine 90° * 1
    End If
    aLine(cnt).show : Flip              ' show 1 line per run (360°) | copy screen page
    Sleep(10, 1) : cnt += 1             ' slow it slightly down | incr. counter (index)
    If cnt = 360 Then                   ' finished with graphics, ask user: repeat/quit
        askUser(cnt, qflg, radius)      ' a simple extension of the loop (could be inlined too)
        If qflg Then Erase aLine, bLine, cLine  ' no longer needed (clean up: free mem.)
    End If
Loop Until qflg
' ===== End-MAIN =====

' implement loop-extension
Sub askUser( _                          ' external user Q & A & the required actions!
    ByRef c     As ULong, _             ' counter (may be modified = reset)
    ByRef q     As Boolean, _           ' quit flag (may be modified = set)
    ByVal r     As ULong _              ' radius (for circle, copy only)
    )
    Var m = "Re-run program loop? [y/N]"    ' user message (Var = String)
    While Len(InKey()) > 0 : Wend       ' assure: keyboard buffer = empty
    Draw String (30, 30), m             ' position | message (default: exit, aka "N")
    Flip : Sleep                        ' show it | wait | get user answer
    If LCase(InKey()) = "y" Then        ' only if "y"/"Y" pressed
        Cls : c = 0                     ' prep. for re-run | clear screen | reset c
        Circle(scr_cx, scr_cy), r       ' re-draw circle then, back to: main-loop
    Else                                ' anything NOT "y"/"Y", prep. exit
        q = TRUE                        ' set quit flag (to exit main-loop)
    End If
End Sub

' implement "helper"
Function Calc_V2D(_                     ' angle/distance based calc. of a vector
    ByVal vsx   As Single, _            ' vector (start x pos.)
    ByVal vsy   As Single, _            ' vector (start y pos.)
    ByVal radi  As Single, _            ' radius (= distance)
    ByVal angl  As Single _             ' angle (in degrees, conv. to radian internal)
    ) As V2D                            ' calculated vector (start or end)
    Dim As V2D  ret                     ' define return type
    Var rad = angl * d2r                ' once, instead of twice (speed/readability)
    ret.x = vsx + Cos(rad) * radi       ' init. x pos. (of vector)
    ret.y = vsy + Sin(rad) * radi       ' init. y pos. (of vector)
    Return ret                          ' return the calculated type
End Function
'-----EOF -----

It's essentially the same code, but it requests a full-screen mode. Now, depending on your card, this can take anywhere from 3-12 seconds to try and set the video mode requested. It obviously fails, so it finally falls back to a windowed mode (which is not what the code requested).
On older monitors you could get away with this, but not on modern monitors with physical resolution. It's always safer to enumerate the available modes and pick one from there (if you're doing full-screen stuff, of course):

Code: Select all

namespace gfx
  type FullScreenVideoModes
    public:
      declare constructor()
      declare constructor( _
        byval as integer )
      declare destructor()
     
      declare property count() as integer
      declare property width( _
        byval as integer ) as short
      declare property height( _
        byval as integer ) as short
     
      declare function isAvailable( _
        byval as integer, byval as integer ) as boolean
   
    private:
      declare sub addItem( _
        byval as long )
     
      m_modes( any ) as long
      m_count as integer
  end type
 
  constructor FullScreenVideoModes()
    '' Default is 32-bit color
    this.constructor( 32 )
  end constructor
 
  constructor FullScreenVideoModes( _
    byval depth as integer )
     '' Enumerates all available fullscreen modes for the given depth
     dim as long item = screenList( depth )
    
    do while( item <> 0 )
      addItem( item )
      item = screenList()
    loop   
  end constructor
 
  destructor FullScreenVideoModes()
  end destructor
 
  property FullScreenVideoModes.count() as integer
    return( m_count )
  end property
 
  property FullScreenVideoModes.width( _
    byval index as integer ) as short
   
    return( hiWord( m_modes( index ) ) )
  end property
 
  property FullScreenVideoModes.height( _
    byval index as integer ) as short
   
    return( loWord( m_modes( index ) ) )
  end property
 
  sub FullScreenVideoModes.addItem( _
    byval pValue as long )
    '' Adds a video mode to the list
    m_count += 1
    redim preserve m_modes( 0 to m_count - 1 )
    m_modes( m_count - 1 ) = pValue
  end sub
 
  function FullScreenVideoModes.isAvailable( _
    byval pWidth as integer, byval pHeight as integer ) as boolean
   
    dim as boolean found = false
   
    '' See if we can find the requested video mode
    for i as integer = 0 to m_count - 1
      if( pWidth = width( i ) andAlso _
        pHeight = height( i ) ) then
        '' Video mode is available
        found = true
        exit for
      end if
    next
   
    return( found )
  end function
end namespace

/'
  Main code
'/
dim as integer bitDepth = 32
dim as gfx.FullScreenVideoModes _
  videoModes32bit = gfx.FullScreenVideoModes( bitDepth )

? "Available fullscreen video modes for " & bitDepth & "-bit: "

with videoModes32bit
  for i as integer = 0 to .count - 1
    ? .width( i ), .height( i )
  next
 
  ?
  ? "320x200 available: "; iif( _
    .isAvailable( 320, 200 ), "yes", "no" )
 
  ? "2433x3425 available: "; iif( _
    .isAvailable( 2433, 3425 ), "yes", "no" )
end with

sleep()
Last edited by paul doe on Sep 10, 2018 11:54, edited 2 times in total.
fxm
Posts: 8424
Joined: Apr 22, 2009 12:46
Location: Paris (suburbs), FRANCE

Re: Lines using Vectors - DEMO

Postby fxm » Sep 09, 2018 16:13

When using dynamic arrays, 'Erase' frees the memory allocated for the array elements, but the array descriptor is not deallocated (the array remains declared).
The descriptor is full reset except for the descriptor data corresponding to the declared array datatype, and to the number of dimensions of the array if this one has been sized before calling 'Erase'.
paul doe
Posts: 804
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Lines using Vectors - DEMO

Postby paul doe » Sep 09, 2018 19:30

fxm wrote:When using dynamic arrays, 'Erase' frees the memory allocated for the array elements, but the array descriptor is not deallocated (the array remains declared).
The descriptor is full reset except for the descriptor data corresponding to the declared array datatype, and to the number of dimensions of the array if this one has been sized before calling 'Erase'.

Mmmm, that is indeed helpful info. IMO, it should be added to the wiki, no?
fxm
Posts: 8424
Joined: Apr 22, 2009 12:46
Location: Paris (suburbs), FRANCE

Re: Lines using Vectors - DEMO

Postby fxm » Sep 10, 2018 5:52

This is why once the number of dimensions of a dynamic array is defined, it can not be changed even after an 'Erase', because the descriptor size is adapted to the number of dimensions:
fxm wrote:The array descriptor has the following structure (each item is coded on an Integer):
- pointer to the real or virtual element: @array(0, 0,...)
- pointer to the first real element: @array(lbound1, lbound2,...)
- "global" size in bytes: (ubound1-lbound1+1)*(ubound2-lbound2+1).....*(size of 1 element)
- size of one element in bytes
- number of dimensions
then for each dimension:
- number of elements: (ubound-lbound+1)
- lbound
- ubound

paul doe wrote:Mmmm, that is indeed helpful info. IMO, it should be added to the wiki, no?
I will see how I can complete a little bit without going into the details of the internal implementation (as above), but staying mainly at the user level.
paul doe
Posts: 804
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Lines using Vectors - DEMO

Postby paul doe » Sep 10, 2018 9:36

fxm wrote:I will see how I can complete a little bit without going into the details of the internal implementation (as above), but staying mainly at the user level.

The paragraph from before is quite succint but descriptive:
fxm wrote:When using dynamic arrays, 'Erase' frees the memory allocated for the array elements, but the array descriptor is not deallocated the array remains declared ???at its scope level???.

How about this?
fxm
Posts: 8424
Joined: Apr 22, 2009 12:46
Location: Paris (suburbs), FRANCE

Re: Lines using Vectors - DEMO

Postby fxm » Sep 10, 2018 11:38

Done:
KeyPgErase → fxm [Reformulated description, very slightly]
MrSwiss
Posts: 2817
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Lines using Vectors - DEMO

Postby MrSwiss » Sep 10, 2018 14:02

paul doe wrote:(if you're doing full-screen stuff, of course)
I don't want to ever, do that! (I've no patience, to wait!)

The only required changes are:
  • ReDim (instead of Dim) the V2D 'helpers' (dynamic, instead of static)
  • remove the line, containing 'Erase' from MAIN-LOOP
  • insert DPI correction, on radius offset: off = (scr_cy \ 16) * DPI
in order, to achieve the desired results. Updated code in first post.
Last edited by MrSwiss on Sep 10, 2018 14:51, edited 1 time in total.
dodicat
Posts: 5254
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Lines using Vectors - DEMO

Postby dodicat » Sep 12, 2018 22:37

You could also use magnitude and direction to define a line.

Code: Select all

 
screen 20,32
sub drawline(x as long,y as long,angle as double,length as double,col as ulong,byref x2 as long=0,byref y2 as long=0)
    angle=angle*.0174532925199433 
     x2=x+length*cos(angle)
     y2=y-length*sin(angle)
     line(x,y)-(x2,y2),col
end sub

dim as single angle
dim as single d
dim as ulong u1,u2
do
    d-=1
for angle=0 to 360 step .1
     drawline(1024\2,768\2,angle+d,angle,rgb(angle/2,255-angle/2,0),u1,u2)
     drawline(u1,u2,angle+d,angle/10,rgb(angle/2,0,255-angle/2))
 next
loop until len(inkey)
sleep

 
MrSwiss
Posts: 2817
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Lines using Vectors - DEMO

Postby MrSwiss » Sep 12, 2018 23:18

dodicat wrote:You could also use magnitude and direction to define a line.
I do exactly that (without drawing the Line, of course) with:

Code: Select all

Function Calc_V2D( ByVal vsx   As Single, ByVal vsy   As Single, _
                   ByVal radi  As Single, ByVal angl  As Single ) As V2D
Just returning a pre-calculated Vector, instead ...
Last edited by MrSwiss on Sep 12, 2018 23:36, edited 1 time in total.
dafhi
Posts: 1222
Joined: Jun 04, 2005 9:51

Re: Lines using Vectors - DEMO

Postby dafhi » Sep 12, 2018 23:30

dodicat i must congratulate you on that rather beautiful piece of code. it makes one stop and sniff a rose
MrSwiss
Posts: 2817
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Lines using Vectors - DEMO

Postby MrSwiss » Sep 13, 2018 15:40

@dafhi,

you've obviously not understood, the point "at issue" here, which is:
  • pre-compute the line's definition's (in order to: eliminate calculations in Main-Loop)
  • which also allowes, to re-run the Loop endlessly ... (if desired, without re-calculation)
dafhi
Posts: 1222
Joined: Jun 04, 2005 9:51

Re: Lines using Vectors - DEMO

Postby dafhi » Sep 13, 2018 19:39

MrSwiss, good to see you working on graphics.

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 1 guest