Hallo liebe Community,
da ich grade an etwas arbeite wo ich diesen algorithmus benötige, hab ich ihn basierend auf ein bisschen wikipedia und gamedev etc... geschrieben. War ein ziemliches gehacke aber er funktioniert. Ich werde morgen eine etwas schönere, kommentierte fassung hochladen, ich wollt ihne jetz einfach loswerden
Vorteile:
ziemlich schnell
Reihenfolge der Vertices ist sch*** egal... (uhrzeigersinn, anti uhrzeigersinn, quer durch..)
Nachteile:
Hab noch nicht lange getestet, bitte Feedback!
Ach ja und der code...
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] Type TVertex Field x:Float Field y:Float End Type
Type TPoly Field fragments:TList Field vertices:TList Field orientation:Int End Type
Type TFragment Field v1:TVertex Field v2:TVertex Field v3:TVertex End Type
Global polygons:TList = CreateList()
Const CLOCKWISE:Int = 0 Const COUNTER_CLOCKWISE:Int = 1 Global BIG:Float = 1.0e30
poly:TPoly = New TPoly poly.vertices = CreateList() poly.fragments = CreateList() ListAddLast(polygons,poly)
Graphics(800, 600, 0, 60)
While Not KeyDown(KEY_ESCAPE) Or AppTerminate() Cls SetColor(255,0,0) If MouseHit(1) vertex:TVertex = New TVertex vertex.x = MouseX() vertex.y = MouseY() ListAddLast(poly.vertices, vertex) End If Local vv:TVertex For vv = EachIn poly.vertices DrawRect(vv.x, vv.y, 3, 3) Next
If KeyHit(KEY_SPACE) Local vertices:TVertex[CountList(poly.vertices)] Local v:TVertex Local i:Int=0 For v = EachIn poly.vertices vertices[i] = v i:+ 1 Next poly.orientation = orientation(Len(vertices), vertices) draw = True End If If draw = True Then draw_poly(Len(vertices),vertices)
Flip Wend
Function orientation(n:Float, vertices:TVertex[]) Local area:Float Local i:Int area = vertices[n-1].x * vertices[0].y - vertices[0].x * vertices[n-1].y For i=0 To n-2 area:+ vertices[i].x * vertices[i+1].y - vertices[i+1].x * vertices[i].y Next
If area >= 0.0 Return COUNTER_CLOCKWISE Else Return CLOCKWISE End If End Function
Function determinant(p1:Int, p2:Int, p3:Int, vertices:TVertex[]) Local x1:Float, x2:Float, x3:Float Local y1:Float, y2:Float, y3:Float Local determ:Float
x1 = vertices[p1].x x2 = vertices[p2].x x3 = vertices[p3].x y1 = vertices[p1].y y2 = vertices[p2].y y3 = vertices[p3].y
determ = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)
If determ >= 0.0 Return COUNTER_CLOCKWISE Else Return CLOCKWISE End If End Function
Function distance2:Float(x1:Float, y1:Float, x2:Float, y2:Float) Local xd:Float = x1 - x2 Local yd:Float = y1 - y2
Return xd*xd + yd*yd End Function
Function no_interior(p1:Int, p2:Int, p3:Int, vertices:TVertex[], vp:Int[], orient:Int, n:Int) Local i:Int Local p:Int
For i=0 To n-1 p = vp[i] If p = p1 Or p = p2 Or p = p3 Then Continue If determinant(p2, p1, p, vertices) = orient Or determinant(p1, p3, p, vertices) = orient Or determinant(p3, p2, p, vertices) = orient Continue Else Return 0 End If Next Return 1 End Function
Function draw_poly(n:Int, v:TVertex[]) Local prev:Int, cur:Int, nex:Int Local vp:Int[100] Local count:Int Local min_vert:Int Local i:Int Local dist:Float Local min_dist:Float Local poly_orient:Int Local t:TFragment
If n > 100 Then Notify("Too many vertices!"); End poly_orient = orientation(n, v) For i=0 To n-1 vp[i] = i Next
count = n While count > 3 min_dist = BIG min_vert = 0 For cur=0 To count - 1 prev = cur - 1 nex = cur + 1
If cur = 0 prev = count - 1 ElseIf cur = count - 1 nex = 0 End If
dist = distance2(v[vp[prev]].x, v[vp[prev]].y, v[vp[nex]].x, v[vp[nex]].y) If determinant(vp[prev], vp[cur], vp[nex], v) = poly_orient And no_interior(vp[prev], vp[cur], vp[nex], v, vp, count, poly_orient) And dist < min_dist min_dist = dist min_vert = cur End If Next If min_dist = BIG Then Notify("No triangles found -.-'!"); End
prev = min_vert - 1 nex = min_vert + 1 If min_vert = 0 prev = count - 1 Else If min_vert = count - 1 nex = 0 End If
Local frag:TFragment = New TFragment frag.v1 = New TVertex frag.v2 = New TVertex frag.v3 = New TVertex frag.v1.x = v[vp[prev]].x frag.v1.y = v[vp[prev]].y frag.v2.x = v[vp[min_vert]].x frag.v2.y = v[vp[min_vert]].y
frag.v3.x = v[vp[nex]].x frag.v3.y = v[vp[nex]].y
DrawFragment(frag)
count:- 1 For i=min_vert To count - 1 vp[i] = vp[i+1] Next Wend
final_frag:TFragment = New TFragment final_frag.v1 = New TVertex final_frag.v1.x = v[vp[0]].x final_frag.v1.y = v[vp[0]].y final_frag.v2 = New TVertex final_frag.v2.x = v[vp[1]].x final_frag.v2.y = v[vp[1]].y final_frag.v3 = New TVertex final_frag.v3.x = v[vp[2]].x final_frag.v3.y = v[vp[2]].y DrawFragment(final_frag) End Function Function DrawFragment(frag:TFragment) DrawLine(frag.v1.x,frag.v1.y, frag.v2.x, frag.v2.y) DrawLine(frag.v1.x,frag.v1.y, frag.v3.x, frag.v3.y) DrawLine(frag.v2.x, frag.v2.y, frag.v3.x, frag.v3.y) End Function
Ich weiss wie schrecklich der code ist, wie gesagt morgen...
lg
ComNik
|