Seidel Algorithmus - Polygon in Dreiecke zerlegen

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

ComNik

Betreff: Seidel Algorithmus - Polygon in Dreiecke zerlegen

BeitragDo, Jul 23, 2009 14:12
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Rolling Eyes

Vorteile:
Arrow ziemlich schnell
Arrow Reihenfolge der Vertices ist sch*** egal... (uhrzeigersinn, anti uhrzeigersinn, quer durch..)

Nachteile:
Arrow Hab noch nicht lange getestet, bitte Feedback!

Ach ja und der code...
BlitzMax: [AUSKLAPPEN]

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
Rem
test:TFragment = New TFragment
test.v1 = New TVertex
test.v2 = New TVertex
test.v3 = New TVertex
test.v1.x = 10
test.v1.y = 10
test.v2.x = 10
test.v2.y = 20
test.v3.x = 20
test.v3.y = 20
DrawFragment(test)
End Rem

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

'Print(BIG+" "+min_dist)
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
WIP: Vorx.Engine

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group