Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

ws1920:tag_02_code

Zweiter Tag: Aktueller Code

19.03.2020

<< | Home | Text | >>

[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])
ws1920/tag_02_code.txt · Zuletzt geändert: 2020/03/19 17:41 von Zetraeder