Seite 2 von 3

Verfasst: 16.07.2007 20:48
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

Verfasst: 16.07.2007 20:49
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

Verfasst: 16.07.2007 20:53
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.

Verfasst: 16.07.2007 20:57
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?

Verfasst: 16.07.2007 20:59
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?

Verfasst: 16.07.2007 21:01
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.

Verfasst: 16.07.2007 21:02
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?

Verfasst: 16.07.2007 21:04
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.

Verfasst: 16.07.2007 21:21
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.

Verfasst: 16.07.2007 22:15
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.