Rotierende Tangente

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag von PureLust »

Fluid Byte hat geschrieben:Kannste machen was de willst. Die Linie ist immer 1 Pixel zu weit rechts. Wie kann ich das beheben?
Also bei mir klappts (PB4.10-Beta2, Intel, WinXP).
Wenn ich bei Deinem Ursprungscode #WIDTH = 351 und #HEIGHT = 351 setze (that's it - nothing else) sitzt alles perfekt. :roll:

Code: Alles auswählen

#WIDTH = 351 : #HEIGHT = 351 : #WSPACE = 40 

CreateImage(0,#WIDTH + (#WSPACE * 2),#HEIGHT + (#WSPACE * 2)) 

OpenWindow(0,0,0,#WIDTH + (#WSPACE * 2),#HEIGHT + (#WSPACE * 2),"void",#WS_OVERLAPPEDWINDOW | 1) 
CreateGadgetList(WindowID(0)) 
ImageGadget(0,0,0,0,0,ImageID(0)) 

SetWindowColor(0,0) 

SetTimer_(WindowID(0),0,20,0) 
#Linelength = 100
Procedure WindowCallback(hWnd,uMsg,wParam,lParam) 
   Static Angle = 45 
    
   Select uMsg 
      Case #WM_TIMER       
      Angle + 1 
       
      StartDrawing(ImageOutput(0)) 
      Box(0,0,#WIDTH + (#WSPACE * 2),#HEIGHT + (#WSPACE * 2)) 
      Circle((#WIDTH / 2) + #WSPACE,(#HEIGHT / 2) + #WSPACE,11,#Red) 
      DrawingMode(4) 
      Circle((#WIDTH / 2) + #WSPACE,(#HEIGHT / 2) + #WSPACE,#WIDTH / 2,#HEIGHT / 2) 
      DrawingMode(0) 
       
      X1.f = Cos((Angle - 45) * #PI/180) * #WIDTH/2 
      Y1.f = Sin((Angle - 45) * #PI/180) * #HEIGHT/2 
      X2.f = Cos((Angle + 45) * #PI/180) * 100 
      Y2.f = Sin((Angle + 45) * #PI/180) * 100 
       
      FX.f = X1 + (#WIDTH / 2) + #WSPACE 
      FY.f = Y1 + (#HEIGHT / 2) + #WSPACE 
       
      LineXY(FX-X2-1,FY-Y2-1,FX + X2-1,FY + Y2-1,#Green) 

      StopDrawing() 
      SetGadgetState(0,ImageID(0))       
   EndSelect 
    
   ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

SetWindowCallback(@WindowCallback()) 

While WaitWindowEvent() ! 16 : Wend
Zuletzt geändert von PureLust am 16.07.2007 20:50, insgesamt 1-mal geändert.
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Nix bei misch alde. Guckst du hier:

Code: Alles auswählen

#Width = 351
#Height = 351
#WhiteSpace = 30
#Linelength = 100
#Radius = #Height / 2
#CenterX =  (#Width / 2) + #WhiteSpace
#CenterY =  (#Height / 2) + #WhiteSpace		
		
CreateImage(0,#Width + (#WhiteSpace * 2),#Height + (#WhiteSpace * 2))

OpenWindow(0,0,0,#Width + (#WhiteSpace * 2),#Height + (#WhiteSpace * 2),"void",#WS_OVERLAPPEDWINDOW | 1)
CreateGadgetList(WindowID(0))
ImageGadget(0,0,0,0,0,ImageID(0))

SetWindowColor(0,0)

SetTimer_(WindowID(0),0,40,0)

Procedure WindowCallback(hWnd,uMsg,wParam,lParam)
	Static Angle = 0
	
	Select uMsg
		Case #WM_TIMER
		Angle + 0
		
		StartDrawing(ImageOutput(0))
		Box(0,0,#Width + (#WhiteSpace * 2),#Height + (#WhiteSpace * 2))
		Circle((#Width / 2) + #WhiteSpace,(#Height / 2) + #WhiteSpace,11,#Red)
		DrawingMode(4)
		Circle((#Width / 2) + #WhiteSpace,(#Height / 2) + #WhiteSpace,#Width / 2,#Red)
		DrawingMode(0)		

		X1.f = Cos((Angle - 90) * #PI/180) * #Linelength/2
		Y1.f = Sin((Angle - 90) * #PI/180) * #Linelength/2
		X2.f = Cos((Angle + 90) * #PI/180) * #Linelength/2
		Y2.f = Sin((Angle + 90) * #PI/180) * #Linelength/2
		
		FX.f = #CenterX + Cos(Angle * #PI/180) * #Radius
		FY.f = #CenterY + Sin(Angle * #PI/180) * #Radius
		
		LineXY(FX + X1, FY + Y1, FX + X2, FY + Y2,#Green)		
	
		StopDrawing()
		
		SetGadgetState(0,ImageID(0))      
   EndSelect
   
	ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

SetWindowCallback(@WindowCallback())

While WaitWindowEvent() ! 16 : Wend
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

dann muss du einfach so tun als ob der Kreis weiter links ist :

x = Kreis_x - 1

wenn du den x-Wert des Kreises für die Linien brauchst.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

STARGÅTE hat geschrieben:dann muss du einfach so tun als ob der Kreis weiter links ist :

x = Kreis_x - 1

wenn du den x-Wert des Kreises für die Linien brauchst.
Theorie oder Praxis? Ich meine wie soll das ausehen? Dann stimmt es doch auf linken Seite nicht mehr. Oder hab das sprichwörtliche Brett vorm Kopf?
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag von PureLust »

STARGÅTE hat geschrieben:dann muss du einfach so tun als ob der Kreis weiter links ist :

x = Kreis_x - 1

wenn du den x-Wert des Kreises für die Linien brauchst.
Das wär'n Tick zu einfach. :mrgreen:

Das Problem ist, dass der Durchmesser des von Circle() gezeichneten Kreises im Grunde um 1 Pixel abweicht von der Durchmesser der durch Sin()/Cos() berechneten Kreisbahn auf der sich die Linie bewegt.
Wenn man nun also einfach die Umlaufbahn um einen Pixel verschiebt, so passt es dann plötzlich auf der anderen Seite nicht mehr.

[Edit] @FB: Haste mal meinen oben geposteten Code getestet?
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Hehehe Bild

Jesus, Maria und Joseph! Es wird doch wohl möglich sein das so hinzukriegen das es links/rechts und oben/unten exakt auf der Linie des Kreises liegt. Oder wat?

PS: Ja hab ich, selbes Ergebniss. Links liegt sie genau auf, nicht aber rechts.
Zuletzt geändert von Fluid Byte am 16.07.2007 21:08, insgesamt 3-mal geändert.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

wie wäre es dann, nicht die Circle-funktion von DicertDraw zu benutzen,
sondern den kreis selber zu zeichnen, mit der selben formel, mit der man den tagentialpunkt berechnet?
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Ne, der Radius brechnet sich durch die angegeben Breite bzw. Höhe. In meinen Beispiel 350 Px. Ich habs gescheckt, die Maße des Kreises stimmen. Es nicht der Kreis der angepaßt werden muss sondern die Formel.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag von PureLust »

Wie gesagt, mit Deiner ursprünglichen Berechnungsmethode klappts:

Code: Alles auswählen

;Code aus Platzgründen entfernt, da Code in Folgepost allgemeingültiger sein dürfte.
Zuletzt geändert von PureLust am 16.07.2007 22:18, insgesamt 1-mal geändert.
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag von PureLust »

Sodele .. nun hamm wir's abba. :mrgreen:

Das Problem war, dass der Circle()-Befehl ja einen Kreis mit einem geradzahligen Durchmesser zeichnet (2 x den angegebenen Radius).
Bei der eigene Kreisformel hingegen kommt ja immer ein Kreis mit einem ungeraden Durchmesser heraus (Radius+MittelPunkt+Radius).

Um nun also diese Abweichung von einem Pixel aufzufangen muss sowohl der Mittelpunkt als auch der Radius etwas angepasst werden (um etwa 0.333 Pixel).

Nachfolgend mal der angepasste Code der die von Kaeru beschriebene Formel verwendet:
(Die eigentlichen Anpassungen befinden sich in Zeile 5-7 bei den Werten für die Konstanten.)

Code: Alles auswählen

#Width = 350 
#Height = 350 
#WhiteSpace = 30 
#Linelength = 100 
#Radius = #Height / 2 - 0.333
#CenterX =  (#Width / 2) + #WhiteSpace - 0.333
#CenterY =  (#Height / 2) + #WhiteSpace - 0.333
Debug #CenterX  
       
CreateImage(0,#Width + (#WhiteSpace * 2),#Height + (#WhiteSpace * 2)) 

OpenWindow(0,0,0,#Width + (#WhiteSpace * 2),#Height + (#WhiteSpace * 2),"void",#WS_OVERLAPPEDWINDOW | 1) 
CreateGadgetList(WindowID(0)) 
ImageGadget(0,0,0,0,0,ImageID(0)) 

SetWindowColor(0,0) 

SetTimer_(WindowID(0),0,40,0) 

Procedure WindowCallback(hWnd,uMsg,wParam,lParam) 
   Static Angle = 0 
    
   Select uMsg 
      Case #WM_TIMER 
      Angle + 90 
       
      StartDrawing(ImageOutput(0)) 
;       Box(0,0,#Width + (#WhiteSpace * 2),#Height + (#WhiteSpace * 2)) 
      Circle((#Width / 2) + #WhiteSpace,(#Height / 2) + #WhiteSpace,11,#Red) 
      DrawingMode(4) 
      Circle((#Width / 2) + #WhiteSpace,(#Height / 2) + #WhiteSpace,#Width / 2,#Red) 
      DrawingMode(0)       

      X1.f = Cos((Angle - 90) * #PI/180) * #Linelength/2 
      Y1.f = Sin((Angle - 90) * #PI/180) * #Linelength/2 
      X2.f = Cos((Angle + 90) * #PI/180) * #Linelength/2 
      Y2.f = Sin((Angle + 90) * #PI/180) * #Linelength/2 
       
      FX.f = #CenterX + Cos(Angle * #PI/180) * #Radius 
      FY.f = #CenterY + Sin(Angle * #PI/180) * #Radius 
       
      LineXY(FX + X1, FY + Y1, FX + X2, FY + Y2,#Green)       
    
      StopDrawing() 
       
      SetGadgetState(0,ImageID(0))      
   EndSelect 
    
   ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

SetWindowCallback(@WindowCallback()) 

While WaitWindowEvent() ! 16 : Wend
Grüße, PL.
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Antworten