I need to plot 3D volumes defined with their surfaces, surfaces defined with line loops, line loops defined with lines, lines defined with points.
Here is an example:
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.sstatic.net/qrvIC.png
I have tried matplotlib and mayavi.mlab plot functions but none worked as I hoped. I also looked for a .geo import function but didn't find one.
These files (.geo files) are exported from SketchUp (Google 3D design software) and are imported in GMesh to create a mesh. In my case I would like to plot my volumes in Python before importing it in Gmesh.
Would someone have an idea to plot this kind of data ?
After few days of works, I got the answer, for displaying edges from a .geo file:
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 ()