Artemis.Bezier : Bézierkurven n-ter Ordnung + kubische

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

Artemis

Betreff: Artemis.Bezier : Bézierkurven n-ter Ordnung + kubische

BeitragSa, Nov 25, 2006 18:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Da ich für mein Projekt Bézierkurven brauche, habe ich mir ein kleines Modul geschrieben, um kubische Bézierkurven (n=3) und allgemeine Bézierkurven n-ter Ordnung zu berechnen.

Edit [28.11, 21:00]

So, habe das Modul umstrukturiert, umbenannt in Artemis.Bezier und Bézierpatches hinzugefügt.

Der ganze Quell-Code: [AUSKLAPPEN]
SuperStrict

Rem
bbdoc: Bézier
about:
Enhält Berechnungen für Bézierkurven und Bézierpatches.
EndRem
Module Artemis.Bezier

ModuleInfo "Version: 1.0"
ModuleInfo "Author: Artemis"
ModuleInfo "License: Public Domain"
ModuleInfo "Modserver: BlitzHelp"
ModuleInfo ":"
ModuleInfo "History: 1.00 erste Version"

Import Artemis.Point
Import Artemis.Math
Import Brl.LinkedList

Rem
bbdoc: Enthält Funktionen zur Berechnung einer dreidimensionalen, kubischen Bézierkurve.
EndRem
Type TBezier
   
   Rem
   bbdoc: Gibt eine Koordinate aufgrund vier gegebener Koordinaten und der Stelle t zurück.
   EndRem
   Function get:Float(p0:Float, p1:Float, p2:Float, p3:Float, t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Return p0*(1-t)^3 + 3*p1*t*(1-t)^2 + 3*p2*t^2*(1-t) + p3*t^3
   EndFunction

   Rem
   bbdoc: Gibt die X-Koordinate aufgrund vier gegebener Punkte und der Stelle t zurück.
   EndRem
   Function getX:Float(p0:TPoint, p1:TPoint, p2:TPoint, p3:TPoint, t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Return p0.x*(1-t)^3 + 3*p1.x*t*(1-t)^2 + 3*p2.x*t^2*(1-t) + p3.x*t^3
   EndFunction
   
   Rem
   bbdoc: Gibt die Y-Koordinate aufgrund vier gegebener Punkte und der Stelle t zurück.
   EndRem
   Function getY:Float(p0:TPoint, p1:TPoint, p2:TPoint, p3:TPoint, t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Return p0.y*(1-t)^3 + 3*p1.y*t*(1-t)^2 + 3*p2.y*t^2*(1-t) + p3.y*t^3
   EndFunction
   
   Rem
   bbdoc: Gibt die Z-Koordinate aufgrund vier gegebener Punkte und der Stelle t zurück.
   EndRem
   Function getZ:Float(p0:TPoint, p1:TPoint, p2:TPoint, p3:TPoint, t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Return p0.z*(1-t)^3 + 3*p1.z*t*(1-t)^2 + 3*p2.z*t^2*(1-t) + p3.z*t^3
   EndFunction
   
   Rem
   bbdoc: Gibt den Punkt aufgrund vier gegebener Punkte und der Stelle t zurück.
   EndRem
   Function getPoint:TPoint(p0:TPoint, p1:TPoint, p2:TPoint, p3:TPoint, t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Local x:Float
      Local y:Float
      Local z:Float
      
      x = p0.x*(1-t)^3 + 3*p1.x*t*(1-t)^2 + 3*p2.x*t^2*(1-t) + p3.x*t^3
      y = p0.y*(1-t)^3 + 3*p1.y*t*(1-t)^2 + 3*p2.y*t^2*(1-t) + p3.y*t^3
      z = p0.z*(1-t)^3 + 3*p1.z*t*(1-t)^2 + 3*p2.z*t^2*(1-t) + p3.z*t^3
      
      Return TPoint.Create(x, y, z)
   EndFunction
   
EndType

Rem
bbdoc: Enthält Funktionen zur Berechnung einer dreidimensionalen, Bézierkurve n-ter Ordnung.
EndRem
Type TBezierN
   
   Rem
   bbdoc: Gibt eine Koordinate aufgrund beliebiger gegebener Koordinaten und der Stelle t zurück.
   EndRem
   Function get:Float(points:Float[], t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Local n:Int = points.length-1
      Local i:Int = 0

      Local p:Float
      Local r:Float = 0
      
      For p = EachIn points
         r :+ p * TMath.BernsteinPolynomial(i, n, t)
         i :+ 1
      Next
      
      Return r
   EndFunction
   
   Rem
   bbdoc: Gibt die X-Koordinate aufgrund beliebiger gegebener Punkte und der Stelle t zurück.
   EndRem
   Function getX:Float(points:TPoint[], t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Local n:Int = points.length-1
      Local i:Int = 0
      Local p:TPoint
      Local x:Float = 0
      
      For p = EachIn points
         x :+ p.x * TMath.BernsteinPolynomial(i, n, t)
         i :+ 1
      Next
      
      Return x
   EndFunction
   
   Rem
   bbdoc: Gibt die Y-Koordinate aufgrund beliebiger gegebener Punkte und der Stelle t zurück.
   EndRem
   Function getY:Float(points:TPoint[], t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Local n:Int = points.length-1
      Local i:Int = 0
      Local p:TPoint
      Local y:Float = 0
      
      For p = EachIn points
         y :+ p.y * TMath.BernsteinPolynomial(i, n, t)
         i :+ 1
      Next
      
      Return y
   EndFunction
   
   Rem
   bbdoc: Gibt die Z-Koordinate aufgrund beliebiger gegebener Punkte und der Stelle t zurück.
   EndRem
   Function getZ:Float(points:TPoint[], t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Local n:Int = points.length-1
      Local i:Int = 0
      Local p:TPoint
      Local z:Float = 0
      
      For p = EachIn points
         z :+ p.z * TMath.BernsteinPolynomial(i, n, t)
         i :+ 1
      Next
      
      Return z
   EndFunction
   
   Rem
   bbdoc: Gibt den Punkt aufgrund beliebiger gegebener Punkte und der Stelle t zurück.
   EndRem
   Function getPoint:TPoint(points:TPoint[], t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Local n:Int = points.length-1
      Local i:Int = 0
      Local p:TPoint
      Local x:Float = 0
      Local y:Float = 0
      Local z:Float = 0
      
      For p = EachIn points
         x :+ p.x * TMath.BernsteinPolynomial(i, n, t)
         y :+ p.y * TMath.BernsteinPolynomial(i, n, t)
         z :+ p.z * TMath.BernsteinPolynomial(i, n, t)
         i :+ 1
      Next
      
      Return TPoint.Create(x, y, z)
   EndFunction
   
EndType

Rem
bbdoc: Definiert eine kubische Bézierkurve.
EndRem
Type TBezierCurve
   
   Field p0:TPoint
   Field p1:TPoint
   Field p2:TPoint
   Field p3:TPoint
   
   Rem
   bbdoc: Gibt die X-Koordinate zurück.
   EndRem
   Method getX:Float(t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Return TBezier.getX(self.p0, self.p1, self.p2, self.p3, t)
   EndMethod
   
   Rem
   bbdoc: Gibt die Y-Koordinate zurück.
   EndRem
   Method getY:Float(t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Return TBezier.getY(self.p0, self.p1, self.p2, self.p3, t)
   EndMethod
   
   Rem
   bbdoc: Gibt die Z-Koordinate zurück.
   EndRem
   Method getZ:Float(t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Return TBezier.getZ(self.p0, self.p1, self.p2, self.p3, t)
   EndMethod
   
   Rem
   bbdoc: Gibt den Punkt zurück.
   EndRem
   Method getPoint:TPoint(t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Return TBezier.getPoint(self.p0, self.p1, self.p2, self.p3, t)
   EndMethod
   
EndType

Rem
bbdoc: Definiert eine Bézierkurve n-ter Ordnung.
EndRem
Type TBezierCurveN
   
   Field points:TList = New TList
   
   Rem
   bbdoc: Fügt einen Punkt an das Ende der Kurve an
   EndRem
   Method add(x:Float, y:Float, z:Float=0)
      self.points.addLast(TPoint.Create(x, y, z))
   EndMethod
   
   Rem
   bbdoc: Fügt einen Punkt an das Ende der Kurve an
   EndRem
   Method addPoint(p:TPoint)
      self.points.addLast(p)
   EndMethod
   
   Rem
   bbdoc: Gibt die X-Koordinate zurück.
   EndRem
   Method getX:Float(t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Return TBezierN.getX(TPoint[](self.points.toArray()), t)
   EndMethod
   
   Rem
   bbdoc: Gibt die Y-Koordinate zurück.
   EndRem
   Method getY:Float(t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Return TBezierN.getY(TPoint[](self.points.toArray()), t)
   EndMethod
   
   Rem
   bbdoc: Gibt die Z-Koordinate zurück.
   EndRem
   Method getZ:Float(t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Return TBezierN.getZ(TPoint[](self.points.toArray()), t)
   EndMethod
   
   Rem
   bbdoc: Gibt den Punkt zurück.
   EndRem
   Method getPoint:TPoint(t:Float)
      If (t < 0) Or (t > 1) Then Return Null
      
      Return TBezierN.getPoint(TPoint[](self.points.toArray()), t)
   EndMethod
   
EndType

Rem
bbdoc: Definiert einen Bézierpatch mit beliebig vielen Punkten.
EndRem
Type TBezierPatch
   
   Field size_u:Int
   Field size_v:Int
   Field points:TPoint[][]
   
   Rem
   bbdoc: Erstellt einen neuen Bézierpatch mit der Anzahl der Punkte für die u-Béziers (size_u) und für die v-Béziers (size_v).
   EndRem
   Function Create:TBezierPatch(size_u:Int, size_v:Int)
      If (size_u < 2) Or (size_v < 2) Then Return Null
      
      Local bezier_patch:TBezierPatch = New TBezierPatch
      Local loop:Int
      
      bezier_patch.size_u = size_u
      bezier_patch.size_v = size_v
      bezier_patch.points = New TPoint[][size_v]
      For loop = 0 To size_v-1
         bezier_patch.points[loop] = New TPoint[size_u]
      Next
      
      Return bezier_patch
   EndFunction
   
   Rem
   bbdoc: Gibt den Punkt des Patchs aufgrund der Beiden Kurvenpositionen u und v an.
   EndRem
   Method getPoint:TPoint(u:Float, v:Float)
      If (u < 0) Or (u > 1) Then Return Null
      If (v < 0) Or (v > 1) Then Return Null
      
      Local bezier:TPoint[] = New TPoint[size_v]
      Local loop  :Int
      
      For loop = 0 To self.size_v-1
         bezier[loop] = TBezierN.getPoint(self.points[loop], u)
      Next
      
      Return TBezierN.getPoint(bezier, v)

   EndMethod
   
EndType

Und das TPoint-Modul:
Code: [AUSKLAPPEN]
SuperStrict

Rem
bbdoc: Point
about:
Dieses Modul beinhaltet eine einfache Klasse, die einen Punkt definiert.
EndRem
Module Artemis.Point

ModuleInfo "Version: 1.02"
ModuleInfo "Author: Artemis"
ModuleInfo "License: Public Domain"
ModuleInfo "Modserver: BlitzHelp"
ModuleInfo ":"
ModuleInfo "History: 1.02"
ModuleInfo "History: Changed: Removed all classes but TPoint which contains now a 3d float point."
ModuleInfo "History: 1.01"
ModuleInfo "History: Added: T3DPoint and T3DFloatPoint."
ModuleInfo "History: 1.00 first Release"

Rem
bbdoc: Diese Klasse definiert einen Punkt.
EndRem
Type TPoint
   
   Rem
   bbdoc: Diese Variable enthält die X-Koordinate des Punktes.
   EndRem
   Field x:Float
   
   Rem
   bbdoc: Diese Variable enthält die Y-Koordinate des Punktes.
   EndRem
   Field y:Float
   
   Rem
   bbdoc: Diese Variable enthält die Z-Koordinate des Punktes.
   EndRem
   Field z:Float
   
   Rem
   bbdoc: Diese Funktion erstellt einen neuen Punkt mit den übergebenen Koordinaten.
   EndRem
   Function Create:TPoint(x:Float, y:Float, z:Float=0)
      Local point:TPoint = New TPoint
      
      point.x = x
      point.y = y
      point.z = z
      
      Return point
   EndFunction
   
   Method toString:String()
      Local x:String = self.x
      Local y:String = self.y
      Local z:String = self.z
      
      While x[x.length-1..] = "0"
         x = x[..x.length-1]
      Wend
      If x[x.length-1..] = "." Then x = x[..x.length-1]
      While y[y.length-1..] = "0"
         y = y[..y.length-1]
      Wend
      If y[y.length-1..] = "." Then y = y[..y.length-1]
      While z[z.length-1..] = "0"
         z = z[..z.length-1]
      Wend
      If z[z.length-1..] = "." Then z = z[..z.length-1]
      
      Return "TPoint(" + x + ", " + y + ", " + z + ")"
   EndMethod
   
EndType
  • Zuletzt bearbeitet von Artemis am So, Aug 31, 2008 17:21, insgesamt 2-mal bearbeitet

Vertex

BeitragSa, Nov 25, 2006 19:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Ist ja ganz schön, aber warum muss man für jeden "Kleinmist" denn bitteschön ein Modul machen? Vorschlag zur Erweiterung: Bézier-Patches - Man gibt 8 x 3D Punkte an, und er berechnet daraus eine Oberfläche. Ist auch relativ einfach umzusetzen. Bei GetPoint brauchste dann die 2 Parameter U und V, die auch im Interval [0, 1] liegen.

mfg olli
vertex.dreamfall.at | GitHub

Artemis

BeitragMo, Nov 27, 2006 20:14
Antworten mit Zitat
Benutzer-Profile anzeigen
Jo, Bézier-Patches kommen. Bin gerade dabei, das Modul umzustrukturieren und zu vereinfachen.

Aber 8-Punkte?
Sind das nicht 16-Punkte, so wie hier:
user posted image user posted image
?

Mit 16 Punkten klingt das für mich ganz logisch, aber mit 8 Punkten?

Vertex

BeitragMo, Nov 27, 2006 22:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja, 16, sorry Smile
vertex.dreamfall.at | GitHub

Artemis

BeitragDi, Nov 28, 2006 22:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Ok, Bézierpatches sind da. Sie sind außerdem nicht auf 4*4 beschränkt, sondern sind variabel.

Außerdem habe ich das Modul umstrukturiert und vereinfacht und vor allem das Modul Artemis.Point verinfacht.

Habe eine Bézierpatch vorhin getestet und es klappte alles.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group