如何使用 3D 点、线和面数据绘制体积(.geo 文件)

How to plot volumes with 3D points, lines and surfaces data (.geo file)

我需要绘制用其表面定义的 3D 体积, 用线环定义的表面, 用线定义的线循环, 用点定义的线。

这是一个例子:

Point(1) = x1,y1,z1
Point(2) = x2,y2,z2
Point(3) = x3,y3,z3
Point(4) = x4,y4,z4
Point(5) = x5,y5,z5
Point(6) = x6,y6,z6
Point(7) = x7,y7,z7
Point(8) = x8,y8,z8
Line(1) = Point(1), Point(2)
Line(2) = Point(2), Point(3)
Line(3) = Point(3), Point(4)
Line(4) = Point(4), Point(1)
Line(5) = Point(5), Point(6)
Line(6) = Point(6), Point(7)
Line(7) = Point(7), Point(8)
Line(8) = Point(8), Point(5)
Line(9) = Point(1), Point(5)
Line(10) = Point(2), Point(6)
Line(11) = Point(3), Point(7)
Line(12) = Point(4), Point(8)
Line loop(1) = Line(1), Line(2), Line(3), Line(4)
Line loop(2) = Line(5), Line(6), Line(7), Line(8)
Line loop(3) = Line(1), Line(10), Line(-5), Line(-9)
Line loop(4) = Line(2), Line(11), Line(-6), Line(-10)
Line loop(5) = Line(3), Line(12), Line(-7), Line(-11)
Line loop(6) = Line(4), Line(9), Line(-8), Line(-12)
Surface(1) = Line Loop(1) #top
Surface(2) = Line Loop(2) #bottom
Surface(3) = Line Loop(3)
Surface(4) = Line Loop(4)
Surface(5) = Line Loop(5)
Surface(6) = Line Loop(6)
Volume(1) = Surface(1), Surface(2), Surface(3), Surface(4), Surface(5), Surface(6)

https://i.imgur.com/XRqdgXY.png

我尝试了 matplotlib 和 mayavi.mlab 绘图函数,但 none 的效果如我所愿。 我也找了一个 .geo 导入函数,但没有找到。

这些文件(.geo 文件)是从 SketchUp(Google 3D 设计软件)导出并导入到 GMesh 中以创建网格。 在我的例子中,我想在将它导入 Gmesh 之前在 Python 中绘制我的体积。

有人会想到绘制这种数据吗?

经过几天的工作,我得到了答案,用于显示 .geo 文件中的边缘:

from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
import matplotlib.pyplot as plt
import os
from os import system
from numpy import array, argsort, sqrt, unique, linspace
fig = plt.figure ()
ax = fig.add_subplot (1, 1, 1, projection = '3d', aspect = 1)

## Name of GEO file
fileName = "vfv8_fusion.geo"

## Reading GEO file
with open(fileName) as f:
  lineList = f.readlines()

V,P,L,LL,PS,SL = [],[],[],[],[],[]
e1,f1 = [],[]

## Separation of variables (points, lines, loop lines, plane surface, surface loop, volumes)
for ii in range(len(lineList)):

    if lineList[ii][0:5]=="Point":  
        a1 = lineList[ii]
        a2 = a1.split('{')
        a3 = a2[1].split('}')
        a4 = a3[0].split(',')
        coord = [float(a4[0]),float(a4[1]),float(a4[2])]
        P.append(coord)

    if lineList[ii][0:5]=="Line(":
        b1 = lineList[ii]
        b2 = b1.split('{ ')
        b3 = b2[1].split(' }')
        b4 = b3[0].split(',')
        points_to_line = [int(float(b4[0])),int(float(b4[1]))]
        L.append(points_to_line)      

    if lineList[ii][0:9]=="Line Loop": 
        c1 = lineList[ii]
        c2 = c1.split('{')
        c3 = c2[1].split('}')
        c4 = c3[0].split(',')
        line_to_lineloop = []
        for jj in range(len(c4)):
            line_to_lineloop.append(int(float(c4[jj])))
        LL.append(line_to_lineloop)      

    if lineList[ii][0:13]=="Plane Surface":
        d1 = lineList[ii]
        d2 = d1.split('{')
        d3 = d2[1].split('}')
        d4 = d3[0].split(',')
        lineloop_to_planesurface = []
        for jj in range(len(d4)):
            lineloop_to_planesurface.append(int(float(d4[jj])))
        PS.append(lineloop_to_planesurface)   

    if lineList[ii][0:12]=="Surface Loop":
        e1.append(lineList[ii])
        e2 = e1[-1].split('{')
        e3 = e2[1].split('}')
        e4 = e3[0].split(',')
        planesurface_to_surfaceloop = []
        for jj in range(len(e4)):
            planesurface_to_surfaceloop.append(int(float(e4[jj])))
        SL.append(planesurface_to_surfaceloop)   

    if lineList[ii][0:6]=="Volume":
        f1.append(lineList[ii])
        f2 = f1[-1].split('{')
        f3 = f2[1].split('}')
        f4 = f3[0].split(',')
        surfaceloop_to_volume = []
        for jj in range(len(f4)):
            surfaceloop_to_volume.append(int(float(f4[jj])))
        V.append(surfaceloop_to_volume)   


nb_points,nb_line,nb_lineloop,nb_planesurface,nb_surfaceloop,nb_volume = len(P),len(L),len(LL),len(PS),len(SL),len(V)

## Rewriting the list of lines with the coordinates of the points
## line1 = [point1, point2] becomes line1 = [[x1,y1,z1],[x2,y2,z2]]

L_P = [[]]*len(L)
for ii in range(len(L)):
    L_P[ii] = [[]]*len(L[ii])
    for jj in range(len(L[ii])):
        L_P[ii][jj] = P[L[ii][jj]-1]


liste = [[]]*len(V)


## Rearrangement


for ii in range(len(V)):#for each volume
    listlignes = []
    Vn = V[ii]#the corresponding surface loop list is retrieved

    for jj in range(len(Vn)):#for each surface loop in the volume

        Vnj = Vn[jj]

        SLn = SL[Vnj-1]#we get the list of the corresponding surface plane list

        for kk in range(len(SLn)):#for each plane surface

            SLnk = SLn[kk]

            PSn = PS[SLnk-1]#we get the list of the corresponding line loops

            for mm in range(len(PSn)):#for each ligne loop

                PSnm = PSn[mm]

                LLn = LL[PSnm-1]#we get the correspondign list of lines

                for nn in range(len(LLn)):#for each line

                    LLnn = abs(LLn[nn])

                    Ln = L_P[LLnn-1]#we get the coordinates of the corresponding points

                    listlignes.append(Ln)#points are stored 2 by 2 (line by line)


    liste[ii] = listlignes#all lines are stored for each volume

## Definition of the limits of the graphic reference mark
minX,maxX,minY,maxY,minZ,maxZ = 0,0,0,0,0,0
for ii in range(len(P)):
    if P[ii][0]>maxX:
        maxX = P[ii][0]
    if P[ii][1]>maxY:
        maxY = P[ii][1]
    if P[ii][2]>maxZ:
        maxZ = P[ii][2]
    if P[ii][0]<minX:
        minX = P[ii][0]
    if P[ii][1]<minY:
        minY = P[ii][1]
    if P[ii][2]<minZ:
        minZ = P[ii][2]
MAX = max(maxX,maxY,maxZ)
MIN = min(minX,minY,minZ)

## Colors list
colors_list = [[0,255,255], #aqua
               [227,207,87], #banana
               [0,0,255],#blue
               [138,43,226], #blueviolet
               [255,64,64], #brown1
               [152,245,255], #cadetblue1
               [255,97,3], #cadmiumorange
               [127,255,0], #chartreuse1
               [61,89,171], #cobalt
               [0,100,0],   #darkgreen
               [153,50,204], #darkorchid
               [155,205,155], #darkseagreen3
               [255,20,147], #deeppink1
               [28,134,238], #dodgerblue2
               [255,48,48], #firebrick1
               [34,139,34], #forestgreen
               [112,112,112], #gray44
               [255,105,108], #hotpink
               [238,99,99], #indianred2
               [173,216,230], #lightblue
               [255,255,0]] #yellow1           

## Normalization of RGB values
colors_list_RBG = colors_list
for ii in range(len(colors_list)):
    colors_list_RBG[ii][0] = float(colors_list[ii][0])/255
    colors_list_RBG[ii][1] = float(colors_list[ii][1])/255
    colors_list_RBG[ii][2] = float(colors_list[ii][2])/255

## We store the volumes we want to display   
for ii in range(len(liste)):
    poly2 = Line3DCollection(liste[ii],colors=colors_list_RBG[ii])
    ax.add_collection3d(poly2)

ax.set_xlim(MIN,MAX)
ax.set_ylim(MIN,MAX)
ax.set_zlim(MIN,MAX)

## Display
plt.show ()