QB64 Phoenix Edition
Help needed regarding Lesson 17 - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: Official Links (https://qb64phoenix.com/forum/forumdisplay.php?fid=16)
+--- Forum: Learning Resources and Archives (https://qb64phoenix.com/forum/forumdisplay.php?fid=13)
+---- Forum: Terry Ritchie's Tutorial (https://qb64phoenix.com/forum/forumdisplay.php?fid=14)
+---- Thread: Help needed regarding Lesson 17 (/showthread.php?tid=3108)

Pages: 1 2 3


Help needed regarding Lesson 17 - RhoSigma - 10-08-2024

Hi Terry,

there's a lost soul at Discord. He/she obviously got lots of informations from your Tutorial Lesson 17 (Movement and Rotation).

From a quick visit to that lesson I see for your teachings you use (for whatever reason) a modified version of the standard math coordinate system, which assumes 0° as north direction and then counts the angles clockwise.

Now, this guy/girl is trying to calculate the angle from one point to another one using the _ATAN2 function and wonders about the results, mayby you could have a look: https://discord.com/channels/975381912350752819/975383819848912926/1292989790559666196

Steve and me tried to help, but as his/her thinking is obviously compromised by your coordinate modell, we probably made it even worse than better.


RE: Help needed regarding Lesson 17 - TerryRitchie - 10-08-2024

(10-08-2024, 10:39 AM)RhoSigma Wrote: Hi Terry,

there's a lost soul at Discord. He/she obviously got lots of informations from your Tutorial Lesson 17 (Movement and Rotation).

From a quick visit to that lesson I see for your teachings you use (for whatever reason) a modified version of the standard math coordinate system, which assumes 0° as north direction and then counts the angles clockwise.

Now, this guy/girl is trying to calculate the angle from one point to another one using the _ATAN2 function and wonders about the results, mayby you could have a look: https://discord.com/channels/975381912350752819/975383819848912926/1292989790559666196

Steve and me tried to help, but as his/her thinking is obviously compromised by your coordinate modell, we probably made it even worse than better.
SIgh

Yes, Lesson 17 has caused troubles for a few because of the way I orient the coordinate system. The reason I did that is because 99% of the people that visit the tutorial want nothing to do with the math and just want north, 0 degrees, to face up like the real world.

Those that understand the math understand what I've done here. Those that want to learn the math (which is surprisingly few) get confused as the user you are pointing out.

What to do, what to do.

I need to update Lesson 17 with a section on how the coordinate actually looks and why it needs to be modified for screen use. I'll log into discord and try to explain. Thank you for bringing this to my attention.

UPDATE: OK, I can't log into Discord? I get a popup after putting my user name and password in asking me to verify I'm human but nothing to do to verify?
--------- Give the user my email address --> quickbasic64@gmail.com <-- and have them contact me directly please.


RE: Help needed regarding Lesson 17 - bplus - 10-08-2024

Quote:What to do, what to do.

Simply say 270 degrees or -90 degrees or _Pi(3/2) radians is "North" on a Basic Screen.

Likewise 0 degrees or radians is "East" on a Basic Screen
90 degrees is "South" or _PI(1/2) radians
180 degrees "West" or _PI radians

That way the direction name matches all the trig functions in Basic.


RE: Help needed regarding Lesson 17 - bplus - 10-08-2024

I suspect non mathematicians would be happy to be rid of Radians:
Code: (Select All)
' OK let's be rid on the confusion caused by Radians
' by using User Defined Funcions SinD and CosD that take Degrees 0 to 360 for whole circle,
' and having replaced _Atan2 by returning an angle in Degrees between 2 points: DAtan2(deltaY, deltaX)

_Title "Degrees for everything" 'b+ 2022-10-12
Screen _NewImage(800, 600, 32) ' standard screen size 800 wide, 600 height for quick QB64 Demos with full color potential (the 32)
_ScreenMove 250, 50

cx = _Width / 2 ' middle of the screen point  center x
cy = _Height / 2 ' center y
radius = 250 ' max is 300 for height 600
ArrowTo cx, cy, 0, radius - 3, &HFFFFFFFF
For degrees = 0 To 359 Step 10 ' go around a full circle in degrees in steps of 10 degrees

    ' calculate and draw points around the center of the screen
    x = cx + radius * CosD(degrees) ' use CosD for x dimensions
    y = cy + radius * SinD(degrees) ' use SinD for y dimensions
    Circle (x, y), 1 ' draw bigger points than single pixel

    ' labeling the degree angles before or after the point ?
    If x < cx Then Xoffset = -10 * Len(_Trim$(Str$(degrees))): YOffset = 0
    If x > cx Then Xoffset = 4 * Len(_Trim$(Str$(degrees))): YOffset = 0
    If x = cx Then
        Xoffset = -4 * Len(_Trim$(Str$(degrees)))
        If y > cy Then YOffset = 20 Else YOffset = -20
    End If
    _PrintString (x + Xoffset, y - 8 + YOffset), _Trim$(Str$(degrees))
Next

' save our compass dial to image
dial& = _NewImage(_Width, _Height, 32)
_PutImage , 0, dial& ' screen to dial image stored

' Getting use to seeing angles mouse makes to center of screen
Do
    Cls
    _PutImage , dial&, 0
    While _MouseInput: Wend ' this checks where mouse is right now!
    mx = _MouseX: my = _MouseY: mb1 = _MouseButton(1) ' left mouse down  ' saves mouse status to common variable names
    'lets's the angle in degrees the mouse is to the center of the screen
    dAngle = DAtan2(cx, cy, mx, my)
    Print "The mouse pointer is "; _Trim$(Str$(dAngle)); " Degrees from the screen center." ' then center point is first the mouse point is second
    ArrowTo cx, cy, dAngle, radius - 3, &HFFFFFF00
    drawArc cx, cy, 70, 0, dAngle, &HFFFFFF00
    _Display ' stop the blinking
    _Limit 60 ' only loop 60 times per second
Loop Until _KeyDown(27)


' use angles in degrees units instead of radians (converted inside sub)
Function CosD (degrees)
    ' Note this function uses whatever the default type is, better not be some Integer Type.
    CosD = Cos(_D2R(degrees))
End Function

' use angles in degrees units instead of radians (converted inside sub)
Function SinD (degrees)
    ' Note this function uses whatever the default type is, better not be some Integer Type.
    SinD = Sin(_D2R(degrees))
End Function

' use angles in degrees units instead of radians (converted inside sub)
Function DAtan2 (x1, y1, x2, y2) ' The angle in degrees a 2nd point (x2, y2)  makes to a first point (x1, y1)
    ' Note this function uses whatever the default type is, better not be some Integer Type.
    ' Delta means change between 1 measure and another for example x2 - x1
    deltaX = x2 - x1
    deltaY = y2 - y1
    '  To find the angle point(x2, y2) makes to (x1, y1) in Degrees
    ' Take DegreeAngle = DAtan2(y2 - y1, x2 - x1)
    rtn = _R2D(_Atan2(deltaY, deltaX))
    If rtn < 0 Then DAtan2 = rtn + 360 Else DAtan2 = rtn
End Function

' use angles in degrees units instead of radians (converted inside sub)
Sub ArrowTo (BaseX As Long, BaseY As Long, dAngle As Double, lngth As Long, colr As _Unsigned Long)
    Dim As Long x1, y1, x2, y2, x3, y3
    Dim As Double rAngle
    rAngle = _D2R(dAngle)
    x1 = BaseX + lngth * Cos(rAngle)
    y1 = BaseY + lngth * Sin(rAngle)
    x2 = BaseX + .8 * lngth * Cos(rAngle - _Pi(.05))
    y2 = BaseY + .8 * lngth * Sin(rAngle - _Pi(.05))
    x3 = BaseX + .8 * lngth * Cos(rAngle + _Pi(.05))
    y3 = BaseY + .8 * lngth * Sin(rAngle + _Pi(.05))
    Line (BaseX, BaseY)-(x1, y1), colr
    Line (x1, y1)-(x2, y2), colr
    Line (x1, y1)-(x3, y3), colr
End Sub

' use angles in degrees units instead of radians (converted inside sub)
Sub drawArc (xc, yc, radius, dStart, dMeasure, colr As _Unsigned Long)
    ' xc, yc Center for arc circle
    ' rStart is the Radian Start Angle, use _D2R for conversion from Degrees to Radians
    ' rMeasure is the measure of Arc in Radain units, use _D2R for conversion from Degrees to Radians
    ' Arc will start at rStart and go clockwise around for rMeasure Radians

    Dim rStart, rMeasure, rEnd, stepper, a, x, y
    rStart = _D2R(dStart)
    rMeasure = _D2R(dMeasure)
    rEnd = rStart + rMeasure
    stepper = 1 / radius ' the bigger the radius the smaller  the steps
    For a = rStart To rEnd Step stepper
        x = xc + radius * Cos(a)
        y = yc + radius * Sin(a)
        If a > rStart Then Line -(x, y), colr Else PSet (x, y), colr
    Next
End Sub



RE: Help needed regarding Lesson 17 - TerryRitchie - 10-08-2024

Thanks bplus. I was thinking of visuals along the same lines as you provided. I was wondering if explaining a sine wave first would help with understanding radians?


RE: Help needed regarding Lesson 17 - SMcNeill - 10-08-2024

Quote:I try to figure out how to count angle between two points. I based my attempt on Qb64tutorials lesson 17 and there is this Trig demo I based my poor knowledge. This is simplified attempt I try to figure out:

$Color:32

screen1 = _NewImage(1280, 720, 32)
Screen screen1

Const PI = 3.1415926
x1 = 622 + 8
y1 = 395 + 8

x2 = 636 + 4
y2 = 356 + 4

angle = _Atan2(x2 - x1, y2 - y1) * 180 / PI
If angle < 0 Then angle = angle + 360

Print angle

PSet (x1, y1), White
PSet (x2, y2), White

Maybe I misunderstand something totally. The angle should be around 190, give or take, right?

^ The issue as reported on Discord, in case you can sort out what the solution might be for what they're looking for here.


RE: Help needed regarding Lesson 17 - bplus - 10-08-2024

Oh thanks Steve, he almost got it right but y's over x's or Y's come first for _Atan2 then x's in 2nd argument:

fixed: his line is just over 270 degrees or 283 something:
Code: (Select All)
screen1 = _NewImage(1280, 720, 32)
Screen screen1

Const PI = 3.1415926
x1 = 622 + 8
y1 = 395 + 8
Circle (x1, y1), 1, &HFFFFFF00 ' yellow
x2 = 636 + 4
y2 = 356 + 4
Circle (x2, y2), 1, &HFFFFFFFF ' white
Line (x1, y1)-(x2, y2), &HFF0000FF ' blue
'angle = _Atan2(x2 - x1, y2 - y1) * 180 / PI
angle = _Atan2(y2 - y1, x2 - x1) * 180 / PI  ' y's first, x's 2nd for Atan2
If angle < 0 Then angle = angle + 360

Print angle

And the angle from point 2 (x2, y2) to point 1 (x1, y1) would be 283 - 180 = 103 degrees just past 90 clockwise.


RE: Help needed regarding Lesson 17 - TerryRitchie - 10-08-2024

bplus beat me to it. Yep, xs and ys reversed.


RE: Help needed regarding Lesson 17 - SMcNeill - 10-08-2024

Quote: Pouli: So
angle = _Atan2(y2 - y1, x2 - x1) * 180 / PI ?
The result is still off

Feel free to pop into Discord and chat with the guy.

It may be simply a case of him getting the proper result and then needing to rotate/flip it until it fits into the coordinate system Terry is using in his tutorial. I dunno. All I know is he's saying it's not working, even after the Y and X swap as you (and Rho) both pointed out for him.

Quote:Maybe I misunderstand something totally. The angle should be around 190, give or take, right?



RE: Help needed regarding Lesson 17 - bplus - 10-08-2024

@TerryRitchie here is another visual:
Code: (Select All)
Option _Explicit
_Title "orbit demo" 'b+ 2024-05-10

'============================== Main
Const Xmax = 1000, Ymax = 700
Const Thick = 2
Const Arc_Radius = 100
Const Sin_color = _RGB32(0, 0, 255)
Const Cos_color = _RGB32(0, 128, 0)
Const Radius_color = _RGB32(255, 0, 0)
Const Ang_color = _RGB32(255, 255, 0)
Const White = _RGB32(255, 255, 255)
Const Origin_color = _RGB32(255, 128, 0)
Dim cx, cy, mx, my, stepX, stepY, Radius, dAng, xOut, yOut, x, y
cx = Xmax / 2: cy = Ymax / 2
Screen _NewImage(Xmax, Ymax, 32)
_ScreenMove 60, 0
_PrintMode _KeepBackground
_MouseMove cx + 100, cy + 100 ' get ball rolling
While 1
    Cls
    Color White
    Locate 2, 18
    Print "Move your mouse clockwise starting at 0 due East to see Basics Angle in Degrees increase."
    Locate 5, 68
    Print "Orbit ";
    Color Origin_color
    Print "X_Origin, Y_Origin,";
    Color Ang_color
    Print " Degrees,";
    Color Radius_color
    Print " Radius,";
    Color White
    Print " xOut, yOut"
    'draw horizontal through center of screen
    Line (70, cy)-(Xmax - 70, cy), Cos_color
    ' draw vertical line through center of screen
    Line (cx, 70)-(cx, Ymax - 70), Sin_color
    'poll mouse
    While _MouseInput: Wend ' updates all mouse stuff except wheel
    mx = _MouseX: my = _MouseY 'get mouse location

    'draw our Color Coded Trig Triangle
    ThickLine cx, cy, mx, cy, 1, Cos_color
    ThickLine mx, cy, mx, my, 1, Sin_color
    ThickLine cx, cy, mx, my, Thick, Radius_color

    stepX = mx - cx: stepY = my - cy
    Radius = (stepX ^ 2 + stepY ^ 2) ^ .5

    'to draw angle need to do some math
    'dAng = mouse angle to 0 Degrees due East
    dAng = _R2D(_Atan2(my - cy, mx - cx))
    If dAng < 0 Then dAng = dAng + 360

    Color Ang_color
    ThickArc cx, cy, Radius, 0, dAng, Thick

    'report all numbers color coded
    Color Ang_color
    Locate 5, 3: Print "Yellow Angle (in Degrees) ~ "; dAng \ 1
    Color Radius_color
    Locate 7, 7: Print "    Length red Radius ~ "; Radius \ 1
    Color Sin_color
    Locate 9, 7: Print " Length blue Opp side ~ "; Abs(stepY) \ 1
    Color Cos_color
    Locate 8, 7: Print "Length green Adj side ~ "; Abs(stepX) \ 1
    Color White
    Locate 11, 1: Print " Ratios: (if no division by 0)"
    If Radius <> 0 Then
        Color Cos_color
        Locate 12, 8: Print "COS = Adj ";
        Color Radius_color
        Print "/ Radius ";
        Color White
        Print "~ "; Left$(Str$(stepX / Radius), 6) '; Cos(_D2R(dAng))  ' double check

        Color Sin_color
        Locate 13, 8: Print "SIN = Opp ";
        Color Radius_color
        Print "/ Radius ";
        Color White
        Print "~ "; Left$(Str$(stepY / Radius), 6) '; Sin(_D2R(dAng)) ' double check
    End If
    Color White
    orbit cx, cy, dAng, Radius, xOut, yOut ' mouse here
    orbit cx, cy, dAng, Radius + 50, x, y ' set label here
    label x, y, "(xOut, yOut) = (" + _Trim$(Str$(xOut \ 1)) + "," + Str$(yOut \ 1) + ")"
    Color Origin_color
    label cx, cy - 10, "(X_Origin, Y_Origin) = (" + _Trim$(Str$(cx)) + "," + Str$(cy) + ")"
    _Display
    _Limit 60
Wend


'      !!!!!!   featuring the use of this SUB routine   !!!!
Sub orbit (X_Origin, Y_Origin, Degrees, Radius, xOut, yOut) ' all default single  should be ok
    xOut = X_Origin + Radius * Cos(_D2R(Degrees))
    yOut = Y_Origin + Radius * Sin(_D2R(Degrees))
End Sub

Sub label (xc, yc, text$)
    Dim th2, pw2
    th2 = _FontHeight / 2
    pw2 = _PrintWidth(text$) / 2
    _PrintString (xc - pw2 + 1.25, yc - th2 + .5), text$
End Sub

Sub ThickArc (xCenter, yCenter, arcRadius, dAngleStart, dAngleEnd, rThick)
    Dim rAngle, rAngleStart, rAngleEnd, x1, y1, Stepper
    'draws an Arc with center at xCenter, yCenter, Radius from center is arcRadius

    'for SmallBASIC angle 0 Degrees is due East and angle increases clockwise towards South

    'THIS SUB IS SETUP TO DRAW AN ARC IN CLOCKWISE DIRECTION

    'dAngleStart is where to start Angle in Degrees
    ' so make the dAngleStart the first ray clockwise from 0 Degrees that starts angle drawing clockwise

    'dAngleEnd is where the arc ends going clockwise with positive Degrees
    ' so if the arc end goes past 0 Degrees clockwise from dAngleStart
    '  express the end angle as 360 + angle

    'rThick is the Radius of the many,many tiny circles this will draw to make the arc thick
    ' so if rThick = 2 the circles will have a Radius of 2 pixels and arc will be 4 pixels thick
    If arcRadius < 1 Then PSet (xCenter, yCenter): Exit Sub
    rAngleStart = _D2R(dAngleStart): rAngleEnd = _D2R(dAngleEnd)
    If Int(rThick) = 0 Then Stepper = 1 / (arcRadius * _Pi) Else Stepper = rThick / (arcRadius * _Pi / 2)
    For rAngle = rAngleStart To rAngleEnd Step Stepper
        x1 = arcRadius * Cos(rAngle): y1 = arcRadius * Sin(rAngle)
        If Int(rThick) < 1 Then
            PSet (xCenter + x1, yCenter + y1)
        Else
            fcirc xCenter + x1, yCenter + y1, rThick, Ang_color
        End If
    Next
End Sub

Sub ThickLine (x1, y1, x2, y2, rThick, K As _Unsigned Long)
    Dim length, stepx, stepy, dx, dy, i

    'x1,y1 is one endpoint of line
    'x2,y2 is the other endpoint of the line
    'rThick is the Radius of the tiny circles that will be drawn
    '   from one end point to the other to create the thick line
    'Yes, the line will then extend beyond the endpoints with circular ends.

    stepx = x2 - x1
    stepy = y2 - y1
    length = (stepx ^ 2 + stepy ^ 2) ^ .5
    If length Then
        dx = stepx / length: dy = stepy / length
        For i = 0 To length
            fcirc x1 + dx * i, y1 + dy * i, rThick, K
        Next
    End If
End Sub

Sub fcirc (CX As Long, CY As Long, R As Long, C As _Unsigned Long)
    Dim Radius As Long, RadiusError As Long
    Dim X As Long, Y As Long
    Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
    If Radius = 0 Then PSet (CX, CY), C: Exit Sub
    Line (CX - X, CY)-(CX + X, CY), C, BF
    While X > Y
        RadiusError = RadiusError + Y * 2 + 1
        If RadiusError >= 0 Then
            If X <> Y + 1 Then
                Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
                Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
            End If
            X = X - 1
            RadiusError = RadiusError - X * 2
        End If
        Y = Y + 1
        Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
        Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
    Wend
End Sub

the featured Sub Orbit calculates a point (xOut, yOut) from (Xorigin, Yorigin) a given degrees out and at a given radius length away.
The ThickArc routine works better than trying to draw arcs with built in Circle Sub (IMHO)