DrawOvalEx

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

Der Eisvogel

Betreff: DrawOvalEx

BeitragFr, Apr 10, 2009 14:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo
Da ich bei meinem aktuellen Projekt eine Ellipse ohne Füllung brauche, habe ich mir eine gecodet:
Code: [AUSKLAPPEN]
Function DrawOvalEx(x:Int,y:Int,width:Int,height:Int,fill:Byte=True)
   If fill=False Then
      Local hnd_x:Float,hnd_y:Float ; GetHandle(hnd_x,hnd_y) ; SetHandle 0,0
      Local rot:Int=GetRotation() ; SetRotation 0
      Local scl_x:Float,scl_y:Float ; GetScale(scl_x,scl_y) ; SetScale 1,1
      
      width:*scl_x/2
      height:*scl_y/2
      
      Local tx1:Float=(1+Cos(0))*(width)-hnd_x
      Local ty1:Float=(1+Sin(0))*(height)-hnd_y
      Local tx2:Float,ty2:Float
      Local w:Float=ATan2(ty1,tx1)
      Local pyt:Float=Sqr(tx1*tx1+ty1*ty1)
      tx1=Cos(w+rot)*pyt
      ty1=Sin(w+rot)*pyt
      
      For Local r:Int=1 To 360
         tx2=(1+Cos(r))*(width)-hnd_x
         ty2=(1+Sin(r))*(height)-hnd_y
         If rot Mod 360<>0 Then
            w=ATan2(ty2,tx2)
            pyt=Sqr(tx2*tx2+ty2*ty2)
            tx2=Cos(w+rot)*pyt
            ty2=Sin(w+rot)*pyt
         EndIf
         DrawLine x+tx1,y+ty1,x+tx2,y+ty2
         
         tx1=tx2
         ty1=ty2
      Next
      
      SetHandle hnd_x,hnd_y
      SetRotation rot
      SetScale scl_x,scl_y
   Else
      DrawOval x,y,width,height
   EndIf
End Function


Sie ist zwar langsamer, aber kann alles was die Hauseigene Funktion von BM kann.
Sie kann allerdings auch, was ja auch der Sinn ist, eine Ellipse ohne Füllung zeichnen.

Parameter:
x Arrow X-Koordinate
y Arrow Y-Koordinate
width Arrow Breite
height Arrow Höhe
fill Arrow Füllung=True

Wenn man bei fill False angibt, wird einfach die Hauseigene Funktion DrawOval mit den angegebenen Parametern ausgeführt.

Ich hoffe es nutzt dem ein oder anderen auch etwas.

Hier noch ein Beispielprogramm:
Code: [AUSKLAPPEN]
SuperStrict

Graphics 800,600

Local x:Int=200,y:Int=300
Local width:Int=100,height:Int=200
Local fill:Byte
Local hnd_x:Float,hnd_y:Float
Local rot:Int=0
Local scl_x:Float=1,scl_y:Float=1
Local org_x:Int,org_y:Int

Repeat
   Cls
   
   If KeyDown(KEY_SPACE) Then
      If KeyDown(KEY_LEFT) Then hnd_x:-3
      If KeyDown(KEY_RIGHT) Then hnd_x:+3
      If KeyDown(KEY_UP) Then hnd_y:-3
      If KeyDown(KEY_DOWN) Then hnd_y:+3
      
      If KeyDown(KEY_A) Then scl_x:-.01
      If KeyDown(KEY_D) Then scl_x:+.01
      If KeyDown(KEY_W) Then scl_y:-.01
      If KeyDown(KEY_S) Then scl_y:+.01
   Else
      If KeyDown(KEY_LEFT) Then x:-3
      If KeyDown(KEY_RIGHT) Then x:+3
      If KeyDown(KEY_UP) Then y:-3
      If KeyDown(KEY_DOWN) Then y:+3
      
      If KeyDown(KEY_A) Then width:-3
      If KeyDown(KEY_D) Then width:+3
      If KeyDown(KEY_W) Then height:-3
      If KeyDown(KEY_S) Then height:+3
   EndIf
   
   
   If KeyHit(KEY_C) Then fill=1-fill
   
   If KeyDown(KEY_Q) Then rot:-3-360*(rot<0)
   If KeyDown(KEY_E) Then rot:+3-360*(rot>360)
   
   If KeyDown(KEY_F) Then org_x:-3
   If KeyDown(KEY_H) Then org_x:+3
   If KeyDown(KEY_T) Then org_y:-3
   If KeyDown(KEY_G) Then org_y:+3
   
   If KeyHit(KEY_R) Then
      x=200
      y=300
      width=100
      height=200
      fill=0
      hnd_x=0
      hnd_y=0
      rot=0
      scl_x=1
      scl_y=1
      org_x=0
      org_y=0
   EndIf
   
   
   SetDrawDefaults()
   SetHandle hnd_x,hnd_y
   SetRotation rot
   SetScale scl_x,scl_y
   SetOrigin org_x,org_y
   Local ms:Int=MilliSecs()
   DrawOvalEx x,y,width,height,fill
   SetDrawDefaults()
   DrawText (MilliSecs()-ms)+"ms",GraphicsWidth()-30,20
   
   
   DrawFPS GraphicsWidth()-30,5
   DrawText "X-Koordinate: "+x+" - Y-Koordinate: "+y,10,10
   DrawText "Breite: "+width+" - Hoehe: "+height,10,25
   DrawText "Rotation: "+rot,10,40
   DrawText "Handle-X: "+hnd_x+" - Handle-Y: "+hnd_y,10,55
   DrawText "Scale-X: "+scl_x+" - Scale-Y: "+scl_y,10,70
   DrawText "Origin-X: "+org_x+" - Origin-Y: "+org_y,10,85
   
   
   SetColor 255,0,0
   
   DrawOval x-3,y-3,6,6
   DrawTextEx "XY-Koordinaten",x,y-20,1
   
   DrawRect x-hnd_x,y-hnd_y+height*scl_y,width*scl_x,1
   DrawTextEx "Breite ("+Abs(width*scl_x)+"px)",x-hnd_x+(width*scl_x)/2,y-hnd_y+height*scl_y+3,1,0
   
   DrawRect x-hnd_x+width*scl_x,y-hnd_y,1,height*scl_y
   DrawTextEx "Hoehe ("+Abs(height*scl_y)+"px)",x-hnd_x+width*scl_x+3,y-hnd_y+(height*scl_y)/2,0,1
   
   DrawOval x-3,y-3,6,6
   DrawTextEx "Handle-XY",x,y+5,1
   
   DrawOval -3,-3,6,6
   DrawTextEx "Origin-XY",0,5,1
   
   Flip
Until KeyHit(KEY_ESCAPE)
End





Function DrawOvalEx(x:Int,y:Int,width:Int,height:Int,fill:Byte=True)
   If fill=False Then
      Local hnd_x:Float,hnd_y:Float ; GetHandle(hnd_x,hnd_y) ; SetHandle 0,0
      Local rot:Int=GetRotation() ; SetRotation 0
      Local scl_x:Float,scl_y:Float ; GetScale(scl_x,scl_y) ; SetScale 1,1
      
      width:*scl_x/2
      height:*scl_y/2
      
      Local tx1:Float=(1+Cos(0))*(width)-hnd_x
      Local ty1:Float=(1+Sin(0))*(height)-hnd_y
      Local tx2:Float,ty2:Float
      Local w:Float=ATan2(ty1,tx1)
      Local pyt:Float=Sqr(tx1*tx1+ty1*ty1)
      tx1=Cos(w+rot)*pyt
      ty1=Sin(w+rot)*pyt
      
      For Local r:Int=1 To 360
         tx2=(1+Cos(r))*(width)-hnd_x
         ty2=(1+Sin(r))*(height)-hnd_y
         If rot Mod 360<>0 Then
            w=ATan2(ty2,tx2)
            pyt=Sqr(tx2*tx2+ty2*ty2)
            tx2=Cos(w+rot)*pyt
            ty2=Sin(w+rot)*pyt
         EndIf
         DrawLine x+tx1,y+ty1,x+tx2,y+ty2
         
         tx1=tx2
         ty1=ty2
      Next
      
      SetHandle hnd_x,hnd_y
      SetRotation rot
      SetScale scl_x,scl_y
   Else
      DrawOval x,y,width,height
   EndIf
End Function





Function DrawTextEx(txt:String,x:Int,y:Int,zentr_x:Int=False,zentr_y:Int=False)
   If zentr_x Then x=x-TextWidth(txt)/2
   If zentr_y Then y=y-TextHeight(txt)/2
   DrawText txt,x,y
End Function





Function SetDrawDefaults()
   SetHandle 0,0
   SetAlpha 1
   SetScale 1,1
   SetRotation 0
   SetColor 255,255,255
End Function





Function DrawFPS(x:Int,y:Int)
   ?debug
   Global fps_ms:Int
   Global fps:Int,fps_:Int
   If MilliSecs()>fps_ms+1000 Then
      fps_ms=MilliSecs()
      fps=fps_
      fps_=0
   EndIf
   fps_:+1
   
   DrawText fps,x,y
   ?
End Function


Viel Spaß damit!

PS: Nein, Bugs sollt ihr nicht behalten. Wink


EDIT: Achso, ja die Steurung noch:
Gedrückte Leertaste:
Arrow Pfeiltasten: Handle verschieben
Arrow WASD: Scale verändern
Nicht gedrückte Leertaste:
Arrow Pfeiltaste: Koordinaten verschieben
Arrow WASD: Breite/Höhe verändern

QE: Rotation
C: Umschaltung zw. Füllung und ohne Füllung
R: Alles zurücksetzten

TFGH: Origin verschieben
MfG
Der Eisvogel
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.

BtbN

BeitragFr, Apr 10, 2009 15:37
Antworten mit Zitat
Benutzer-Profile anzeigen
Code: [AUSKLAPPEN]
Function DrawOvalEx(x:Float, y:Float, w:Float, h:Float, fill:Int = True)
   If (Not fill) And _max2dDriver.toString().toLower() = "opengl" Then
      Local tmp:Int
      glGetIntegerv(GL_POLYGON_MODE, Varptr(tmp)) ' Originalwert zwischenspeichern

      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) ' In den Line-Modus setzen
      DrawOval(x,y,w,h) ' Das Oval zeichnen

      glPolygonMode(GL_FRONT_AND_BACK, tmp) ' Originalwert wiederherstellen
   Else ' Kein OpenGL benutzt oder gefüllt gefordert
      DrawOval(x,y,w,h)
   EndIf
EndFunction


Sollte um einiges Schneller sein, funktioniert aber nur mit OpenGL.

Midimaster

BeitragFr, Dez 25, 2009 1:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Der Code macht es genauso schnell wie Eisvogels Code, sieht aber nicht so dramatisch aus:

BlitzMax: [AUSKLAPPEN]
Function MeinOval(x%,y%,b%,h%,Filled%)
Local i%
If Filled=0 Then
B=B/2
H=H/2
For i=0 To 360
DrawLine x+Sin(i)*b,y+Cos(i)*h,x+Sin(i+1)*b,y+Cos(i+1)*h
Next
Else
DrawOval X,Y,B,H
EndIf
End Function


...und ich glaub, ich könnte es auch noch schneller.....muss aber erst ausprobieren...
  • Zuletzt bearbeitet von Midimaster am Fr, Dez 25, 2009 20:54, insgesamt einmal bearbeitet

Der Eisvogel

BeitragFr, Dez 25, 2009 2:00
Antworten mit Zitat
Benutzer-Profile anzeigen
So hatte ich es damals auch, aber einige Features haben so ihre Funktion verfehlt, weiß aber gerade nicht mehr welche das waren.
Ungarische Notation kann nützlich sein.
BlitzMax ; Blitz3D
Win 7 Pro 64 Bit ; Intel Core i7-860 ; 8 GB Ram ; ATI HD 5750 1 GB
Projekte: Window-Crasher
Ich liebe es mit der WinAPI zu spielen.

Midimaster

BeitragSo, Dez 27, 2009 3:36
Antworten mit Zitat
Benutzer-Profile anzeigen
So, nun hier der versprochene superflotte Algoritmus für nicht gefüllte Ovale und Kreise:

Der Algoritmus ist etwa 2-20x schneller und zeichnet sehr saubere Ovale. Man kann die Ovale in diesem Beispiel nicht rotieren. (Machen liese sich das aber nach einer Code-Änderung schon)

BlitzMax: [AUSKLAPPEN]
Function FastOval(X%,Y%,B%,H%,Filled%=0)
' free public domain source code by midimaster
If Filled=0 Then
'part I
Local Mal:TPixmap=CreatePixmap(B*0.3+2,H*0.7+2,PF_RGBA8888)
ClearPixels Mal
For Local I#=225 To 270 Step .1
WritePixel Mal,B*(1+Sin(i))+1,H*(0.7+Cos(i))+1,$ffffffff
Next
Local Bild:TImage=LoadImage(Mal)

'part II
Mal:TPixmap=CreatePixmap(B*0.7+2,H*0.3+2,PF_RGBA8888)
ClearPixels Mal
For I#=180 To 225 Step .1
WritePixel Mal,B*(0.7+Sin(i))+1,H*(1+Cos(i))+1,$ffffffff
Next
Local Bild2:TImage=LoadImage(Mal)


SetScale 1,1
DrawImage Bild,X-1,Y-1+h*0.3
SetScale -1,1
DrawImage Bild,X-1+2*b,Y-1+h*0.3
SetScale 1,-1
DrawImage Bild,X-1,Y-1+1.7*h
SetScale -1,-1
DrawImage Bild,X-1+2*b,Y-1+1.7*h


SetScale 1,1
DrawImage Bild2,X-1+b*0.3,Y-1
SetScale -1,1
DrawImage Bild2,X-1+1.7*b,Y-1
SetScale 1,-1
DrawImage Bild2,X-1+b*0.3,Y-1+2*h
SetScale -1,-1
DrawImage Bild2,X-1+1.7*b,Y-1+2*h
Else
DrawOval X,Y,B,H

EndIf
End Function


So geht es:

In einer Pixmap werden 2 Achtelkreise gezeichnet und dann je 4x in den Screen kopiert.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group