05-14-2024, 08:00 PM
(This post was last modified: 05-14-2024, 08:05 PM by TerryRitchie.)
More playing around today. I created a few functions to quickly get vector quantities from a SIN lookup table.
The SIN/COSINE table returns standard results while the conversion functions negate the COSINE value so 0 degrees and 0Pi are north/up.
The SIN/COSINE table returns standard results while the conversion functions negate the COSINE value so 0 degrees and 0Pi are north/up.
Code: (Select All)
'+-------------------------------------------------------+
'| Radian to Vector and Degree to Vector subroutines |
'| by |
'| Terry Ritchie |
'| 05/14/24 |
'| |
'| Convert radians or degrees to vector pairs using a |
'| pre-calculated lookup table or real-time calculation. |
'| Documentation contained in subs. |
'| |
'| R2VX!(radian, mode) - return radian x vector |
'| R2VY!(radian, mode) - return radian y vector |
'| D2VX!(degree, mode) - return degree x vector |
'| D2VY!(degree, mode) - return degree y vector |
'| SINE!(Index) - return SINE from lookup table |
'| COSINE!(Index) - return COSINE from lookup table |
'| |
'| R2VX!, R2VY!, D2VX!, and D2VY! return vector values |
'| based on the following input values: |
'| |
'| 0 = North 90 = East 180 = South 270 = West |
'| 0Pi = North .5Pi = East Pi = South 1.5Pi = West |
'| |
'| Degrees based on 0 to 359, radians from 0 to 2Pi. |
'+-------------------------------------------------------+
'+--------------------+
'| Begin demo program |
'+--------------------+
CONST MODE% = 0 ' (0 to use lookup table, 1 to calculate in real time)
DIM d AS SINGLE ' counter
SCREEN _NEWIMAGE(640, 480, 32)
' Draw line from center point using degree values passed in
FOR d = 0 TO 359
LINE (319, 239)-(319 + D2XV(d, MODE) * 200, 239 + D2YV(d, MODE) * 200)
_DELAY .005
NEXT d
SLEEP
CLS
' Draw line from center point using radian values passed in
FOR d = 0 TO 2 * _PI STEP 2 * _PI / 360
LINE (319, 239)-(319 + R2XV(d, MODE) * 200, 239 + R2YV(d, MODE) * 200)
_DELAY .005
NEXT d
'+------------------+
'| End demo program |
'+------------------+
'------------------------------------------------------------------------------------------------------------
FUNCTION R2XV! (rad AS SINGLE, mode AS INTEGER) ' radian to x vector
'+---------------------------------------------------------------------------+
'| Converts a radian value passed in to the corresponding x vector value. |
'| 0Pi = North/Up, .5Pi = East/Right, Pi = South/Down, 1.5Pi = West/Left. |
'| |
'| rad - the radian value to convert to x vector |
'| mode - 0 return value from lookup table, not 0 return calculated value |
'| |
'| Note: To use the lookup table the radian value needs to be converted to a |
'| degree value. The lookup table only contains the values for integer |
'| degrees ranging from 0 to 359. If you need a more precise |
'| calculation set mode above to a non xero integer value. |
'+---------------------------------------------------------------------------+
IF mode THEN ' calculate vector?
R2XV! = SIN(rad) ' yes, return calculated SINE value
ELSE ' no, use lookup table
R2XV! = SINE!(_R2D(rad)) ' return SINE value from table
END IF
END FUNCTION
'------------------------------------------------------------------------------------------------------------
FUNCTION R2YV! (rad AS SINGLE, mode AS INTEGER) ' radian to y vector
'+---------------------------------------------------------------------------+
'| Converts a radian value passed in to the corresponding y vector value. |
'| 0Pi = North/Up, .5Pi = East/Right, Pi = South/Down, 1.5Pi = West/Left. |
'| |
'| rad - the radian value to convert to y vector |
'| mode - 0 return value from lookup table, not 0 return calculated value |
'| |
'| Note: To use the lookup table the radian value needs to be converted to a |
'| degree value. The lookup table only contains the values for integer |
'| degrees ranging from 0 to 359. If you need a more precise |
'| calculation set mode above to a non xero integer value. |
'+---------------------------------------------------------------------------+
IF mode THEN ' calculate vector?
R2YV! = -COS(rad) ' yes, return calculated COSINE value (negate so 0 = north)
ELSE ' no, use lookup table
R2YV! = -COSINE!(_R2D(rad)) ' return COSINE value from table (negate so 0 = north)
END IF
END FUNCTION
'------------------------------------------------------------------------------------------------------------
FUNCTION D2XV! (deg AS SINGLE, mode AS INTEGER) ' degree to x vector
'+---------------------------------------------------------------------------+
'| Converts a degree value passed in to the corresponding x vector value. |
'| 0 = North / Up, 90 = East / Right, 180 = South / Down, 270 = West / Left. |
'| |
'| deg - the degree value to convert to x vector |
'| mode - 0 return value from lookup table, not 0 return calculated value |
'| |
'| Note: The lookup table only contains SIN/COS values for integer degrees |
'| ranging from 0 to 359. If you need a more precise calculation set |
'| mode above to a non zero integer value. |
'+---------------------------------------------------------------------------+
IF mode THEN ' calculate vector?
D2XV! = SIN(_D2R(deg)) ' yes, return calculated SINE value
ELSE ' no, use lookup table
D2XV! = SINE!(deg) ' return SINE value from table
END IF
END FUNCTION
'------------------------------------------------------------------------------------------------------------
FUNCTION D2YV! (deg AS SINGLE, mode AS INTEGER) ' degree to y vector
'+---------------------------------------------------------------------------+
'| Converts a degree value passed in to the corresponding y vector value. |
'| 0 = North / Up, 90 = East / Right, 180 = South / Down, 270 = West / Left. |
'| |
'| deg - the degree value to convert to y vector |
'| mode - 0 return value from lookup table, not 0 return calculated value |
'| |
'| Note: The lookup table only contains SIN/COS values for integer degrees |
'| ranging from 0 to 359. If you need a more precise calculation set |
'| mode above to a non zero integer value. |
'+---------------------------------------------------------------------------+
IF mode THEN ' calculate vector?
D2YV! = -COS(_D2R(deg)) ' yes, return calculated COSINE value (negate so 0 = north)
ELSE ' no, use lookup table
D2YV! = -COSINE!(deg) ' return COSINE value from table (negate so 0 = north)
END IF
END FUNCTION
'------------------------------------------------------------------------------------------------------------
FUNCTION SINE! (Index AS INTEGER) ' SINE lookup table
'+--------------------------------------------------+
'| Returns a SINE value from the SINE lookup table. |
'| |
'| Index - 0 to 359 |
'+--------------------------------------------------+
STATIC x(360) AS SINGLE ' SINE lookup table persistent values
DIM d AS INTEGER ' data counter
'+-----------------------------------------------------------------+
'| Build the SINE lookup table the first time subroutine is called |
'+-----------------------------------------------------------------+
IF x(90) = 0 THEN ' has the lookup table been built?
DO ' no, begin data read loop
READ x(d) ' SINE 0 through 90
x(180 - d) = x(d) ' SINE 90 through 180
x(180 + d) = -x(d) ' SINE 180 through 270
x(360 - d) = -x(d) ' SINE 270 through 360
d = d + 1 ' increment degree counter
LOOP UNTIL d = 91 ' leave when all data values read
END IF
SINE! = x(Index) ' return SINE
'+------------------------------------------------------------------------------------------------------+
'| The values for SINE 0 to 0.5PI (0 to 90 degrees) |
'| |
'| I know what you're thinking, "Why not just calculate these and then place the values into the array |
'| table?" I was getting strange anomolies in the returned values. For instance, sometimes .49999999 or |
'| .50000001 would show up for .5 and other times numbers like this would appear .58778552520000001. |
'| Creating and using this data set ensures consistent values. |
'+------------------------------------------------------------------------------------------------------+
DATA 0
DATA .017452406,.034899496,.052335956,.069756473,.087155742,.104528463,.121869343,.139173100,.156434465
DATA .173648177,.190808995,.207911690,.224951054,.241921895,.258819045,.275637355,.292371704,.309016994
DATA .325568154,.342020143,.358367949,.374606593,.390731128,.406736643,.422618261,.438371146,.453990499
DATA .469471562,.484809620,.500000000,.515038074,.529919264,.544639035,.559192903,.573576436,.587785252
DATA .601815023,.615661475,.629320391,.642787609,.656059028,.669130606,.681998360,.694658370,.707106781
DATA .719339800,.731353701,.743144825,.754709580,.766044443,.777145961,.788010753,.798635510,.809016994
DATA .819152044,.829037572,.838670567,.848048096,.857167300,.866025403,.874619707,.882947592,.891006524
DATA .898794046,.906307787,.913545457,.920504853,.927183854,.933580426,.939692620,.945518575,.951056516
DATA .956304755,.961261695,.965925826,.970295726,.974370064,.978147600,.981627183,.984807753,.987688340
DATA .990268068,.992546151,.994521895,.996194698,.997564050,.998629534,.999390827,.999847695,1.00000000
END FUNCTION
'------------------------------------------------------------------------------------------------------------
FUNCTION COSINE! (Index AS INTEGER) ' COSINE lookup table
'+---------------------------------------------------+
'| Returns a COSINE value from the SIN lookup table. |
'| |
'| Index - 0 to 359 |
'+---------------------------------------------------+
SELECT CASE Index ' which array index to return?
CASE 0 TO 89 ' quadrant 1
COSINE! = SINE!(90 - Index) ' return equivalent from SINE table
CASE 90 TO 179 ' quadrant 2
COSINE! = -SINE!(Index - 90) ' return equivalent from SINE table
CASE 180 TO 269 ' quadrant 3
COSINE! = -SINE!(270 - Index) ' return equivalent from SINE table
CASE 270 TO 359 ' quadrant 4
COSINE! = SINE!(Index - 270) ' return equivalent from SINE table
END SELECT
END FUNCTION