Angle degree to X,Y and back (simple trig)

Just starting out? Need help? Post your questions and find answers here.
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Angle degree to X,Y and back (simple trig)

Post by Keya »

trying to brush some dust off my trigonometry! :)
I have a circle and want to draw a line exactly like a clock hand, so I'm converting degrees to X&Y and drawing that line ok

But how then to convert the X&Y back to degrees??? I've run out of combinations to try

Code: Select all

If OpenWindow(0, 0, 0, 200, 200, "Trig", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  If CreateImage(0, 200, 200) And StartDrawing(ImageOutput(0))
    
    #MiddleX = 100
    #MiddleY = 100
    #LineLen = 80
    Circle(#MiddleX,#MiddleY, #LineLen,$00A000) 
    
    ;// DEGREES to X,Y  (this part seems fine)
    Degrees = 90
    
    Debug "Degrees = " + Str(Degrees)        
    CalcDegrees = 360 - Degrees + 180
    XX.f = Sin(CalcDegrees * (2 * #PI / 360))
    YY.f = Cos(CalcDegrees * (2 * #PI / 360))
    LineXY(#MiddleX, #MiddleY, #MiddleX + (XX * #LineLen),
           #MiddleY + (YY * #LineLen),           $FFFFFF)
    Debug "X="+StrF(XX)  + "  Y=" + StrF(YY)
    
;?????????????????????????????????????????    
    ;// X,Y back to DEGREES  (not right!)
    rad.f = ATan2(#MiddleX+XX, #MiddleY+YY)
    deg.f = rad * 180.0 / #PI
    Debug "v1 Degrees  = " + StrF(deg)
    Debug "v2 Degree() = " + Degree(rad)
;?????????????????????????????????????????    
       
    StopDrawing() 
    ImageGadget(0, 0, 0, 200, 200, ImageID(0))
  EndIf
  
  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
EndIf
MrMat
Enthusiast
Enthusiast
Posts: 762
Joined: Sun Sep 05, 2004 6:27 am
Location: England

Re: Angle degree to X,Y and back (simple trig)

Post by MrMat »

Hello,

Try this:

Code: Select all

rad.f = Mod(ATan2(-YY, XX)+2*#PI,2*#PI)
deg.f = rad * 180.0 / #PI
You don't really need the mod, it is just to convert to a range of 0...2*PI and 0...360.

Cheers,
Mat
Mat
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Angle degree to X,Y and back (simple trig)

Post by Keya »

super, thankyou and thanks for the Mod tip! it feels good to brush the dust off the trig in my mind so I can work outside the box
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

Re: Angle degree to X,Y and back (simple trig)

Post by vwidmer »

I was trying to make a wind gauge from your code but not having luck to get it to show right.

It only shows nice which this but if I try to change then it all turns black.

Can some one help me with this please.

thanks

Code: Select all

Procedure windGauge(windDir.i,windMsg.s)
  
    If CreateImage(0, 200, 200,32,$FFFFFF) And StartDrawing(ImageOutput(0))
   
    MiddleX = ImageWidth(0) / 2
    MiddleY = ImageHeight(0) /2
    LineLen = ImageWidth(0) / 2 - 20
    Circle(MiddleX,MiddleY, LineLen+10,$818282)
    Circle(MiddleX,MiddleY, LineLen+5,$FFFFFF)
    
    Degrees = windDir   
    Debug "Degrees = " + Str(Degrees)    
    
    CalcDegrees = 360 - Degrees + 180
    XX.f = Sin(CalcDegrees * (2 * #PI / 360))
    YY.f = Cos(CalcDegrees * (2 * #PI / 360))
    LineXY(MiddleX, MiddleY, MiddleX + (XX * LineLen), MiddleY + (YY * LineLen), $FFFFFF)
    
    DrawText(MiddleX - (ImageWidth(0) * 0.04),(ImageHeight(0) * 0.10),"N",$0,$FFFFFF)
    ;DrawText(170,90,"E",$FFFFFF,$00A000)
    ;DrawText(95,165,"S",$FFFFFF,$00A000)
    ;DrawText(20,90,"W",$FFFFFF,$00A000)
    DrawText(MiddleX-20,MiddleY-10,windMsg,$0,$FFFFFF)
    
    ;- Arrow Stuff
    x1 = MiddleX
    y1 = MiddleY
    x2 = MiddleX + (XX * LineLen)
    y2 = MiddleY + (YY * LineLen)
    
    length = -20.0 ;length = arrow line length
    tightness = 2
    ;tightness = arrowhead tightness; range 1 -> 10, 1 is the least tight, 10 is the tightest.
    slopY = ATan2(x1 - x2, y1 - y2)
    cosY = Cos(slopY)
    sinY = Sin(slopY)
    
    LineXY(x2, y2, x2 + Int(length * cosY - length / tightness * sinY), y2 + Int(length * sinY + length / tightness * cosY ),$0)
    LineXY(x2 + Int(length * cosY + length / tightness * sinY ), y2 - Int(length / tightness * cosY  - length * sinY),x2, y2,$0)
    LineXY(x2 + Int(length * cosY - length / tightness * sinY), y2 + Int(length * sinY + length / tightness * cosY ),x2 + Int(length * cosY + length / tightness * sinY ), y2 - Int(length / tightness * cosY  - length * sinY),$0)
    
    FillArea(MiddleX + (XX * LineLen)+10, MiddleY + (YY * LineLen),$0,$0)
    
    Debug "X="+StrF(XX)  + "  Y=" + StrF(YY)
   
;?????????????????????????????????????????   
    rad.f = Mod(ATan2(-YY, XX)+2*#PI,2*#PI)
    deg.f = rad * 180.0 / #PI
    Debug "v1 Degrees  = " + StrF(deg)
    Debug "v2 Degree() = " + Degree(rad)
;?????????????????????????????????????????   

    StopDrawing()
    ImageGadget(0, 0, 0, 150, 150, ImageID(0))
  EndIf
  
EndProcedure

If OpenWindow(0, 0, 0, 200, 200, "Wind", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  windGauge(90,"20kn")
 
  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
EndIf
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA
User avatar
STARGÅTE
Addict
Addict
Posts: 2067
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: Angle degree to X,Y and back (simple trig)

Post by STARGÅTE »

1. If you calc Sin and Cos or Tan it should be stored in a float number!

Code: Select all

    slopY.f = ATan2(x1 - x2, y1 - y2)
    cosY.f = Cos(slopY)
    sinY.f = Sin(slopY)

2. Your FillArea() seems to be wrong. Without, it works
3. Try to work with the VectorDrawing lib, it is much more easier with rotation and filling.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

Re: Angle degree to X,Y and back (simple trig)

Post by vwidmer »

STARGÅTE wrote:1. If you calc Sin and Cos or Tan it should be stored in a float number!
3. Try to work with the VectorDrawing lib, it is much more easier with rotation and filling.
Thank you it is working now..

If you have a sec can you please give me more info on the VectorDrawing lib, an example or point me somewhere..

Thanks
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA
User avatar
STARGÅTE
Addict
Addict
Posts: 2067
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: Angle degree to X,Y and back (simple trig)

Post by STARGÅTE »

Here a small example.
It shows a circle with an arrow and it shows the direction of you mouse:

Code: Select all

Enumeration
	#Window
	#Gadget
	#Timer
EndEnumeration

Procedure Update()
	
	Protected Angle.f
	
	If StartVectorDrawing(CanvasVectorOutput(#Gadget))
		
		VectorSourceColor($FFFFFFFF)
		FillVectorOutput() ; fill all with white
		
		VectorSourceColor($FF808080)
		AddPathCircle(200, 200, 180) 
		StrokePath(5) ; gray circle with 5px thickness
		
		Angle = ATan2(DesktopMouseX()-WindowX(#Window, #PB_Window_InnerCoordinate)-200, DesktopMouseY()-WindowY(#Window, #PB_Window_InnerCoordinate)-200) ; angle between mouse and center
		TranslateCoordinates(200, 200) ; Center
		RotateCoordinates(0, 0, Degree(Angle)) ; Rotation
		TranslateCoordinates(160, 0)  ; Shift to circle
		VectorSourceColor($FF00C040)
		MovePathCursor(30, 0)
		AddPathLine(-10, -15)
		AddPathLine(-10, 15)
		ClosePath()
		FillPath() ; green triangle filled
		
		StopVectorDrawing()
	EndIf
	
EndProcedure

OpenWindow(#Window, 0, 0, 400, 400, "Vector Demo", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CanvasGadget(#Gadget, 0, 0, WindowWidth(#Window), WindowHeight(#Window))
AddWindowTimer(#Window, #Timer, 20)

Repeat
	
	Select WaitWindowEvent()
		Case #PB_Event_Timer
			Select EventTimer()
				Case #Timer
					Update()
			EndSelect
		Case #PB_Event_CloseWindow
			End
	EndSelect
ForEver
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
vwidmer
Enthusiast
Enthusiast
Posts: 282
Joined: Mon Jan 20, 2014 6:32 pm

Re: Angle degree to X,Y and back (simple trig)

Post by vwidmer »

Wow very nice example.. Thank you very much.
WARNING: I dont know what I am doing! I just put stuff here and there and sometimes like magic it works. So please improve on my code and post your changes so I can learn more. TIA
Little John
Addict
Addict
Posts: 4519
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Angle degree to X,Y and back (simple trig)

Post by Little John »

Hi Stargate,

that's a nice example, thank you!

When I tested your code with PB 5.71 beta 1, it turned out that the DPI awareness flag was set in my IDE. Thus the circle wasn't in the center of the window, and the green arrow did not always point into the right direction.
As an exercise for myself, I changed your code so that it now works with and without the DPI awareness flag set:

Code: Select all

; tested with PB 5.71 beta 1 (x64) on Windows 10
; (compiled with and without the DPI awareness flag set)

EnableExplicit

Enumeration
   #Window
   #Gadget
   #Timer
EndEnumeration


Procedure Update (cx.i, cy.i)
   ; in: cx, cy: coordinates of the center of the circle
   Protected Angle.f, cxs.f, cys.f
   
   If StartVectorDrawing(CanvasVectorOutput(#Gadget))
      VectorSourceColor($FFFFFFFF)
      FillVectorOutput()             ; white background
      
      cxs = DesktopScaledX(cx)
      cys = DesktopScaledY(cy)
      
      VectorSourceColor($FF808080)
      AddPathCircle(cxs, cys, DesktopScaledX(cx-20))
      StrokePath(DesktopScaledX(5))  ; gray circle
      
      Angle = ATan2(DesktopMouseX()-WindowX(#Window, #PB_Window_InnerCoordinate)-cx, DesktopMouseY()-WindowY(#Window, #PB_Window_InnerCoordinate)-cy) ; angle between mouse and center
      TranslateCoordinates(cxs, cys)                         ; Center
      RotateCoordinates(0, 0, Degree(Angle))                 ; Rotation
      TranslateCoordinates(DesktopScaledX(cx-40), 0)         ; Shift to circle
      VectorSourceColor($FF00C040)
      MovePathCursor(DesktopScaledX(30), 0)
      AddPathLine(-DesktopScaledX(10), -DesktopScaledY(15))
      AddPathLine(-DesktopScaledX(10),  DesktopScaledY(15))
      ClosePath()
      FillPath()                     ; green triangle filled
      
      StopVectorDrawing()
   EndIf
EndProcedure


Define.i cx = 200, cy = 200

OpenWindow(#Window, 0, 0, 2*cx, 2*cy, "Vector Demo", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CanvasGadget(#Gadget, 0, 0, WindowWidth(#Window), WindowHeight(#Window))
AddWindowTimer(#Window, #Timer, 20)

Repeat
   Select WaitWindowEvent()
      Case #PB_Event_Timer
         Select EventTimer()
            Case #Timer
               Update(cx, cy)
         EndSelect
      Case #PB_Event_CloseWindow
         End
   EndSelect
ForEver
User avatar
Altenburger
New User
New User
Posts: 5
Joined: Thu Aug 22, 2019 7:35 am

Re: Angle degree to X,Y and back (simple trig)

Post by Altenburger »

trig student wrote:

It was quite simple. I tried some combinations from https://domyhomeworkonline.net/do-my-trigonometry-homework.php X&Y samples.
Simple trigonometry? As you wish ;)

I didn't find it that easy to grasp at the first time.

https://stackoverflow.com/questions/159 ... o-an-angle
AZJIO
Addict
Addict
Posts: 1319
Joined: Sun May 14, 2017 1:48 am

Re: Angle degree to X,Y and back (simple trig)

Post by AZJIO »

I tried to figure out which sector the mouse is in and ended up making buttons.

Code: Select all

EnableExplicit

#Window_1 = 1
Define h, m
Define i, j, EvnGd, EvWin

If OpenWindow(#Window_1, #PB_Ignore, #PB_Ignore, 500, 500, "Timer")
	j=0
	For i=0 To 359 Step 15
		ButtonGadget(j+1000 , 160 * Cos(Radian(i-90))+230 , 160 * Sin(Radian(i-90))+230 , 30 , 30 , Str(j), #PB_Button_Toggle)
		j+1
	Next
	j=0
	For i=0 To 359 Step 6
		ButtonGadget(j+1100 , 236 * Cos(Radian(i-90))+239 , 236 * Sin(Radian(i-90))+239 , 19 , 19 , Str(j), #PB_Button_Toggle)
		j+1
	Next
	
	h = 0
	m = 0
	
	; Обработать гаджеты только этого окна
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_Gadget
				EvnGd = EventGadget()
				Select EvnGd
					Case 1000 To 1023
						For i=1000 To 1023
							If GetGadgetState(EvnGd) = 1 And i <> EvnGd
								SetGadgetState(i , 0)
								h = EvnGd - 1000
							EndIf
						Next
					Case 1100 To 1159
						For i=1100 To 1159
							If GetGadgetState(EvnGd) = 1 And i <> EvnGd
								SetGadgetState(i , 0)
								m = EvnGd - 1100
							EndIf
						Next
				EndSelect
			Case #PB_Event_CloseWindow
				CloseWindow(#Window_1)
				Break
		EndSelect
	ForEver
EndIf

If h = 0 And m = 0
	MessageRequester("Message", "Specify timer time")
Else
	MessageRequester("Message", Str(h) + #LF$ + Str(m))
EndIf
Post Reply