Angle, Vector, Radian, and Distance Library
#11
Here's a demo I created for the tutorial that shows the relationship between Degrees, Radians, and Vectors. The ZIP file attached includes the source code and my Graphics Line Input library which is required to execute the code. Some people (myself included) are visual learners and benefit from these concepts by actually seeing things in progress. Please let me know what you think of the demo and if there's anything that needs attention before I commit it to the tutorial.

Code: (Select All)
'** TRIG Demo
'** By Terry Ritchie
'** 09/03/22
'** Created for the QB64 tutorial located at www.qb64tutorial.com
'------------------------------------------------------------------------------------------------------------
'Graphics Line Input Library by Terry Ritchie
'Creates interactive LINE INPUT statements
'$INCLUDE:'glinputtop.bi'
'------------------------------------------------------------------------------------------------------------

TYPE XYPAIR '       2D point location definition
    x AS SINGLE '   x coordinate
    y AS SINGLE '   y coordinate
END TYPE

TYPE XY2PAIR '      two 2D point locations and associated vectors definition
    p1 AS XYPAIR '  point 1 x,y
    p2 AS XYPAIR '  point 2 x,y
    p1v AS XYPAIR ' point 1 vectors
    p2v AS XYPAIR ' point 2 vectors
END TYPE

TYPE VALUES '       display values definition
    Vec AS XYPAIR ' calculated vector
    Rad AS SINGLE ' calculated radian
    Deg AS SINGLE ' calculated degree
    x1 AS SINGLE '  point 1 x
    x2 AS SINGLE '  point 2 x
    y1 AS SINGLE '  point 1 y
    y2 AS SINGLE '  point 2 y
END TYPE

CONST FALSE = 0, TRUE = NOT FALSE '    truth detectors
CONST PI = 3.1415926, PI2 = PI * 2 '   useful PI values
CONST DARKGRAY = _RGB32(96, 96, 96) '  define colors
CONST DARKERGRAY = _RGB32(32, 32, 32)
CONST YELLOW = _RGB32(255, 255, 0)
CONST RED = _RGB32(255, 0, 0)
CONST GREEN = _RGB32(0, 255, 0)
CONST WHITE = _RGB32(255, 255, 255)
CONST BLACK = _RGB32(0, 0, 0)
CONST DARKRED = _RGB32(127, 0, 0)
CONST CYAN = _RGB32(0, 255, 255)
CONST MAGENTA = _RGB32(255, 0, 255)
DIM Value AS VALUES '                  calculated display values
DIM InputDegree AS INTEGER '           interactive degree input
DIM InputRadian AS INTEGER '           interactive radian input
DIM InputVector AS INTEGER '           interactive vector input
DIM InputPoint1 AS INTEGER '           interactive point 1 input
DIM InputPoint2 AS INTEGER '           interactive point 2 input
DIM RadianScreen AS LONG '             radian static screen image
DIM VectorScreen AS LONG '             vector static screen image
DIM CoordGrid AS LONG '                coordinate grid image
DIM CoordGridCopy AS LONG '            copy of coordinate grid image
DIM CurrentScreen AS INTEGER '         0 for radian screen, 1 for vector screen
DIM ButtonDown AS INTEGER '            left mouse button status

SCREEN _NEWIMAGE(800, 600, 32) '       graphics screen
_TITLE "Trig Demo" '                   give window a title
_SCREENMOVE _MIDDLE '                  center window on desktop
_ICON '                                use QB64 icon
DrawScreens '                          create static screen images
DO '                                   begin main program loop
    MakeGLInputs CurrentScreen '       create interactive inputs for current screen                     (library)
    IF CurrentScreen = 0 THEN '        radian screen active?
        ShowRadianScreen '             yes, switch to it
    ELSE '                             no, vector screen is active
        ShowVectorScreen '             switch to it
    END IF
LOOP UNTIL _KEYDOWN(27) '              leave when ESC key pressed
SYSTEM '                               return to operating system
'----------------------------------------------------------------------------------------------------------------
SUB ShowVectorScreen ()

    '** Display and interactive with the vector screen display

    SHARED InputPoint1 AS INTEGER '   interactive point 1 input
    SHARED InputPoint2 AS INTEGER '   interactive point 2 input
    SHARED Value AS VALUES '          calculated display values
    SHARED VectorScreen AS LONG '     static vector screen image
    SHARED CurrentScreen AS INTEGER ' current screen showing
    SHARED ButtonDown AS INTEGER '    left mouse button status
    SHARED CoordGrid AS LONG '        coordinate grid image
    SHARED CoordGridCopy AS LONG '    copy of coordinate grid image
    DIM Vector AS XYPAIR '            vector values
    DIM Radian AS SINGLE '            radian value
    DIM Degree AS SINGLE '            degree value
    DIM Coord AS XY2PAIR '            coordinates and vectors of points
    DIM OldCoord AS XY2PAIR '         copy of current coordinates and vectors of points
    DIM Speed AS INTEGER '            speed of moving points
    DIM Radius AS SINGLE '            radius of circle to be drawn
    DIM PlotVector AS XYPAIR '        vectors used to plot right triangle
    DIM Intro AS INTEGER '            intro mode status
    DIM Message AS STRING '           message to user
    DIM Comma AS INTEGER '            comma location within input fields
    DIM Ps1 AS STRING '               interactive point 1 input field
    DIM Ps2 AS STRING '               interactive point 2 input field
    DIM MsgTimer AS INTEGER '         5 second count down message timer

    RANDOMIZE TIMER '                                                       seed the RND generator
    Intro = TRUE '                                                          enable intro mode
    Speed = 2 '                                                             set speed of moving points
    Coord.p1.x = INT(RND * 360) '                                           random moving point coordinates
    Coord.p1.y = INT(RND * 360)
    Coord.p2.x = INT(RND * 360)
    Coord.p2.y = INT(RND * 360)
    P2PVector Coord.p1, Coord.p2, Coord.p1v '                               vectors pointing at each other
    P2PVector Coord.p2, Coord.p1, Coord.p2v
    DO '                                                                    begin main loop
        _LIMIT 60 '                                                         restrict to 60 frames per second
        GLICLEAR '                                                          restore background image    (library)
        _PUTIMAGE , VectorScreen '                                          restore static vector screen
        WHILE _MOUSEINPUT: WEND '                                           get latest mouse updates
        IF NOT _MOUSEBUTTON(1) THEN ButtonDown = FALSE '                    has mouse button been released?
        IF _MOUSEBUTTON(1) AND NOT ButtonDown THEN '                        left click and previously released?
            IF _MOUSEX > 30 AND _MOUSEX < 152 AND _MOUSEY > 190 AND _MOUSEY < 225 THEN ' yes, within button?
                CurrentScreen = 1 - CurrentScreen '                         yes, switch to next screen
                ButtonDown = TRUE '                                         remember mouse button is down
            END IF
        END IF
        COLOR YELLOW '                                                      yellow text
        SELECT CASE GLICURRENT '                                            which input is user on?     (library)
            CASE InputPoint1 '                                              point1
                LOCATE 11, 3: PRINT "From: X,Y  0-359,0-359"; '             display point format help
            CASE InputPoint2 '                                              point2
                LOCATE 11, 3: PRINT "To  : X,Y  0-359,0-359"; '             display point format help
        END SELECT
        COLOR WHITE '                                                       white text
        OldCoord = Coord '                                                  remember current point information
        IF GLIENTERED(0) THEN '                                             both fields been ENTERed?   (library)
            Message = "" '                                                  yes, reset message
            Ps1 = GLIOUTPUT$(InputPoint1) '                                 get user input for point 1  (libaray)
            Ps2 = GLIOUTPUT$(InputPoint2) '                                 get user input for point 2  (library)
            IF INSTR(Ps1, ",") = 0 OR INSTR(Ps2, ",") = 0 THEN '            user forget commas?
                SOUND 800, 1 '                                              yes, warning sound
                Message = " YOU MUST SUPPLY A COORDINATE X,Y PAIR " '       message to user
                MsgTimer = 360 '                                            5 second count down timer
            ELSE '                                                          no, both fields have commas
                Intro = FALSE '                                             leave intro mode
                Comma = INSTR(Ps1, ",") '                                   comma location in first field
                Coord.p1.x = INT(VAL(LEFT$(Ps1, Comma - 1))) '              get X1 coordinate
                Coord.p1.y = INT(VAL(MID$(Ps1, Comma + 1, LEN(Ps1)))) '     get Y1 coordinate
                Comma = INSTR(Ps2, ",") '                                   comma location in second field
                Coord.p2.x = INT(VAL(LEFT$(Ps2, Comma - 1))) '              get X2 coordinate
                Coord.p2.y = INT(VAL(MID$(Ps2, Comma + 1, LEN(Ps2)))) '     get Y2 coordinate
                IF Coord.p1.x < 0 OR Coord.p1.x > 359 OR Coord.p2.x < 0 OR_
                   Coord.p2.x > 359 OR Coord.p1.y < 0 OR Coord.p1.y > 359 OR_
                   Coord.p2.y < 0 OR Coord.p2.y > 359 THEN '                  values outside of limits?
                    SOUND 800, 1 '                                          yes, warning sound
                    Message = " VALUES CAN ONLY RANGE FROM 0 TO 359 " '     message to user
                    MsgTimer = 360 '                                        5 second count down timer
                    Coord = OldCoord '                                      restore previous point information
                END IF
            END IF
            GLICLOSE 0, TRUE '                                              close input fields          (library)
            MakeGLInputs 1 '                                                recreate input fields       (library)
        END IF
        IF Intro THEN '                                                     intro mode active?
            Coord.p1.x = Coord.p1.x + Coord.p1v.x * Speed '                 yes, move the points along vectors
            Coord.p1.y = Coord.p1.y + Coord.p1v.y * Speed
            Coord.p2.x = Coord.p2.x + Coord.p2v.x * Speed
            Coord.p2.y = Coord.p2.y + Coord.p2v.y * Speed
            IF Coord.p1.x <= 0 OR Coord.p1.x > 359 THEN Coord.p1v.x = -Coord.p1v.x ' keep points within boundary
            IF Coord.p1.y <= 0 OR Coord.p1.y > 359 THEN Coord.p1v.y = -Coord.p1v.y
            IF Coord.p2.x <= 0 OR Coord.p2.x > 359 THEN Coord.p2v.x = -Coord.p2v.x
            IF Coord.p2.y <= 0 OR Coord.p2.y > 359 THEN Coord.p2v.y = -Coord.p2v.y
        END IF
        IF _HYPOT(Coord.p2.x - Coord.p1.x, Coord.p2.y - Coord.p1.y) = 0 THEN ' same coordinates both fields?
            SOUND 800, 1 '                                                  yes, warning sounds
            Message = " SUPPLY TWO DIFFERENT COORDINATE VALUES " '          message to user
            MsgTimer = 360 '                                                5 second count down timer
            Coord = OldCoord '                                              restore previous point information
        END IF
        P2PVector Coord.p1, Coord.p2, Vector '                              get vector between the points
        Radian = Vector2Radian(Vector) '                                    calculate radian from vector
        Degree = Radian2Degree(Radian) '                                    calculate degree from radian
        Value.Vec.x = Vector.x '                                            record screen values
        Value.Vec.y = Vector.y
        Value.Rad = Radian
        Value.Deg = Degree
        Value.x1 = Coord.p1.x
        Value.y1 = Coord.p1.y
        Value.x2 = Coord.p2.x
        Value.y2 = Coord.p2.y
        UpdateScreenValues '                                                display screen values
        Radius = _HYPOT(Coord.p2.x - Coord.p1.x, Coord.p2.y - Coord.p1.y) ' calculate distance between points
        PlotVector.x = Coord.p1.x + Vector.x * Radius '                     plot second point on circle
        PlotVector.y = Coord.p1.y + Vector.y * Radius
        _DEST CoordGrid '                                                   switch to grid image
        _PUTIMAGE (0, 0), CoordGridCopy '                                   restore the grid image
        LINE (PlotVector.x, PlotVector.y)-(Coord.p1.x, Coord.p1.y), YELLOW 'draw right triangle
        LINE -(PlotVector.x, Coord.p1.y), GREEN
        LINE -(PlotVector.x, PlotVector.y), RED
        CIRCLE (Coord.p1.x, Coord.p1.y), Radius, DARKGRAY '                 draw circle between points
        CIRCLE (Coord.p1.x, Coord.p1.y), 3, CYAN '                          draw first point
        PAINT (Coord.p1.x, Coord.p1.y), CYAN, CYAN
        CIRCLE (PlotVector.x, PlotVector.y), 3, MAGENTA '                   draw second point
        PAINT (PlotVector.x, PlotVector.y), MAGENTA, MAGENTA
        _DEST 0 '                                                           switch to vector screen
        _PUTIMAGE (225, 20), CoordGrid '                                    display grid coordinate image
        IF LEN(Message) THEN '                                              does an error message exist?
            COLOR YELLOW, DARKRED '                                         yes, yellow text dark red background
            LOCATE 18, 51 - (LEN(Message) / 2) '                            center text
            PRINT Message; '                                                print error message
            COLOR WHITE, BLACK '                                            white text on black background
            Intro = TRUE '                                                  enable intro mode
            MsgTimer = MsgTimer - 1 '                                       decrement count down timer
            IF MsgTimer = 0 THEN Message = "" '                             timer finished, remove message
        END IF
        GLIUPDATE '                                                         update interactive inputs   (library)
        _DISPLAY '                                                          update screen with changes
    LOOP UNTIL CurrentScreen = 0 OR _KEYDOWN(27) '                          leave when screen switched or ESC
    GLICLOSE 0, TRUE '                                                      close interactive inputs    (library)

END SUB '                                                                   well that was fun! :p
'----------------------------------------------------------------------------------------------------------------
SUB UpdateScreenValues ()

    '** Updates screen formula values

    SHARED Value AS VALUES '       calculated display values
    DIM x2_x1 AS SINGLE '          point 2 x - point 1 x
    DIM y2_y1 AS SINGLE '          point 2 y - point 1 y
    DIM x2_x1squared AS SINGLE '   point 2 x - point 1 x squared
    DIM y2_y1squared AS SINGLE '   point 2 y - point 1 y squared
    DIM hypot AS SINGLE '          distance between point 1 and point 2

    x2_x1 = Value.x2 - Value.x1 '                                       calculate screen values
    y2_y1 = Value.y2 - Value.y1
    x2_x1squared = x2_x1 * x2_x1
    y2_y1squared = y2_y1 * y2_y1
    hypot = _HYPOT(x2_x1, y2_y1)
    COLOR YELLOW, BLACK '                                               RESULT
    LOCATE 3, 85: PRINT USING "###.####"; Value.Deg;
    LOCATE 4, 87: PRINT USING "#.######"; Value.Rad;
    LOCATE 5, 86: PRINT USING "##.###,##.###"; Value.Vec.x; Value.Vec.y;
    LOCATE 24, 8: COLOR YELLOW: PRINT USING "#.######"; Value.Rad; '    RADIAN TO DEGREE
    LOCATE 25, 8: PRINT USING "###.####"; Value.Deg;
    LOCATE 29, 14: COLOR GREEN: PRINT USING "##.##"; Value.Vec.x; '     VECTOR TO DEGREE
    LOCATE 29, 20: COLOR RED: PRINT USING "##.##"; Value.Vec.y;
    LOCATE 30, 8: COLOR YELLOW: PRINT USING "###.####"; Value.Deg;
    LOCATE 33, 21: COLOR GREEN: PRINT USING "###.##"; Value.x2; '       NORMALIZED VECTOR
    LOCATE 33, 30: PRINT USING "###.##"; Value.x1;
    LOCATE 33, 40: PRINT USING "####.##"; x2_x1;
    LOCATE 34, 21: COLOR RED: PRINT USING "###.##"; Value.y2;
    LOCATE 34, 30: PRINT USING "###.##"; Value.y1;
    LOCATE 34, 40: PRINT USING "####.##"; y2_y1;
    LOCATE 35, 29: COLOR GREEN: PRINT USING "######"; x2_x1squared;
    LOCATE 35, 38: COLOR RED: PRINT USING "######"; y2_y1squared;
    LOCATE 35, 48: COLOR YELLOW: PRINT USING "###.##"; hypot;
    LOCATE 36, 20: COLOR GREEN: PRINT USING "####.#"; x2_x1;
    LOCATE 36, 29: COLOR YELLOW: PRINT USING "###.##"; hypot;
    IF hypot = 0 THEN '                                                 same coordinates entered?
        LOCATE 36, 40: COLOR GREEN: PRINT USING "##.###"; 0; '          yes, display 0 to avoid /0 error
        LOCATE 37, 40: COLOR RED: PRINT USING "##.###"; 0;
    ELSE
        LOCATE 36, 40: COLOR GREEN: PRINT USING "##.###"; x2_x1 / hypot;
        LOCATE 37, 40: COLOR RED: PRINT USING "##.###"; y2_y1 / hypot;
    END IF
    LOCATE 37, 20: COLOR RED: PRINT USING "####.#"; y2_y1;
    LOCATE 37, 29: COLOR YELLOW: PRINT USING "###.##"; hypot;
    LOCATE 24, 83: COLOR YELLOW: PRINT USING "###.##"; Value.Deg; '     DEGREE TO RADIAN
    LOCATE 25, 83: PRINT USING "#.######"; Value.Rad;
    LOCATE 28, 91: PRINT USING "#.######"; Value.Rad; '                 RADIAN TO VECTOR
    LOCATE 29, 91: PRINT USING "#.######"; Value.Rad;
    LOCATE 30, 74: COLOR GREEN: PRINT USING "##.###"; Value.Vec.x;
    LOCATE 30, 88: COLOR RED: PRINT USING "##.###"; Value.Vec.y;
    LOCATE 34, 81: COLOR YELLOW: PRINT USING "###.##"; Value.Deg; '     DEGREE TO VECTOR
    LOCATE 36, 82: PRINT USING "###.##"; Value.Deg;
    LOCATE 37, 77: COLOR GREEN: PRINT USING "##.###"; Value.Vec.x;
    LOCATE 37, 91: COLOR RED: PRINT USING "##.###"; Value.Vec.y;
    COLOR WHITE, BLACK '                                                white text on black background

END SUB
'----------------------------------------------------------------------------------------------------------------
SUB ShowRadianScreen ()

    '** Display and interactive with the radian screen display

    SHARED Value AS VALUES '          calculated display values
    SHARED RadianScreen AS LONG '     static radian screen image
    SHARED CurrentScreen AS INTEGER ' current active screen
    SHARED InputDegree AS INTEGER '   interactive degree input
    SHARED InputRadian AS INTEGER '   interactive radian input
    SHARED InputVector AS INTEGER '   interactive vector input
    SHARED ButtonDown AS INTEGER '    left mouse button status
    DIM Idegree AS SINGLE '           interactive degree input value
    DIM Iradian AS SINGLE '           interactive radian input value
    DIM Ivector AS STRING * 10 '      interactive vector input string
    DIM Ivec AS XYPAIR '              vector pair entered by user
    DIM ZeroZero AS XYPAIR '          0,0 coordinate (center of circle)
    DIM PlotVector AS XYPAIR '        vectors used to plot right triangle
    DIM Message AS STRING '           message to user
    DIM Intro AS INTEGER '            intro mode status
    DIM Comma AS INTEGER '            comma location within vector input field
    DIM Vector AS XYPAIR '            vector coordinates
    DIM Radian AS SINGLE '            radian value
    DIM Degree AS SINGLE '            degree value
    DIM OneDg AS SINGLE '             one radian degree
    DIM MsgTimer AS INTEGER '         5 second count down message timer

    OneDg = .01745329 '                                                     one radian degree
    Intro = TRUE '                                                          enable intro mode
    DO '                                                                    begin main loop
        _LIMIT 60 '                                                         restrict to 60 frames per second
        GLICLEAR '                                                          restore background image    (library)
        _PUTIMAGE , RadianScreen '                                          restore static radian screen
        WHILE _MOUSEINPUT: WEND '                                           get latest mouse updates
        IF NOT _MOUSEBUTTON(1) THEN ButtonDown = FALSE '                    was mouse button released?
        IF _MOUSEBUTTON(1) AND NOT ButtonDown THEN '                        mouse click and previously released?
            IF _MOUSEX > 30 AND _MOUSEX < 152 AND _MOUSEY > 190 AND _MOUSEY < 225 THEN ' yes, within button?
                CurrentScreen = 1 - CurrentScreen '                         switch screens
                ButtonDown = TRUE '                                         remember mouse button down
            END IF
        END IF
        COLOR YELLOW '                                                      yellow text
        SELECT CASE GLICURRENT '                                            which input is user on?     (library)
            CASE InputDegree '                                              degree
                LOCATE 11, 4: PRINT "0 - 360 for Degree"; '                 display degree limit help
            CASE InputRadian '                                              radian
                LOCATE 11, 3: PRINT "0 - 6.28 for Radian"; '                display radian limit help
            CASE InputVector '                                              vector
                LOCATE 11, 5: PRINT CHR$(241); "X, "; CHR$(241); "Y for vector"; ' display vector format help
        END SELECT
        COLOR WHITE '                                                       white text
        IF GLIENTERED(InputDegree) THEN '                                   ENTER pressed on Degree?    (library)
            Message = "" '                                                  yes, reset error message
            Idegree = VAL(GLIOUTPUT$(InputDegree)) '                        get value of degree input   (library)
            IF Idegree < 0 OR Idegree > 360 THEN '                          degree within limits?
                SOUND 880, 1 '                                              no, warning beep
                Message = "  DEGREE MUST BE 0 THROUGH 360  " '              set error message
                MsgTimer = 360 '                                            5 second count down timer
            ELSE '                                                          yes, degree within limits
                Intro = FALSE '                                             leave intro mode
                Degree = Idegree '                                          set degree
                Radian = Degree2Radian(Idegree) '                           calculate radian from degree
                Radian2Vector Radian, Vector '                              calculate vector from radian
            END IF
            GLICLOSE 0, TRUE '                                              remove interactive inputs   (library)
            MakeGLInputs 0 '                                                recreate interactive inputs (library)
            GLIFORCE InputDegree '                                          force cursor to degree      (library)
        ELSEIF GLIENTERED(InputRadian) THEN '                               ENTER pressed on Radian?    (libaray)
            Message = "" '                                                  yes, reset error message
            Iradian = VAL(GLIOUTPUT$(InputRadian)) '                        get value of radian input   (library)
            IF Iradian < 0 OR Iradian > PI2 THEN '                          radian within limits?
                SOUND 880, 1 '                                              no, warning beep
                Message = "  RADIAN MUST BE 0 THROUGH 6.2831852  " '        set error message
                MsgTimer = 360 '                                            5 second count down timer
            ELSE '                                                          yes, radian within limits
                Intro = FALSE '                                             leave intro mode
                Radian = Iradian '                                          set radian
                Degree = Radian2Degree(Radian) '                            calculate degree from radian
                Radian2Vector Radian, Vector '                              calculate vector from radian
            END IF
            GLICLOSE 0, TRUE '                                              remove interactive inputs   (library)
            MakeGLInputs 0 '                                                recreate interactive inputs (library)
            GLIFORCE InputRadian '                                          force cursor to radian      (library)
        ELSEIF GLIENTERED(InputVector) THEN '                               ENTER pressed on Vector?    (library)
            Message = "" '                                                  yes, reset error message
            Ivector = GLIOUTPUT$(InputVector) '                             get vector string           (library)
            Comma = INSTR(Ivector, ",") '                                   get comma placement from string
            IF Comma = 0 THEN '                                             was a comma found?
                SOUND 880, 1 '                                              no, warning beep
                Message = "  VECTOR MUST BE TWO VALUES SEPARATED BY A COMMA  " ' set error message
                MsgTimer = 360 '                                            5 second count down timer
            ELSE '                                                          yes, a comma was found
                Intro = FALSE '                                             leave intro mode
                Ivec.x = VAL(LEFT$(Ivector, Comma - 1)) '                   get value of X vector
                Ivec.y = VAL(MID$(Ivector, Comma + 1, LEN(Ivector))) '      get value of Y vector
                P2PVector ZeroZero, Ivec, Vector '                          calculate normalized vector
                Radian = Vector2Radian(Vector) '                            calculate radian from vector
                Degree = Radian2Degree(Radian) '                            calculate radian from degree
            END IF
            GLICLOSE 0, TRUE '                                              remove interactive inputs   (library)
            MakeGLInputs 0 '                                                recreate interactive inputs (library)
            GLIFORCE InputVector '                                          force cursor to Vector      (library)
        END IF
        IF Intro THEN '                                                     intro mode enabled?
            Radian = Radian + OneDg '                                       yes, increment radian by one degree
            IF Radian > PI2 THEN Radian = 0 '                               reset radian value if needed
            Degree = Radian2Degree(Radian) '                                calculate degree from radian
            Radian2Vector Radian, Vector '                                  calculate vector from radian
        END IF
        IF _HYPOT(Vector.x, Vector.y) = 0 THEN '                            0,0 entered for vector?
            Radian = 0 '                                                    yes, naughty naughty
            Degree = 0 '                                                    set both to 0
        END IF
        Value.Vec.x = Vector.x '                                            record display values
        Value.Vec.y = Vector.y
        Value.Rad = Radian
        Value.Deg = Degree
        Value.x1 = 0
        Value.y1 = 0
        Value.x2 = Vector.x * 10
        Value.y2 = Vector.y * 10
        UpdateScreenValues '                                                display values to screen
        PlotVector.x = 399 + Vector.x * 225 '                               adjust vectors to circle perimeter
        PlotVector.y = 246 + Vector.y * 225
        LINE (PlotVector.x, PlotVector.y)-(399, 246), YELLOW '              draw hypotenuse   these 3 lines draw
        LINE -(PlotVector.x, 246), GREEN '                                  draw run          the right triangle
        LINE -(PlotVector.x, PlotVector.y), RED '                           draw rise
        IF LEN(Message) THEN '                                              does an error message exist?
            COLOR YELLOW, DARKRED '                                         yes, yellow text dark red background
            LOCATE 18, 51 - (LEN(Message) / 2) '                            center text
            PRINT Message; '                                                print error message
            COLOR WHITE, BLACK '                                            white text on black background
            Intro = TRUE '                                                  enable intro mode
            MsgTimer = MsgTimer - 1 '                                       decrement count down timer
            IF MsgTimer = 0 THEN Message = "" '                             timer finished, remove message
        END IF
        GLIUPDATE '                                                         update interactive inputs   (library)
        _DISPLAY '                                                          update screen with changes
    LOOP UNTIL CurrentScreen = 1 OR _KEYDOWN(27) '                          leave when screen shanges or ESC
    GLICLOSE 0, TRUE '                                                      close interactive inputs    (library)

END SUB '                                                                   another long night of coding 8)
'----------------------------------------------------------------------------------------------------------------
SUB MakeGLInputs (S AS INTEGER)

    '** Creates interactive inputs for Degree, Radian, ,Vector, Point 1, and Point 2
    'S - current active screen (INPUT)

    SHARED InputDegree AS INTEGER ' interactive degree input
    SHARED InputRadian AS INTEGER ' interactive radian input
    SHARED InputVector AS INTEGER ' interactive vector input
    SHARED InputPoint1 AS INTEGER ' interactive point 1 input
    SHARED InputPoint2 AS INTEGER ' interactive point 2 input

    IF S = 0 THEN '                                                                        radian screen active?
        COLOR YELLOW '                                                                     yes
        InputDegree = GLIINPUT(16, 32, GLINUMERIC + GLISYMBOLS, "Degree: ", TRUE) '        create interactive
        InputRadian = GLIINPUT(16, 48, GLINUMERIC + GLISYMBOLS, "Radian: ", TRUE) '        inputs       (library)
        InputVector = GLIINPUT(16, 64, GLINUMERIC + GLIDASH + GLISYMBOLS, "Vector: ", TRUE)
    ELSE '                                                                                 no, vector screen
        COLOR CYAN '                                                                       create interactive
        InputPoint1 = GLIINPUT(16, 32, GLINUMERIC + GLISYMBOLS, "X,Y (from): ", TRUE) '    inputs       (library)
        COLOR MAGENTA
        InputPoint2 = GLIINPUT(16, 48, GLINUMERIC + GLISYMBOLS, "X,Y ( to ): ", TRUE)
    END IF
    COLOR WHITE '                                                                          white text

END SUB
'----------------------------------------------------------------------------------------------------------------
SUB DrawScreens ()

    '** Draws the static screens

    SHARED Vector AS XYPAIR '      vector coordinates
    SHARED RadianScreen AS LONG '  static radian screen image
    SHARED VectorScreen AS LONG '  static vector screen image
    SHARED CoordGrid AS LONG '     coordinate grid image
    SHARED CoordGridCopy AS LONG ' copy of coordinate grid image
    DIM Rad AS SINGLE '            radian counter
    DIM Api AS STRING * 1 '        ASCII pi symbol
    DIM Adg AS STRING * 1 '        ASCII degree symbol
    DIM Asq AS STRING * 1 '        ASCII squared symbol

    RadianScreen = _NEWIMAGE(800, 600, 32) '                 create static radian screen image
    VectorScreen = _NEWIMAGE(800, 600, 32) '                 create static vector screen image
    CoordGrid = _NEWIMAGE(360, 360, 32) '                    create coordinate grid image
    _DEST RadianScreen '                                     switch to radian screen
    CLS '                                                    remove transparency
    Api = CHR$(227) '                                        ASCII Pi symbol
    Adg = CHR$(248) '                                        ASCII degree symbol
    Asq = CHR$(253) '                                        ASCII squared exponent symbol
    CLS '                                                    clear screen
    COLOR GREEN, DARKGRAY '                                  green text on dark gray background
    LOCATE 2, 76: PRINT "         RESULT         "; '        print formula headings
    LOCATE 27, 79: PRINT "  RADIAN TO VECTOR  ";
    LOCATE 32, 79: PRINT "  DEGREE TO VECTOR  ";
    LOCATE 22, 79: PRINT "  DEGREE TO RADIAN  ";
    LOCATE 22, 3: PRINT "  RADIAN TO DEGREE  ";
    LOCATE 27, 3: PRINT "  VECTOR TO DEGREE  ";
    LOCATE 32, 3: PRINT "  NORMALIZED VECTOR  ";
    COLOR WHITE, BLACK '                                     white text on black background
    LOCATE 7, 79: PRINT "Vector has been";
    LOCATE 8, 79: PRINT "normalized -1 to 1.";
    LOCATE 6, 3: PRINT "Use arrow keys or TAB to"; '         print directions
    LOCATE 7, 3: PRINT "move between the input";
    LOCATE 8, 3: PRINT "fields. Press ENTER on";
    LOCATE 9, 3: PRINT "selection. ESC to exit"
    COLOR YELLOW
    LOCATE 3, 77: PRINT "Degree:"; '                         print result fields
    LOCATE 4, 77: PRINT "Radian:";
    LOCATE 5, 77: PRINT "Vector:";
    'RADIAN TO DEGREE                                        print formula fields
    LOCATE 23, 2: COLOR YELLOW: PRINT "Deg";: COLOR WHITE: PRINT " = ";: COLOR YELLOW: PRINT "Rad";: COLOR WHITE
    PRINT " * 180 / PI";
    LOCATE 24, 2: COLOR YELLOW: PRINT "Deg";: COLOR WHITE: PRINT " = ";: COLOR YELLOW: PRINT "########";
    COLOR WHITE: PRINT " * 57.29578";
    LOCATE 25, 2: COLOR YELLOW: PRINT "Deg";: COLOR WHITE: PRINT " = ";: COLOR YELLOW: PRINT "########";
    'VECTOR TO DEGREE
    LOCATE 28, 2: COLOR YELLOW: PRINT "Deg";: COLOR WHITE: PRINT " = ATAN2(";: COLOR GREEN: PRINT "Vx";
    COLOR WHITE: PRINT ", ";: COLOR RED: PRINT "Vy";: COLOR WHITE: PRINT ") * 180 / PI";
    LOCATE 29, 2: COLOR YELLOW: PRINT "Deg";: COLOR WHITE: PRINT " = ATAN2(";: COLOR GREEN: PRINT "#####";
    COLOR WHITE: PRINT ",";: COLOR RED: PRINT "#####";: COLOR WHITE: PRINT ") * 57.29578";
    LOCATE 30, 2: COLOR YELLOW: PRINT "Deg";: COLOR WHITE: PRINT " = ";: COLOR YELLOW: PRINT "########";
    'NORMALIZED VECTOR
    LOCATE 33, 2: COLOR GREEN: PRINT "Vx";: COLOR WHITE: PRINT "  = (";: COLOR GREEN: PRINT "x2";: COLOR WHITE
    PRINT " - ";: COLOR GREEN: PRINT "x1";: COLOR WHITE: PRINT ") = (";: COLOR GREEN: PRINT "######";
    COLOR WHITE: PRINT " - ";: COLOR GREEN: PRINT "######";: COLOR WHITE: PRINT ") = ";: COLOR GREEN
    PRINT "######";
    LOCATE 34, 2: COLOR RED: PRINT "Vy";: COLOR WHITE: PRINT "  = (";: COLOR RED: PRINT "y2";: COLOR WHITE
    PRINT " - ";: COLOR RED: PRINT "y1";: COLOR WHITE: PRINT ") = (";: COLOR RED: PRINT "######";: COLOR WHITE
    PRINT " - ";: COLOR RED: PRINT "##.###";: COLOR WHITE: PRINT ") = ";: COLOR RED: PRINT "######";
    LOCATE 35, 2: COLOR YELLOW: PRINT "Len";: COLOR WHITE: PRINT " = SQR(";: COLOR GREEN: PRINT "Vx"; Asq;
    COLOR WHITE: PRINT " + ";: COLOR RED: PRINT "Vy"; Asq;: COLOR WHITE: PRINT ") = SQR(";: COLOR GREEN
    PRINT "######";: COLOR WHITE: PRINT " + ";: COLOR RED: PRINT "######";: COLOR WHITE: PRINT ") = ";
    COLOR YELLOW: PRINT "######";
    LOCATE 36, 2: COLOR GREEN: PRINT "Vx";: COLOR WHITE: PRINT "  = ";: COLOR GREEN: PRINT "Vx";: COLOR WHITE
    PRINT " / ";: COLOR YELLOW: PRINT "Len";: COLOR WHITE: PRINT "  = ";: COLOR GREEN: PRINT "######";
    COLOR WHITE: PRINT " / ";: COLOR YELLOW: PRINT "######";: COLOR WHITE: PRINT "   = ";: COLOR GREEN
    PRINT "######";
    LOCATE 37, 2: COLOR RED: PRINT "Vy";: COLOR WHITE: PRINT "  = ";: COLOR RED: PRINT "Vy";: COLOR WHITE
    PRINT " / ";: COLOR YELLOW: PRINT "Len";: COLOR WHITE: PRINT "  = ";: COLOR RED: PRINT "######";
    COLOR WHITE: PRINT " / ";: COLOR YELLOW: PRINT "######";: COLOR WHITE: PRINT "   = ";: COLOR RED
    PRINT "######";
    'DEGREE TO RADIAN
    LOCATE 23, 77: COLOR YELLOW: PRINT "Rad";: COLOR WHITE: PRINT " = ";: COLOR YELLOW: PRINT "Deg";
    COLOR WHITE: PRINT " * PI / 180";
    LOCATE 24, 77: COLOR YELLOW: PRINT "Rad";: COLOR WHITE: PRINT " = ";: COLOR YELLOW: PRINT "######";
    COLOR WHITE: PRINT " * .0174532";
    LOCATE 25, 77: COLOR YELLOW: PRINT "Rad";: COLOR WHITE: PRINT " = ";: COLOR YELLOW: PRINT "########";
    'RADIAN TO VECTOR
    LOCATE 28, 69: COLOR GREEN: PRINT "Vx";: COLOR WHITE: PRINT " =  SIN(";: COLOR YELLOW: PRINT "Rad";
    COLOR WHITE: PRINT ") =  SIN(";: COLOR YELLOW: PRINT "########";: COLOR WHITE: PRINT ")";
    LOCATE 29, 69: COLOR RED: PRINT "Vy";: COLOR WHITE: PRINT " = -COS(";: COLOR YELLOW: PRINT "Rad";
    COLOR WHITE: PRINT ") = -COS(";: COLOR YELLOW: PRINT "########";: COLOR WHITE: PRINT ")";
    LOCATE 30, 69: COLOR GREEN: PRINT "Vx";: COLOR WHITE: PRINT " = ";: COLOR GREEN: PRINT "######";
    COLOR WHITE: PRINT " , ";: COLOR RED: PRINT "Vy";: COLOR WHITE: PRINT " = ";: COLOR RED: PRINT "######";
    'DEGREE TO VECTOR
    LOCATE 33, 72: COLOR GREEN: PRINT "Vx";: COLOR WHITE: PRINT " = SIN(";: COLOR YELLOW: PRINT "Deg";
    COLOR WHITE: PRINT "     * PI / 180)";
    LOCATE 34, 72: COLOR GREEN: PRINT "Vx";: COLOR WHITE: PRINT " = SIN(";: COLOR YELLOW: PRINT "######";
    COLOR WHITE: PRINT "  * .0174532)";
    LOCATE 35, 72: COLOR RED: PRINT "Vy";: COLOR WHITE: PRINT " = -COS(";: COLOR YELLOW: PRINT "Deg";
    COLOR WHITE: PRINT "    * PI / 180)";
    LOCATE 36, 72: COLOR RED: PRINT "Vy";: COLOR WHITE: PRINT " = -COS(";: COLOR YELLOW: PRINT "######";
    COLOR WHITE: PRINT " * .0174532)";
    LOCATE 37, 72: COLOR GREEN: PRINT "Vx";: COLOR WHITE: PRINT " = ";: COLOR GREEN: PRINT "######";
    COLOR WHITE: PRINT " , ";: COLOR RED: PRINT "Vy";: COLOR WHITE: PRINT " = ";: COLOR RED: PRINT "######";
    COLOR WHITE, RED '                                       white text on red background
    LOCATE 13, 5: PRINT " Click here to "; '                 mouse button text
    LOCATE 14, 5: PRINT " switch pages. ";
    LINE (31, 191)-(151, 224), WHITE, B '                    mouse button outline
    VectorScreen = _COPYIMAGE(RadianScreen) '                copy everything to vector screen
    COLOR GREEN, DARKGRAY '                                  green text on dark gray background
    LOCATE 2, 2: PRINT "   ENTER A VALUE BELOW   "; '        print heading
    COLOR WHITE, BLACK
    LOCATE 10, 79: PRINT "radius of circle = 10" '           let user know radius of circle
    LOCATE 1, 48: PRINT "0"; Api; " rad"; '                  print text around circle
    LOCATE 31, 49: PRINT Api; " rad";
    LOCATE 16, 80: PRINT ".5"; Api; " rad";
    LOCATE 16, 14: PRINT "1.5"; Api; " rad";
    LOCATE 3, 50: PRINT "0"; Adg;
    LOCATE 29, 49: PRINT "180"; Adg;
    LOCATE 16, 75: PRINT "90"; Adg;
    LOCATE 16, 24: PRINT "270"; Adg;
    CIRCLE (399, 246), 225, DARKGRAY '                       draw main circle
    FOR Rad = 0 TO PI2 STEP .08726645 '                      cycle through radian 5 degrees at a time
        Radian2Vector Rad, Vector '                          get normalized vector at radian
        Vector.x = 399 + Vector.x * 225 '                    adjust vectors for perimeter of circle
        Vector.y = 246 + Vector.y * 225
        PSET (Vector.x, Vector.y), WHITE '                   place tick mark around circle
    NEXT Rad
    _DEST VectorScreen '                                     switch to vector screen
    COLOR GREEN, DARKGRAY '                                  green text on dark gray background
    LOCATE 2, 2: PRINT "   ENTER VALUES BELOW    "; '        print heading
    COLOR WHITE, BLACK
    LOCATE 1, 51: PRINT "0"; '                               print coordinates around box
    LOCATE 25, 50: PRINT "359";
    LOCATE 13, 27: PRINT "0";
    LOCATE 13, 75: PRINT "359";
    LOCATE 1, 29: PRINT CHR$(25); "(0,0)";
    LOCATE 25, 65: PRINT "(359,359)"; CHR$(24);
    LOCATE 16, 3: PRINT "You must press ENTER on"; '         print input field directions
    LOCATE 17, 3: PRINT "both inputs to activate.";
    LINE (224, 19)-(586, 381), WHITE, B '                    draw box outline
    _DEST CoordGrid '                                        switch to coordinate grid image
    CLS '                                                    remove transparency
    FOR Rad = 0 TO 359 STEP 10 '                             cycles in steps of 10
        LINE (Rad, 0)-(Rad, 359), DARKERGRAY '               draw vertical grid lines
        LINE (0, Rad)-(359, Rad), DARKERGRAY '               draw horizontal grid lines
    NEXT Rad
    CoordGridCopy = _COPYIMAGE(CoordGrid) '                  save clean copy of coordinate grid image
    _DEST 0 '                                                switch back to main screen

END SUB '                                                    phew, that was a lot of work!
'----------------------------------------------------------------------------------------------------------------
SUB P2PVector (P1 AS XYPAIR, P2 AS XYPAIR, V AS XYPAIR)

    '** NOTE: V passed by reference is altered
    '** Point to Point Vector Calculator
    '** Returns the x,y normalized vectors from P1 to P2
    ' P1.x, P1.y = FROM coordinate            (INPUT )
    ' P2.x, P2.y = TO coordinate              (INPUT )
    ' V.x, V.y   = normalized vectors to P2   (OUTPUT)

    DIM D AS SINGLE ' distance between points

    V.x = P2.x - P1.x '      horizontal distance (  side A  )
    V.y = P2.y - P1.y '      vertical distance   (  side B  )
    D = _HYPOT(V.x, V.y) '   direct distance     (hypotenuse)
    IF D = 0 THEN EXIT SUB ' can't divide by 0
    V.x = V.x / D '          normalized x vector (  -1 to 1 )
    V.y = V.y / D '          normalized y vector (  -1 to 1 )

END SUB
'----------------------------------------------------------------------------------------------------------------
FUNCTION Vector2degree (V AS XYPAIR)

    '** Vector to Degree Calculator
    '** Converts the supplied normalized vector to a degree with 0 degrees facing up
    'V.x, V.y - normalized vector (INPUT)
    '57.29578 = 180 / PI

    DIM Degrees AS SINGLE ' the returned degree

    Degrees = _ATAN2(V.y, V.x) * 57.29578 '         get degree from vector (-180 to 180)
    IF Degrees < 0 THEN Degrees = 360 + Degrees '   convert to 360
    Degrees = Degrees + 90 '                        set 0 degrees as up
    IF Degrees > 360 THEN Degrees = Degrees - 360 ' adjust if necessary
    Vector2degree = Degrees '                       return degree (0 to 359.99..)

END FUNCTION
'----------------------------------------------------------------------------------------------------------------
SUB Degree2Vector (D AS SINGLE, V AS XYPAIR)

    '** NOTE: V passed by reference is altered
    '** Degree to Vector Calculator
    '** Converts the supplied degree to a normalized vector
    'D        - degree            (INPUT )
    'V.x, V.y - normalized vector (OUTPUT)
    '.017453292 = PI / 180

    V.x = SIN(D * .017453292) '  return x vector
    V.y = -COS(D * .017453292) ' return y vector

END SUB
'----------------------------------------------------------------------------------------------------------------
FUNCTION Vector2Radian (V AS XYPAIR)

    '** Vector to Radian Calculator
    '** Converts the supplied vector to a radian (0 to 2*PI)
    ' V.x, V.y - the supplied vector (INPUT)

    Vector2Radian = Degree2Radian(Vector2degree(V)) ' return radian (0 to 2*PI)

END FUNCTION
'----------------------------------------------------------------------------------------------------------------
SUB Radian2Vector (R AS SINGLE, V AS XYPAIR)

    '** NOTE: V passed by reference is altered
    '** Radian to Vector Calculator
    '** Converts the supplied radian to a normalized vector
    ' R        - supplied radian                (INPUT )
    ' V.x, V.y - the returned normalized vector (OUTPUT)
    ' 6.2831852 = 2 * PI

    Degree2Vector Radian2Degree(R), V ' return normalized vector

END SUB
'----------------------------------------------------------------------------------------------------------------
FUNCTION Radian2Degree (R AS SINGLE)

    '** Radian to Degree Calculator
    '** Converts the supplied radian to degrees
    ' R - the supplied radian (INPUT)
    ' returns R * 180 / PI using the QB64 _R2D() function
    ' 6.2831852 = 2 * PI

    Radian2Degree = _R2D(R) ' return degree (0 to 359.99..)

END FUNCTION
'----------------------------------------------------------------------------------------------------------------
FUNCTION Degree2Radian (D AS SINGLE)

    '** Degree to Radian Calculator
    '** Converts the supplied degree to radian
    ' D - the supplied degree (INPUT)
    ' returns A * PI / 180 using QB64 _D2R() function

    Degree2Radian = _D2R(D) ' return radian (0 to 2*PI)

END FUNCTION
'----------------------------------------------------------------------------------------------------------------
'Graphics Line Input Library by Terry Ritchie
'Creates interactive LINE INPUT statements
'$INCLUDE:'glinput_noerror.bi'
'----------------------------------------------------------------------------------------------------------------
'I thought this was going to be a one day project ... here we are four days later. :)


Attached Files Image(s)
       

.zip   TrigDemo.zip (Size: 687.22 KB / Downloads: 28)
Reply




Users browsing this thread: 5 Guest(s)