Hier werden die Unterschiede zwischen zwei Versionen gezeigt.
Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
ws1920:update_02 [2020/02/09 19:55] Zetraeder angelegt |
ws1920:update_02 [2020/03/25 16:36] (aktuell) Zetraeder |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ---- | ||
+ | |||
====== Update 02 ====== | ====== Update 02 ====== | ||
- | **05.01.2020** | + | **05.02.2020** |
+ | |||
+ | [[ws1920:arbeitstermin_08|<<]] | [[ws1920:scutoids|Home]] | [[ws1920:cd_u02|Code]] | [[ws1920:arbeitstermin_09|>>]] | ||
[ Lukas ] | [ Lukas ] | ||
- | Delaunay - Triangulation 3D verbesser. LinalgError Singular Matrix durch Ausschluss von Determinante = 0 erledigt. Ich bin müde und habe keine Lust weiter zu erörtern deswegen lasse ich das jetzt. | + | Die Delaunay - Tetraedisierung wurde nun implementiert und funktioniert mehr oder weniger zuverlässig. Das Programm wählt nach dem Kugelkriterium die richtigen Tetraeder aus und fügt diese dem Viewport hinzu. |
- | + | ||
- | <code python> | + | |
- | + | ||
- | import bpy | + | |
- | from random import random, randint | + | |
- | from math import * | + | |
- | import numpy as np | + | |
- | + | ||
- | + | ||
- | + | ||
- | # KLASSEN | + | |
- | + | ||
- | class Sphere(object): | + | |
- | pos = np.array([0,0,0]) | + | |
- | radius = 0 | + | |
- | epsilon = 0.001 | + | |
- | + | ||
- | def __init__(self, pos, radius): | + | |
- | self.pos = pos | + | |
- | self.radius = radius | + | |
- | + | ||
- | def punktInKugel(self, p): | + | |
- | if (abstandPunkte(self.pos, p) < self.radius - self.epsilon): | + | |
- | print(abstandPunkte(self.pos, p), self.radius) | + | |
- | return True | + | |
- | else: | + | |
- | return False | + | |
- | + | ||
- | class Tetraeder(object): | + | |
- | verts = [] | + | |
- | faces = [] | + | |
- | sp = np.array([0,0,0]) | + | |
- | name = "tetraeder" | + | |
- | umkugel = Sphere(np.array([0,0,0]), 0) | + | |
- | + | ||
- | def __init__(self, verts, name): | + | |
- | self.name = name | + | |
- | self.verts = verts | + | |
- | self.faces = [(0,1,2),(1,2,3),(2,3,0),(3,0,1)] | + | |
- | if (self.schwerpunkt()[0] != None): | + | |
- | self.sp = self.schwerpunkt() | + | |
- | self.umkugel = Sphere(self.sp,abstandPunkte(self.sp,self.verts[0])) | + | |
- | else: | + | |
- | self.sp = np.array([None,None,None]) | + | |
- | + | ||
- | def schwerpunkt(self): | + | |
- | v1 = np.subtract(self.verts[1],self.verts[0]) | + | |
- | v2 = np.subtract(self.verts[2],self.verts[0]) | + | |
- | v3 = np.subtract(self.verts[3],self.verts[0]) | + | |
- | + | ||
- | sp = tetraSchwerpunkt(self.verts[0],v1,v2,v3) | + | |
- | return sp | + | |
- | + | ||
- | def selfRender(self, ker): | + | |
- | frei = True | + | |
- | for m in range(0, len(ker)): | + | |
- | if (self.umkugel.punktInKugel(ker[m]) == True): | + | |
- | frei = False | + | |
- | print("shit", ker[m]) | + | |
- | if (frei == True): | + | |
- | generateObj("Tetraeder", t.verts, t.faces, (0,0,0)) | + | |
- | #zeichnePunkt(t.sp, "Schwerpunkt") | + | |
- | + | ||
- | class Gerade(object): | + | |
- | ov = (0,0,0) | + | |
- | rv = (0,0,0) | + | |
- | + | ||
- | def __init__(self,ov,rv): | + | |
- | self.ov = ov | + | |
- | self.rv = rv | + | |
- | + | ||
- | def punktAn(self,k): | + | |
- | punkt = np.add(self.ov,(self.rv[0]*k,self.rv[1]*k,self.rv[2]*k)) | + | |
- | return punkt | + | |
- | + | ||
- | + | ||
- | + | ||
- | # FUNKTIONEN | + | |
- | + | ||
- | def schnittTest(g1,g2): | + | |
- | a = [[g2.rv[0],-g1.rv[0]],[g2.rv[1],-g1.rv[1]]] | + | |
- | b = [[g1.ov[0]-g2.ov[0]],[g1.ov[1]-g2.ov[1]]] | + | |
- | + | ||
- | print("Det :",np.linalg.det(a)) | + | |
- | if (np.linalg.det(a) != 0): | + | |
- | return np.linalg.solve(a,b)[0][0] | + | |
- | else: return None | + | |
- | + | ||
- | def schnittPunkt(g1,g2): | + | |
- | z = schnittTest(g1,g2) | + | |
- | if (z != None): | + | |
- | return g2.punktAn(z) | + | |
- | else: return np.array([None,None,None]) | + | |
- | + | ||
- | def dreieckSchwerpunkt(pos,a,b): | + | |
- | print("DreieckSchwerpunkt") | + | |
- | + | ||
- | g1 = Gerade(pos,a) | + | |
- | g2 = Gerade(pos,b) | + | |
- | + | ||
- | c = kreuzProdukt(a,b) | + | |
- | + | ||
- | d = kreuzProdukt(a,c) | + | |
- | e = kreuzProdukt(b,c) | + | |
- | + | ||
- | g3 = Gerade(g1.punktAn(.5), np.divide(d, 40)) | + | |
- | g4 = Gerade(g2.punktAn(.5), np.divide(e, 40)) | + | |
- | + | ||
- | schnitt = schnittPunkt(g3,g4) | + | |
- | #eichnePunkt(schnitt, "Dreieckschwerpunkt") | + | |
- | return schnitt | + | |
- | + | ||
- | def tetraSchwerpunkt(pos, v1, v2, v3): | + | |
- | print("tetraSchwerpunkt") | + | |
- | + | ||
- | sp1 = dreieckSchwerpunkt(pos, v1, v2) | + | |
- | sp2 = dreieckSchwerpunkt(pos, v1, v3) | + | |
- | + | ||
- | print(pos, v1, v2, v3, sp1, sp2) | + | |
- | + | ||
- | if (sp1[0] != None and sp2[0] != None): | + | |
- | g1 = Gerade(sp1, kreuzProdukt(v1, v2)) | + | |
- | g2 = Gerade(sp2, kreuzProdukt(v1, v3)) | + | |
- | + | ||
- | schnitt = schnittPunkt(g1, g2) | + | |
- | print("Tetraschwerpunkt :",schnitt) | + | |
- | return schnitt | + | |
- | else: return np.array([None,None,None]) | + | |
- | + | ||
- | def abstandPunkte(p1, p2): | + | |
- | a = sqrt(((p1[0]-p2[0])**2) + ((p1[1]-p2[1])**2) + ((p1[2]-p2[2])**2)) | + | |
- | return a | + | |
- | + | ||
- | def zeichnePunkt(pos, name = "Punkt"): | + | |
- | verts = [(0.1,0.1,0.1),(-0.1,0.1,0.1),(-0.1,-0.1,0.1),(0.1,-0.1,0.1) | + | |
- | ,(0.1,0.1,-0.1),(-0.1,0.1,-0.1),(-0.1,-0.1,-0.1),(0.1,-0.1,-0.1)] | + | |
- | faces = [(0,1,2,3),(4,5,6,7),(0,1,4,5),(1,2,4,5),(2,3,6,7),(3,0,7,4)] | + | |
- | generateObj(name,verts,faces,pos) | + | |
- | + | ||
- | def kreuzProdukt(a,b): | + | |
- | c = (a[1]*b[2]-a[2]*b[1] , a[2]*b[0]-a[0]*b[2] , a[0]*b[1]-a[1]*b[0]) | + | |
- | return c | + | |
- | + | ||
- | def genKerne(anzahl, x_max, y_max, z_max): | + | |
- | ker = [] | + | |
- | + | ||
- | for n in range(0, anzahl): | + | |
- | x = randint(-x_max, x_max)*((random()/(1+random()))) | + | |
- | y = randint(-y_max, y_max)*((random()/(1+random()))) | + | |
- | z = randint(-z_max, z_max)*((random()/(1+random()))) | + | |
- | if (len(ker) != 0): | + | |
- | neu = True | + | |
- | for m in range(0, len(ker)): | + | |
- | if (x == ker[m][0] and y == ker[m][1] and z == ker[m][2]): | + | |
- | neu = False | + | |
- | if (neu == True): | + | |
- | ker.append([x,y,z]) | + | |
- | zeichnePunkt(ker[n]) | + | |
- | else: | + | |
- | n = n-1 | + | |
- | else: | + | |
- | ker.append([x,y,z]) | + | |
- | zeichnePunkt(ker[n]) | + | |
- | return ker | + | |
- | + | ||
- | def generateObj(name, verts, faces, loc): | + | |
- | mymesh = bpy.data.meshes.new(name) | + | |
- | myobject = bpy.data.objects.new(name,mymesh) | + | |
- | + | ||
- | myobject.location = loc #(0,0,0) #bpy.context.scene.cursor.location | + | |
- | bpy.context.collection.objects.link(myobject) | + | |
- | + | ||
- | mymesh.from_pydata(verts,[],faces) | + | |
- | mymesh.update(calc_edges=True) | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | # CODE | + | |
- | x_max = 10 | + | {{:ws1920:solid.jpg?320|}} |
- | y_max = 10 | + | {{:ws1920:wireframe.jpg?320|}} |
- | z_max = 10 | + | |
- | ker = genKerne(20, x_max, y_max, z_max) | + | |
- | for i in range(0, len(ker)): | + | **Kugelkriterium** Es wird über eine zufällige Punktmenge iteriert und jede mögliche Kombination für vier verschiedene Kerne überprüft. Vier Punkte bestimmen (mathematisch bewiesen!) eine Kugel eindeutig, somit testen wir für alle Kombinationen (äquivalent zum zweidimensionalen Fall), ob sich weitere Kerne innerhalb der aufgespannten Kugel befinden. Ist dies der Fall, handelt es sich bei der zu überprüfenden Kombination NICHT um ein Tetraeder der Delaunay - Tetraedisierung (Begriff von uns eingeführt) - andernfalls handelt es sich um eines der gesuchten Volumina. |
- | for j in range(i+1, len(ker)): | + | |
- | for k in range(j+1, len(ker)): | + | |
- | for l in range(k+1, len(ker)): | + | |
- | print(str(i),str(j),str(k),str(l)) | + | |
- | + | ||
- | t = Tetraeder([ker[i], ker[j], ker[k], ker[l]],"Tetraeder") | + | |
- | t.selfRender(ker) | + | |
- | </code> | + | Außerdem wurde der lästige Fehler "LinalgError Singular Matrix" durch Ausschluss der Determinante = 0 ausgemerzt. |
---- | ---- | ||