09-04-2022, 05:57 PM
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. :)