Linefunktion (mit/ohne Füllung) schnell

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

 

zimtstern#3

Betreff: Linefunktion (mit/ohne Füllung) schnell

BeitragDi, Apr 12, 2005 16:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Das ist die schnellste line funktion für Mit und Ohne Füllung die mir bis jetzt untergekommen ist. Wurde von einem Freund von mir basierend auf dem Bresenham Algorithmuss geschrieben. Ich hoffe sie kann einigen von euch weiter helfen.

Läuft unter B2d und B+ im Unlocked Buffer.

Code: [AUSKLAPPEN]

Graphics 800,600,16,2
SetBuffer BackBuffer()
ClsColor 255,255,255
Color 255,0,0

radius = 50
Dim pixelup(1)
Dim pixeldown(1)
füll = 1
While Not KeyHit(1)
   Cls
   If MouseHit(1) Then
      beg = beg + 1
      If beg > 1 Then beg = 0
   EndIf
   If MouseHit(2) Then
      füll = füll + 1
      If füll > 1 Then füll = 0
   EndIf
   If MouseZ()+50 >= 0 Then  radius = MouseZ() + 50
   
   
   Linie4(400,300,MouseX(),MouseY(),radius,beg,füll)
   
   
   Flip
Wend

End

Function linie4(X1,Y1,X2,Y2,radius#, begrenzung=0, gefüllt=1)

Local rgb=ColorRed()*$10000 + ColorGreen()*$100 + ColorBlue()
Local a,b,c,d
Local X,Y,P
Local alpha#,cosalpha#,sinalpha#
Local dx#,dy#,dx1,dy1,dx2,dy2
Local m#,e#,f#
dx = (X2 - X1)
dy = (Y2 - Y1)
If dx=0 Or dy=0 Then;horizontal oder vertikal///////////////////////////////////////////////////
   If begrenzung = 0 And gefüllt = 0 Then;nicht gefüllt und kreisförmig
      If dx=0 Then
         If Y2<Y1 Then
            a=Y1
            Y1=Y2
            Y2=a
         EndIf
         Line X1-radius, Y1, X2-radius, Y2
         Line X1+radius, Y1, X2+radius, Y2
      Else
         If X2<X1 Then
            a=X1
            X1=X2
            X2=a   
         EndIf
         Line X1, Y1-radius, X2, Y2-radius
         Line X1, Y1+radius, X2, Y2+radius
      EndIf
      
      a = 4
      b = 4
      c = 4
      X = 0
      Y = radius
      P = 3 - (radius * a)

      While X < Y
         WritePixel X1 - X,Y1 - Y,rgb
         WritePixel X2 + X,Y1 - Y,rgb
         WritePixel X1 - Y,Y1 - X,rgb
         WritePixel X2 + Y,Y1 - X,rgb
         
         WritePixel X1 - X,Y2 + Y,rgb
         WritePixel X2 + X,Y2 + Y,rgb
         WritePixel X1 - Y,Y2 + X,rgb
         WritePixel X2 + Y,Y2 + X,rgb
         If P < 0 Then
            P = P + (X * 4) + 6
         Else
            P = P + ((X - Y) * 4) + 12
            Y = Y - 1
         EndIf
            X = X + 1
      Wend
   
      If X = Y Then
         WritePixel X1 - X,Y1 - Y,rgb
         WritePixel X2 + X,Y1 - Y,rgb
         WritePixel X1 - X,Y2 + Y,rgb
         WritePixel X2 + X,Y2 + Y,rgb
      EndIf


   EndIf

   If begrenzung = 0 And gefüllt = 1 Then;gefüllt und kreisförmig
      If dx=0 Then
         If Y2<Y1 Then
            a=Y1
            Y1=Y2
            Y2=a
         EndIf
         Line X1-radius, Y1, X2-radius, Y2
         Line X1+radius, Y1, X2+radius, Y2
      Else
         If X2<X1 Then
            a=X1
            X1=X2
            X2=a   
         EndIf
         Line X1, Y1-radius, X2, Y2-radius
         Line X1, Y1+radius, X2, Y2+radius
      EndIf
      
      a = 4
      b = 4
      c = 4
      X = 0
      Y = radius
      P = 3 - (radius * a)

      While X < Y
         Rect X1-X, Y1-Y, -X1+X2+2*X, -Y1+Y2+2*Y
         Rect X1-Y, Y1-X, -X1+X2+2*Y, -Y1+Y2+2*X
         
         If P < 0 Then
            P = P + (X * 4) + 6
         Else
            P = P + ((X - Y) * 4) + 12
            Y = Y - 1
         EndIf
            X = X + 1
      Wend
   
   EndIf
Else;schiefe linein/////////////////////////////////////////////
   If begrenzung = 0 And gefüllt = 0 Then;nicht gefüllt und kreisförmig
      a = 4
      b = 4
      c = 4
      X = 0
      Y = radius
      P = 3 - (radius * a)
   
      alpha = ATan2(Y2-Y1,X2-X1)
      cosalpha = Cos(alpha)
      sinalpha = Sin(alpha)
   
      While X <= Y
      
         dx1 = ( cosalpha * Y + sinalpha*x)
         dy1 = ( sinalpha * Y - cosalpha*x)
         dx2 = ( cosalpha * Y - sinalpha*x)
         dy2 = (-sinalpha * Y - cosalpha*x)
         WritePixel X1-dx1, y1-dy1, rgb
         WritePixel X1-dx2, y1+dy2, rgb
         WritePixel X1+dy1, y1-dx1, rgb
         WritePixel X1+dy2, Y1+dx2, rgb
         WritePixel X2+dx1, y2+dy1, rgb
         WritePixel X2+dx2, y2-dy2, rgb
         WritePixel X2-dy1, y2+dx1, rgb
         WritePixel X2-dy2, Y2-dx2, rgb
               
         If P < 0 Then
            P = P + (X * b) + 6
         Else
            P = P + ((X - Y) * c) + 12
            Y = Y - 1
         EndIf
         X = X + 1
      Wend
      Line X1+sinalpha*radius, Y1+cosalpha*-radius, X2+sinalpha*radius, Y2+cosalpha*-radius
      Line X1+sinalpha*-radius, Y1+cosalpha*radius, X2+sinalpha*-radius, Y2+cosalpha*radius
      
   EndIf

   
   If begrenzung = 0 And gefüllt = 1 Then;gefüllt und kreisförmig
      If Abs(X1)>Abs(X2) Then;vertauscht die koordinaten so, dass die linien immer von "rechts" nach "links" geht
         a=X1
         X1=X2
         X2=a
         a=Y1
         Y1=Y2
         Y2=a   
      EndIf
      dx = (X2 - X1)
      dy = (Y2 - Y1)
      If Abs(dy)>Abs(dx) Then;vertauscht die koordinaten so, dass dx kleiner dy
         a=X1
         X1=Y1
         Y1=a
         a=X2
         X2=Y2
         Y2=a
         vertauscht=1
      EndIf
      dx = (X2 - X1)
      dy = (Y2 - Y1)

      a = 4
      b = 4
      c = 4
      X = 0
      Y = radius
      P = 3 - (radius * a)
   
      radius = radius+1;!
      Dim pixelup(2*radius)
      Dim pixeldown(2*radius)
      ;radius = radius-1;!
      alpha = ATan2(Y2-Y1,X2-X1)
      cosalpha = Cos(alpha)
      sinalpha = Sin(alpha)
      m=dy/dx
   
      While X <= Y;schreibt den kreisförmigen Teil der linie in das arrey
      
         dx1 = ( cosalpha * Y + sinalpha*x)
         dy1 = ( sinalpha * Y - cosalpha*x)
         dx2 = ( cosalpha * Y - sinalpha*x)
         dy2 = (-sinalpha * Y - cosalpha*x)
   
         ;If Abs(dx1) <= radius And Abs(dx2) <= radius And Abs(dy1) <= radius And Abs(dy2) <= radius Then
         If -dy1 < pixelup(radius - dx1)   Then pixelup(radius - dx1)   = -dy1
         If -dy1 > pixeldown(radius - dx1) Then pixeldown(radius - dx1) = -dy1
         If +dy2 < pixelup(radius - dx2)   Then pixelup(radius - dx2)   = +dy2
         If +dy2 > pixeldown(radius - dx2) Then pixeldown(radius - dx2) = +dy2
         If -dx1 < pixelup(radius + dy1)   Then pixelup(radius + dy1)   = -dx1
         If -dx1 > pixeldown(radius + dy1) Then pixeldown(radius + dy1) = -dx1
         If +dx2 < pixelup(radius + dy2)   Then pixelup(radius + dy2)   = +dx2
         If +dx2 > pixeldown(radius + dy2) Then pixeldown(radius + dy2) = +dx2
         ;EndIf
      
         If P < 0 Then
            P = P + (X * b) + 6
         Else
            P = P + ((X - Y) * c) + 12
            Y = Y - 1
         EndIf
         X = X + 1
      Wend
      For n=1 To radius;füllt vom bresenham nicht gesetzte teile des arreys auf
         If pixelup(n)=0 Then pixelup(n)=pixelup(n-1)
         If pixelup(2*radius-n)=0 Then pixelup(2*radius-n)=pixelup(2*radius-n+1)
         If pixeldown(n)=0 Then pixeldown(n)=pixeldown(n-1)
         If pixeldown(2*radius-n)=0 Then pixeldown(2*radius-n)=pixeldown(2*radius-n+1)
      Next
 
      
      g=0
      If Abs(dx) < Abs(2*(sinalpha*radius)) Then;vermeidet das überstehen/"duchstechen" der lnien 
         g = Abs(2*sinalpha*radius) - Abs(dx)
      EndIf
      
      e = sinalpha*radius
      If m>0 Then;schreibt den durch geraden begrenzten teil in das arrey
         For n=-e  To e - g Step 1
            pixeldown(n+radius) = (n+radius-(radius-sinalpha*radius))*m + cosalpha*radius
         Next
      Else
         For n=-e To e - g Step 1
            pixeldown(-n+radius) = -((n+radius-(radius-sinalpha*radius))*m + cosalpha*radius)
         Next
         For n=-e To e + g Step -1
            pixelup(-n+radius) = -((n+radius-(radius-sinalpha*radius))*m + cosalpha*radius);????????
         Next
      EndIf


      If vertauscht=0;zeichnet je nach Vertauschung das arrey auf den bildschirm
         For n=0 To 2*radius Step 1
            Rect n+x1-radius, pixelup(n)+y1, 1, pixeldown(n)+y1 - (pixelup(n)+y1)
            Rect -n+x2+radius, -pixeldown(n)+y2, 1, Abs(-pixeldown(n)+y2 - (-pixelup(n)+y2))   
         Next
      Else
         For n=0 To 2*radius Step 1
            Rect pixelup(n)+y1, n+x1-radius, pixeldown(n)+y1 - (pixelup(n)+y1), 1
            Rect -pixeldown(n)+y2, -n+x2+radius, Abs(-pixeldown(n)+y2 - (-pixelup(n)+y2)), 1
         Next      
      EndIf
   
      If g=0 Then
         a = Sgn(dx)*Sgn(dy)
         b = (2*radius)/cosalpha
      
         X1 = X1 + sinalpha*radius*a
         X2 = X2 - sinalpha*radius*a
         If a=1 Then
            Y1 = Y1 - radius*cosalpha
            Y2 = Y2 - b + radius*cosalpha
         Else
            If dx<0 Then
               Y2 = Y2 + b - radius*cosalpha
               Y1 = Y1 + radius*cosalpha
            Else
               Y2 = Y2 - radius*cosalpha
               Y1 = Y1 - b + radius*cosalpha
            EndIf
         EndIf

         If vertauscht=1 Then
            dx = (X2 - X1)
            dy = (Y2 - Y1)
            b = Abs(b)
            m = dy/dx
      
            a=X1
            X1=Y1
            Y1=a
            a=X2
            X2=Y2   
            Y2=a
      
            For n=0 To b-1
               Line x1+n,y1,x2+n,y2
            Next
         Else
            dx = (X2 - X1)
            dy = (Y2 - Y1)
            b = Abs(b)
            m = dy/dx
      
            For n=0 To b-1
               Line x1,y1+n,x2,y2+n
            Next
         EndIf
      EndIf   
   EndIf
EndIf

End Function

diGGa

GruppenKaspar

BeitragDi, Apr 12, 2005 17:28
Antworten mit Zitat
Benutzer-Profile anzeigen
da entsteht son weisser kasten in der mitte wenn man die maus leicht nach rechts zieht.. is das beabsichtigt?
Gestern Nacht Schlug der Regen an mein Fenster
Ich ging durch das dunkle Zimmer und
glaubte im Licht der Straßenlampe
Den Geist unseres jahrhunderts auf der
Straße zu sehen
Der uns sagte, daß wir alle am Rande
des Abgrunds stehen.
- Al Steward


Athlon 64 3000+ / Radeon 9600 / 1024mb ddram
 

zimtstern#3

BeitragDi, Apr 12, 2005 17:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Oh.. das passiert wenn man der Abstand der beiden Punkte kleiner als der doppelte Radius ist... falls das der fall sein sollte muss man das weise rechteck halt noch füllen lassen
 

Hot-Bit

Sieger des B2D Retro Wettbewerb / Aug 04

BeitragDi, Apr 12, 2005 17:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Hoi.

Der schnellste vielleicht, den du gesehen hast Smile

Ich kenne schnellere, und dazu noch Bug-freie Smile

Da gehört noch einiges verbessert.

Fahr zB mal in eine Ecke mit der Maus.
Da werden etliche Pixel nicht gezeichnet .....

Außerdem ist das Prog doch recht groß ...


Toni
... ..... .i.. ...

***
Sieger des BB-Gameboy-Contest 2004
Sieger des Blitzbaster 2D-Minigolf-Contest 2005
***
 

zimtstern#3

BeitragDi, Apr 12, 2005 18:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Du kennst schnellere ...?
Welche denn?
Sowas ist verdammt schwierig zu finden. Ich dachte ich hätte alle ausprobiert.

Das die Pixel in der Ecke nicht gezeichnet werden ist richtig. Liegt aber an BB wieso das so ist hab ich noch nicht rausgefunden. aber alle Winkel funktionieren solange man den Rand nicht berührt. Irgendwas stimmt dann mit den Winkelfunktionen nichtmehr.

stfighter01

BeitragMi, Apr 13, 2005 0:35
Antworten mit Zitat
Benutzer-Profile anzeigen
bresenham, sinus- cosinus ? stirnrunzel
ich kenn nur den bresenham kreiszeichenalgo, und das schöne an ihm war das kein sin u. cos darin vorkam und deshalb war er so stark optimiert.
wies bei solcherart linen aussieht weiss ich nicht, aber auch hier sollte eine sinusfunktion überflüssig sein.

trotzdem ganz nett, aber ich würd das mit den pixelfehlern noch fixen.

mfg stfighter
Denken hilft!

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group