----- ====== Zweiter Tag: Aktueller Code ====== **19.03.2020** [[ws1920:tag_01_code|<<]] | [[ws1920:scutoids|Home]] | [[ws1920:tag_02|Text]] | [[ws1920:tag_03_code|>>]] {{ :ws1920:final_day02.jpg?550|}} **[17:37]** Wie im Bild zu sehen ist es nun möglich, komplette Zellen als einzelnes Objekt anzuwählen. Die Zellwände liegen nun nicht mehr als unkontrollierbarer Haufen frei im Raum, sondern sind fest verankert mit den gehörigen Zellobjekten. Dieser text dient nicht als Lückenfüller damit das Bild nicht so bescheuert im Leeren steht. ---- import bpy from random import random, randint from math import * import numpy as np import time from bpy_extras.mesh_utils import ngon_tessellate # 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): 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, col, tetra): frei = True for m in range(0, len(ker)): if (self.umkugel.punktInKugel(ker[m]) == True): frei = False if (frei == True): generateObj("Tetraeder", t.verts, t.faces, (0,0,0), col) tetra.append(self) class Gerade(object): ov = (0,0,0) rv = (0,0,0) kreuzt = False kerne = [0,0] def __init__(self,ov,rv,kerne = [0,0]): self.ov = ov self.rv = rv self.kerne = kerne 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]]] c = [[g2.rv[2],-g1.rv[2]],[g2.rv[1],-g1.rv[1]]] d = [[g1.ov[2]-g2.ov[2]],[g1.ov[1]-g2.ov[1]]] e = [[g2.rv[2],-g1.rv[2]],[g2.rv[0],-g1.rv[0]]] f = [[g1.ov[2]-g2.ov[2]],[g1.ov[0]-g2.ov[0]]] #print("Det :",np.linalg.det(a)) if (np.linalg.det(a) != 0): return np.linalg.solve(a,b)[0][0] elif (np.linalg.det(c) != 0): #print(">> ERGEBNIS") return np.linalg.solve(c,d)[0][0] elif (np.linalg.det(e) != 0): #print(">> SINBEGRE") return np.linalg.solve(e,f)[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): 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) 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,5,4),(1,2,6,5),(2,3,7,6),(3,0,4,7)] 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 # AB HIER ERSTELLUNG DER ZELLWÄNDE def radianBetweenVectors(v1, v2, n): # berechnet den Zwischenwinkel zweier Vektoren unter Beachtung eines Normalenwinkels # (später wird für n die Flächennormale der Zellwand eingesetzt, welche die Verbindung der # beiden Knotenpunkte ist, zwischen denen sich die Zellwand befindet). a = v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2] b = v1[0]*v2[1]*n[2] + v2[0]*n[1]*v1[2] + n[0]*v1[1]*v2[2] - v1[2]*v2[1]*n[0] - v2[2]*n[1]*v1[0] - n[2]*v1[1]*v2[0] rad = np.arctan2(b, a) if (rad < 0): rad = (2*np.pi) +rad deg = rad*180/np.pi #print(">> v02", rad, deg, "\n") return deg def polySortList(v_list, normal): # soll eine Liste von Punkten im Kreis herum links herum anordnen # falls es ein Dreieck ist, ist die Reihenfolge egal if (len(v_list) == 3): return v_list # Startvariablen werden gesetzt geordnet = [] start = v_list[0] aktu = start vv = np.subtract(v_list[0], v_list[1]) # Vergleichswinkel, der zufällig gewählt wird (zeigt immer aus dem Kreis raus) geordnet.append(start) while True: #print(">>", aktu) # loop start values min_angle = 360 min_stelle = 0 # suche nach nächstem Punkt for v in range(0, len(v_list)): if (aktu[0] != v_list[v][0] or aktu[1] != v_list[v][1] or aktu[2] != v_list[v][2]): dir = np.subtract(v_list[v], aktu) deg = radianBetweenVectors(vv, dir, normal) #np.array([0,0,1])) if (deg < min_angle): min_angle = deg min_stelle = v geordnet.append(v_list[min_stelle]) vv = np.subtract(v_list[min_stelle], aktu) aktu = v_list[min_stelle] #print(" >", aktu) if (aktu[0] == start[0] and aktu[1] == start[1] and aktu[2] == start[2]): break return geordnet def genPoly(liste, normal): # sortiert die gegebene Vertecie- Liste im Kreis herum und erstellt dann daraus eine saubere Fläche. geordnet = polySortList(liste, normal) f = [] for i in range(0, len(geordnet)): f.append(i) facelist = [] facelist.append(f) generateObj("Zellwand", geordnet, facelist) def generateObj(name, verts, faces, loc = np.array([0,0,0]), col = ( 1.0, 1.0, 1.0, 1.0 )): # generiert ein Objekt mit den Übergebenen Parametern (Name, Eckpunkte, Seiten) mymesh = bpy.data.meshes.new(name) myobject = bpy.data.objects.new(name,mymesh) mymat = bpy.data.materials.new("Mesh_mat") mymat.diffuse_color = col mymesh.materials.append(mymat) myobject.location = loc bpy.context.collection.objects.link(myobject) mymesh.from_pydata(verts,[],faces) mymesh.update(calc_edges=True) # ZUORDNUNG DER WÄNDE ZU KOLLEKTIONEN def createCollection(name): col = bpy.data.collections.new(name) bpy.context.scene.collection.children.link(col) return col def linkToCollection(obj, col): col.objects.link(obj) def inListeAnStelle(element, liste): # durchsucht eine Liste nach einem Vector und gibt die Stelle aus, falls es enthalten ist if element in liste: for i in range(0, len(liste)): if (element == liste[i]): return i return None def inListeAnStelleNP(element, liste): # durchsucht eine Liste von np.arrays nach einem np.array und gibt die Stelle aus, # falls dieser enthalten ist for i in range(0, len(liste)): if (np.array_equal(element, liste[i])): return i return None # CODE col = createCollection('Delaunay') col = createCollection('Voronoi') x_max = 100 y_max = 100 z_max = 100 anzahlKerne = 25 del_col = (1.0, 0.0, 0.0, 1) tetra = [] ker = genKerne(anzahlKerne, x_max, y_max, z_max) #ker = [[0.5993280181021913, -0.4902980267777478, -0.49501317000167505], [-0.5435355585699094, -0.5797131146501373, 5.358814201657665], [0.3314129669573313, 0.06170948842793362, -0.7049448015853017], [3.1586485852091704, -3.5930246037937623, 0.4050221351432125], [2.3720126622528435, -0.1444049711022323, -0.8239078280684086], [2.737558129947007, 3.263776842262023, -4.292689464037283], [-2.3210411603088885, -3.869616290303755, 0.9243976566069152], [0.2993804076152454, -0.5199510038865012, 0.28987243247419864], [8.201747317589948, 0.6535831987234019, 3.6830815010667664], [-0.42647813347859526, -1.5289270142358882, -0.08034527427391898], [3.9377606048318166, -4.865271969576239, 1.2243584468694046], [0.806041393229286, 0.0, 0.07921029485036851], [0.6137190460585324, 1.535243528493868, -1.600612893884901], [1.1540597542694828, 3.1304758799406356, 2.411227237265708], [1.5083371322537722, 0.059994185768576916, -1.96459150755497], [0.00978110076824692, 0.5153349359712261, 7.447412675253049], [-2.162426719288622, -0.18758603781988797, 1.874187393501292], [-1.2861520576937593, 2.255844853091784, -1.9755975108667347], [4.448892338753108, -2.247797498228902, -2.316136846836149], [0.0, 0.0, 0.2953965724182989]] print("\n\n",ker,"\n\n") for i in range(0, len(ker)): for j in range(i+1, len(ker)): for k in range(j+1, len(ker)): for l in range(k+1, len(ker)): t = Tetraeder([ker[i], ker[j], ker[k], ker[l]],"Tetraeder") t.selfRender(ker, del_col, tetra) print(tetra, len(tetra)) count = 0 vertex = [[] for dummy in range(anzahlKerne)] # liste alle vertecies, index markiert die Zellnummer, zu der sie gehören faces = [[] for dummy in range(anzahlKerne)] # liste alle faces, index markiert die Zellnummer, zu der sie gehören for u in range(0, len(ker)): for v in range(u+1, len(ker)): z_verts = [] count = 0 for w in range(0, len(tetra)): if ((ker[u] in tetra[w].verts) and (ker[v] in tetra[w].verts)): z_verts.append(tetra[w].sp) if (len(z_verts) > 2): normal = np.subtract(ker[u], ker[v]) geordnet = polySortList(z_verts, normal) temp_face1 = [] temp_face2 = [] for i in range(0, len(geordnet)): if (inListeAnStelleNP(geordnet[i], vertex[u]) != None): temp_face1.append(inListeAnStelleNP(geordnet[i], vertex[u])) else: vertex[u].append(geordnet[i]) temp_face1.append(inListeAnStelleNP(geordnet[i], vertex[u])) if (inListeAnStelleNP(geordnet[i], vertex[v]) != None): temp_face2.append(inListeAnStelleNP(geordnet[i], vertex[v])) else: vertex[v].append(geordnet[i]) temp_face2.append(inListeAnStelleNP(geordnet[i], vertex[v])) faces[u].append(temp_face1) faces[v].append(temp_face2) for i in range(0, anzahlKerne): generateObj("Zelle", vertex[i], faces[i])